I started iOS as a 2-year-experience .NET developer. The salary range for a junior iOS dev is a little bit lower than the amount for a 2-year-experience develop get. I wanted to make myself stronger, earn more experience. I had a misconception of working and learning. I thought, freelance projects will help me strengthen my knowledge and experience. So I tried to get as more as possible freelance projects. And my nightmare started from here.
I had no time to spend with my family, no time to work on personal improvement, no time to go out with friends, no time at all. All of my time was used up on my freelance work from coding new features, fixing bugs and much more. I was killing myself working odd hours and missing out on quality time with my family and friends.
I made a mess, uncountable technical debts, bugs, with the project. I was angry with everyone and myself. And the company project was affected. I brought more bugs there, dozens of stupid bugs, critical bugs.
Finally, after lots of stress situations, I found a way to get myself out of these nightmares.
You're developer, and you understand clearly about the pressure in development. I'm sure you want to get some freelance projects to earn more money. So, you should try my solution to manage your time effectively.
You're developer, and you have to work OT. Too many tasks you have and you have no enough time for work. No time for family, no time for your life, no time at all. My solution can help you get out of your situation.
This solution is about how to change the way I work, how to manage time effectively. It's absolutely right for me, and helps me out of the shit situations, boost my career, make my life better. Is it good to try yourself?
This solution has 2 parts:
- Life skills: something you need to change in your life, how you work, how you enjoy your life...
- Tech skills: 4 tips for iOS developers to work faster, better, and save time.
You have to spend at least 8 hours a day for working at your office. The manager says, "We have no time, we have to work OT". Yes, it's a extremely bad solution. Your brain, your body is drained. And now, you force it work more hard. Do you really think you can work effectively after 8 hours working? No, you don't. You know, your colleagues know, but the manager doesn't know.
It's too hard to decline working OT, but you should do. You have to do unless you make more bugs and everything is worse.
One time, I had to work until 8.30 pm, without dinner, just some instance noodle. Went home, went to bed and 11.30pm, got a call.
"What the hell are you doing? Something is wrong with the promotion".
OK, turned my Macbook on and worked like a dead guy.
Many times like that, and the project had shit quality. I can't believe I can do but, but I did, no choice.
The firs thing in my solution, is to switch up working hours. I decline all OT and try to work better, work more in my ideal time to finish more tasks or fix more bugs.
The ideal time for working, for me, is 2am after 3 to 4 hours of sleeping, maybe different from you. This time is ideal because everything is quiet and there are absolutely no distractions. No phone calls, no email, no one bothers you. For me, this is the best time to get my creative juices flowing.
It's exactly same to freelance projects. You can achieve better results than work after office time.
It's hard to start at all, but try it yourself and experience amazing results.
Most importantly, a healthy body is the key to reach success. I have to work 8 hours everyday in an office and an additional 4-6 hours on freelance projects. If you do the math, my body has to work 1.5 times more than usual. Crazy, right? For most people, their body and mind will become exhausted very quickly with a schedule like this. In order for me to prevent myself from becoming ill, I make a conscious effort to include additional nutrition in my meals with more fruits, protein, etc.
In additional to a healthy diet, it’s important to stay active.I try to incorporate a little bit of exercise into my daily activities. For example, I use the stairs instead of the elevator, I try to walk faster, clean the floor manually, and more. Now, I know these types of activities won’t help me become an athlete, but every little bit helps to keep my health up.
You can make more evil bugs when you're not healthy. And you waste double time to fix what you did when you're not healthy. So, keep up your health and make good things for your code.
Freelance projects are very good for expanding your experience. You have many projects to fill into your CV. You can earn more money. It's great. But they're not good to your knowledge. Freelance projects are useful when you have strong experience and want to strengthen them. But it's a bad choice for learning because of pressure.
When you're in a freelance projects, you have many pressure about time limit, money, client attitude... And you just want to make it done, not want to understand how it work and how to make it better. It's harmful for you. You think you have experience with it, CoreData for instance, and you apply for new projects with CoreData require. You run into a big bugs and take lots of time to understand to fix that.
Side projects are better choice. You can research new technologies, try new hot things in new iOS, SiriKit, HealthKit for instance. Don't forget to publish some side projects. They can help you to show off for your clients or your interviewer.
You also practice or strengthen your weakness in iOS with side projects. With these projects, you learn a lot and be confident to apply new projects.
Don't think about money first, think about yourself, Make yourself better and money comes.
Code Snippets is your template codes. You don't want to type all the code or copy it from somewhere. Just type some first characters and select it from suggestion list. For instance, I usually type “button”, and XCode will give me this:
Easy, right? You don't want to type boring code anymore.
Don't forget use <# and #> with the placeholder text in the middle. Go ahead—try typing that into Xcode, and watch as the text between the octothorp tags magically transforms right in front of your eyes.
You can try my snippets at by copy and paste to ~/Library/Developer/Xcode/UserData/CodeSnippets/
Small things but very useful.
It works like an external library, nearly same to Pods but in free way.
Situation like this. You finished a cool animation in company project. It’s really cool and you want to use it in your current freelance project. You copy this code to the freelance project, change something and let it work like a charm. But, you find something can be better in this code. You make changes, and want this change be applied in the company project. You copy this code again. Imagine you have more 2 projects, use this animation. It’s a nightmare.
Knowledge base is good choice for you. Create your own knowledge base in Github, clone to your projects. Add new features, change some if needed. Push to Github and pull it from other projects. All your projects can get the latest update easily. Cool, right?
- Clone your knowledge base to every project to avoid some unpredictable situations. Some changes in this project can make consequence to others projects, and it takes you lots of time to find out the cause.
- Add your knowledge base to .gitignore. Without this step, you will commit your changes into Github with an unrelated commit message. Or you can make some unexpected commit and your knowledge base become a mess.
- Run test for your code and make sure it works good before commit.
- Should use
branch
to manage your base.
Because CocoaPods need to release on Github. But these pieces of code change continuously, new code, new update, remove redundant code.
This is a popular war for many iOS developers. Storyboard fans think this is stupid thing. Programmatically guys fight for their belief.
This is opinion from a developer can't live without Storyboard, and now he abandons it. It's me :)
Auto Layout programmatically saves your time and your life.
My situation is a good example. I designed a very good UI, and connected outlet, started logic coding, finished that feature. One day, I had to refactor code and found some improvement. Some UILabel
had gestures, should be changed to UIButton
. No problem, made changes. What did I do?
- Found the
UILabel
need change
- Delete one by one.
- Add new
UIButton
- Connect new outlets
- Setup Auto Layout constraints. (This is most painful step, dozens of constraints need setup)
- Find and change many things in code
And when I changed to Auto Layout programmatically:
- Found the
UILabel
need change
- Change
UILabel
toUIButton
- Find and change many things in code
Easier a lot, right? Especially, no change in setting up constraints.
Another advantage is to customize controls with Auto Layout programmatically. You can make any custom controls with programmatically, but you can't do that with Storyboard.
If you use Storyboard (I mean Xib file), you can make a view, and copy 2 files, NewTextField.xib
and NewTextField.swift
to your knowledge base. And you want to change it name to MyAwesomeTextField
, you have to change 4 times, the 2 files' name, class' name, and the subclass' name in xib. Never happen in Programmatically.
And my favorite library is knConstraints, an project learned style from TinyConstraints, developed with a new syntax and more advantages.
VIP Architecture is a complex topic. You should view the talk about it at https://github.com/swift-vietnam/iOS-Awesome-Starter-Kit
In my post, I only talk about how to use it quickly.
My example code shows you how to select a photo for profile image. You can do it easily in another way. But in this way, you can easier manage your code and reuse it anywhere.
Move on step by step
-
In your controller, define new variable
var output : SampleControllerOutput?
-
New file and add below code:
// (1) - Define actions controller needs in protocol SampleControllerOutput protocol SampleControllerOutput: class { /* action from controller */ func getProfile() } // (2) - Define actions to respond to result in protocol 'SampleInteractorOutput'. For instance: requestSuccess, updateView... protocol SampleInteractorOutput: class { func getProfileSuccess(profile: UserProfile) func getProfileFail(err: Error) } // (3) - Conform actions from 'SampleControllerOutput' in 'extension SampleInteractor' extension SampleInteractor: SampleControllerOutput { func getProfile() { GGetProfileWorker(id: id, successResponse: output?.fetchProfileSuccess, failResponse: output?.fetchProfileFail) .execute() } } // (4) - Conform actions from 'SampleInteractorOutput' extension SamplePresenter: SampleInteractorOutput { func getProfileFail(err: Error) { output?.showGetProfileFailError(err: err) } func getProfileSuccess(profile: UserProfile) { output?.showUserProfile(profile: profile) } } // (5) - Define actions to update directly to UI to 'SamplePresenterOutput' protocol SamplePresenterOutput: class { func showUserProfile(profile: UserProfile) func showGetProfileFailError(err: Error) } // (6) - Update UI extension SampleController: SamplePresenterOutput { func showGetProfileFailError(err: Error) { } func showUserProfile(profile: UserProfile) { // update view } } /* (7) - It's set up. Don't need to care about it. */ class SampleInteractor { var output: SampleInteractorOutput? } class SamplePresenter { weak var output: SamplePresenterOutput? } //MARK: Configuration class SampleConfiguration /* called in viewDidLoad */ { static let shared = SampleConfiguration() func configure(viewController: SampleController) { // Presenter let presenter = SamplePresenter() presenter.output = viewController // Interactor let interactor = SampleInteractor() interactor.output = presenter // View controller viewController.output = interactor } }
(1) - You define actions your controller need to do. For example: getProfile, updateProfile, viewDetail... (2) - Define what happen when the actions from controller finish. For example: getProfileSuccess, getProfileFail... (3) - This is the execute space. Conform the actions you defined for controller before, and let worker execute the action.
How does the worker look like?
struct GetUserProfile {
private let api = "/workshops/"
var id: Int
var successResponse: ((_ something: UserProfile) -> Void)? = nil
var failResponse: ((_ error: Error) -> Void)? = nil
func execute() {
// connect to server
}
}
(4) - Response to result will be here. You should change the model data to new data, which can easily set to your view. For example, change Date to String, so that you just set to your view, no need to convert Date to String in your controller.
(5), (6) - Actions to update to controller.
(7) - These code is ready to use. It's always same for other controllers. You just need to change the prefix name, Sample
to your feature name.
How to use?
In your controller, viewDidLoad
, call SampleConfiguration.shared.config
. And call output
to do your actions.
This solution saves much time for me. I hope it can help you. Save time, work better and enjoy your life.