Here’s some thoughts on how you should architect your App, based upon discussions between two well-seasoned iOS developers. Let’s jump in!
Model-View-Controller is a very important concept you should adhere to! Don’t be intimidated by the complicated sounding name. All it means is that you should split your responsibilities between 3 broad areas of your code.
Think of it like the company where you work (unless you’re self-employed, in which case you should close your laptop and go surfing now!). Your company should have a marketing department, an accounting department, and an HR department. Whenever anything needs to be done, the appropriate department is responsible for making it happen. That’s the gist of it.
Views are any part of your app that is visible on screen. On iOS, this is easy: UIViews, Xibs, and possibly some helper classes/categories that do display-related things.
Models is your data and core logic of your application. You might consider this your middleware. Managers, Entities, and Service classes fall under this banner.
Controllers are anything that bridges the gap between Views and Models. These are your UIViewControllers, and occasionally some helper classes.
Note: Of course, sometimes you’ll have to bend these guidelines to get things done. Don’t be a hardliner!
A common scenario is that you’ll want to fetch data from the server and display it on screen. In our experience, this is a good way of achieving this:
I’ll explain in detail:
This works well when you may have multiple view controllers who are interested in a common set of data from the same manager. This method will elegantly prevent the multiple view controllers from kicking off multiple loads from the server. This is very important for iPad apps where you’ll likely have multiple view controllers contained on the one screen, eg a UISplitViewController setup.
You may consider simplifying this workflow if eg you will only ever have one view controller querying the manager, common in simpler iPhone apps. In cases like this, you could consider using callbacks instead of KVO.
One issue with the aforementioned architecture is that KVO appears to be unidiomatic in Swift. You need to inherit NSObject
, sprinkle @objc
around the place, and other tricky things to make it work. It appears likely that a future version of Swift will bring us a successor to KVO, but in the meantime here’s what I recommend you consider:
Lets borrow C#’s concept of Events and combine it with Swift’s weak delegates to get a simple effective solution. Basically we’re trying to create a manager which can have multiple weakly-referenced delegates. Here’s how it would look:
/// Since there can be multiple delegates, they can only
/// be used to signifying events (output), not for
/// supplying data for the manager (input).
@objc protocol MyManagerDelegate {
func manager(manager: MyManager, isNowLoading: Bool)
}
@objc class MyManager {
/// Multiple delegates.
let delegates = NSHashTable.weakObjectsHashTable()
// Add a delegate.
func addDelegate(delegate: MyManagerDelegate) {
delegates.addObject(delegate)
}
/// Example of how you'd call the multiple delegates.
private func tellDelegatesIsNowLoading(loading: Bool) {
for object in delegates.allObjects {
let delegate = object as MyManagerDelegate
delegate.manager(self, isNowLoading: loading)
}
}
}
I’ll leave it up to your discretion whether you think the above is worse or better than KVO in Swift. I’ll concede that it is indeed debatable ;)
Update: Better alternatives may be possible.
As for saving your data to ‘disk’, you’ve got a lot of options. From my experience, the good options are as follows: (in order of simple to complicated)
Only you can really decide which of the above are right for your app, as it depends on many factors.
I’d recommend starting with NSCoding for simple apps, moving to YapDatabase if you need further functionality, and Realm if you’ve got a big enterprisey app with a team full of smart people who can handle the complication (eg threading implications) of a proper ORM.
Kudos belongs to Tom from BareFeetWare for the discussion which led to this post!
Thanks for reading! And if you want to get in touch, I'd love to hear from you: chris.hulbert at gmail.
(Comp Sci, Hons - UTS)
Software Developer (Freelancer / Contractor) in Australia.
I have worked at places such as Google, Cochlear, Assembly Payments, News Corp, Fox Sports, NineMSN, FetchTV, Coles, Woolworths, Trust Bank, and Westpac, among others. If you're looking for help developing an iOS app, drop me a line!
Get in touch:
[email protected]
github.com/chrishulbert
linkedin