Complex Startup Logic in iOS Apps: Where Should it Reside? - ios

Everyone has seen the classic didFinishLaunchingMethod run amok.
Well now that we have additional things to consult when starting up like CloudKit, that are, to make things worse, asynchronous, the app delegate seems like the wrong place to do even the most basic stuff like asking if they have accounts and establishing syncing, or grabbing a snapshot.
I hate the idea that those things would go into the first controller that the app would launch, flashes me back to 4GL tinkertoys from days of yore.
Yet, we have to honor the flows of the storyboards. I have found nothing searching around on this. And sadly the most extensive Apple example, Lister, is not a great source for best practices.

It's suitable for the app delegate to trigger the start of this work, but not to handle the results. Often you want some way to display progress / errors / request user info. So, having some form of 'splash' view controller which handles the transition from your launch image into this process and controls the flow into the main app is handy. Generally the logic for this kind of thing is reusable in other situations so that part should be in some other controller class. The storyboard can make the splash VC the initial controller and the app delegate can create and pass it the data controller class which deals with the logic and updates the VC (it's delegate) with the results. Often the splash VC will then pass the data controller on to the subsequent VC it displays, though that isn't required of course.

Related

Is it recommended to destroy UIViewController after finishing your work with them

I'm an Android developer, I started learning iOS development lately and I've been wondering about how to manage the UIViewControllers.
In Android, when you don't need an activity anymore, it is better to remove it from the application stack, for example a login screen is only needed when the user logs in, after that there is no need for that screen so it is better to destroy it and remove it from the stack, but what about iOS? Do you have to manage view controllers the same way as activities? or does the system automatically handle the views in the background?
It would be great if you can link some reference to read more about the way View-controllers are handled in the background, I'm trying to learn the best practices
Short answer: No, let ARC handle it
ARC handles the release from memory automatically when you pop a view from a navigation stack, so if you go "back" (pop) you normally don't need to worry about it.
But, sometimes you have a big navigation stacks with many different views with a lot of data/images/etc that will eat memory. In those cases you could separate your app into different flows and instead replace the root view controller of the main window with the new flow every time you want to change. The old flow should be released from memory automatically, unless its connected to another object (like a singleton).

How to customize Apple CareKit?

In CareKit there are Care Card and Symptom tracker. I'm not understanding how to customize Carecardviewcontroller and symptomtrackerviewcontroller. I don't want to use these view controllers but interested in using components of these view controllers. there is no clear documentation to explore this.
(source: carekit.org)
If you are coming at this from a Swift perspective, then it has to be admitted that CareKit is about as "un-Swifty" as anything you can imagine. The GitHub site is certainly a start, but there is a horrific gap between reading the programming guides there and actually implementing a solution. It certainly has been a long slog for me!
That said, you can add customization to CareKit's story-board-free approach by using the view controller delegate functions that CareKit provides.
For example, suppose you have an app that reminds your user to perform two intervention activities, (1) take aspirin and (2) go for a brisk walk. If the user opens the Care Card and taps an event icon (one of the circles) for "take aspirin" then that will fire a method in the OCKCareCardViewControllerDelegate called:
careCardViewController(_ viewController: OCKCareCardViewController,
didSelectButtonWithInterventionEvent: OCKCarePlanEvent)
In this method you can segue to whatever view controller you'd like. E.g. if the event is for taking aspirin then display a view controller that shows a photo of an aspirin table, a reminder that it should contain just an 81 mg dose, and a recommendation about taking it with water.
Of course, nothing is ever easy with CareKit. It turns out that you will probably also want to turn off CareKit's standard practice of calling an event completed if the circle icon is tapped. That is accomplished by returning "false" from another delegate method called:
careCardViewController( _ viewController: OCKCareCardViewController,
shouldHandleEventCompletionFor
interventionActivity: OCKCarePlanActivity )
-> Bool
There is a book called Beginning CareKit Development that I can cautiously recommend. It was written for an earlier version of Swift and you have to do a lot of "translation" to get things to work with Swift 3. The last time I checked the GitHub repository for the code associated with the book was also entirely in this earlier version. APress will provide the code updated to Swift 3 if you ask. On the Kindle there are numerous little glitches with the book, including an index that has no page numbers nor hyperlinks to the associated text, very odd formatting choices that make the text sometimes hard to distinguish from code, and occasional errors in the solution code. All that said, I doubt that I'd have made any progress with CareKit without the book's help.
I've been looking for this answer myself.
As far as I researched, you can customize this screen visually with UIAppearance.
AND/OR you can create a new screen like this one from scratch using its behavior.
You can check the CareKit source code for hints on this: https://github.com/carekit-apple/CareKit/tree/master/CareKit/CareCard
There you'll notice some interesting classes/files:
OCKCareCardWeekView
OCKWeekLabelsView
OCKHeartView
OCKHeartButton
OCKWeekViewController
OCKHelpers
CareKit draws each screen via code. You can see how they do it by reading the code.
The idea is to create your own ViewController with these pieces, or one from scratch.
Surely it's not as trivial as just using CareCardViewController, but this will get you there.

closing out modal view completely ios

I have a messaging system, theres a inbox view and a viewmessage view, if i go back to the inbox im still reciving data from that message, and if i load another conversation between me ad another user its still loading the previous conversation data i had (verified by logging the convo's, and the new one i have open, and its a continuous loop so to say... basically im trying to figure out how to totally close out a view... i seen dissmissViewController and used that, but all it does is visually make the view go away... it doesn't truly close it.. whats the method to call to do what im trying to achieve?
These are all modal views, my app uses no navigation views due to the nature of the app
edit: i found some great documentation that im going to look over hopefully i'll get my answer from there.
Using Delegation to Communicate with Other Controllers

can my app delegate be used as a controller of UIViewControllers (MVC)

Can an app delegate act the as the glue between all my UIViewControllers for the whole app?
I'm creating a mail client that has a navigation structure very much like sparrow (and fb etc). The first screen would be a login screen.. which would then lead to a UITableViewController that has the famous left menu button, which if clicked reveales other VC's underneath.
To make a long story short, right now it's my app delegate that's running the show.. it's the one that decides if to show the login screen if on first visit, or the default mailbox along with its subviews. If I get information from one subview, it hands off that info to the app delegate, which in turn passes it on to other view controllers.
Is this right from an MVC point of view? I know an app delegate is the first point of contact, it's what kicks off the application, but I haven't seen it used this extensively. I just want to make sure if I'm following iOS MVC best practices here.
It's not recommended, but it's perfectly legal to do that. I generally use a master view controller class and do most of the heavy lifting in that. Keep in mind that XCode will dump most of the auto generated code in the app delegate if you are using Core Data, so it can get a little difficult to navigate if you are using Core Data. It's really just a personal preference though. If it were me, I would still have the app delegate do the login screen vs. main screen logic, but put most of the app logic in a main screen controller.

Progressively load subviews to speed up iOS app performance

I'm looking for a technique to progressively load in the contents of a UIViewController to make an app feel "snappier". I noticed this issue when pushing a viewcontroller onto the stack there's a noticeable delay while waiting for it to push in. The UIViewController's View has some complex subviews with transparency. I'm wondering if I create them after viewDidAppear and 'fade' them in, then the transition will appear much smoother.
I noticed a similar effect in Apple's Trailers app. When tapping a movie in that app the detail view pushes in and the contents load after the fact. Granted part of that delay is because they are downloading the details before showing them, but it seems like they always fadein that large image whether it's been downloaded already or not.
Has anyone had much success with this or with improving UIViewController loads in general.
Before you start making changes in an effort to improve performance, use Instruments to profile your app and find out where the problem really is. Is it in drawing the complex subviews? Is it in loading the data? The only way to know is to measure.
There's no reason you couldn't do as you propose -- have the view controller create/load its main view and then add the complex subviews afterward. Your view controller can add and remove subviews at will. Will that make the app feel snappier? It might -- it's similar to the default image strategy Apple built into iOS, where the OS loads a picture of your interface to make the device seem responsive, and then substitutes the real interface once that's ready. On the other hand, if the user still has to wait for the complex subviews to be created before the view is useful, seeing the rest of the view might not help much.
Another possibility (again, after measuring) might be to create the views before the user needs them. This runs counter to the lazy initialization that iOS apps commonly use to conserve memory and power, but if you know that you're going to need the views and you can expect a lull in user activity before they're needed, it could be a good way to increase the app's apparent speed. All you need to do to get a view controller to create/load its view is to access its view property.

Resources