Best way to load distant data - ios

I'm currently developping an iPhone app and need your opinion.
First, I am developping it for a Football (soccer) Club. It contains many tabs (at least these ones) :
News (Where I am displaying last news posted, obviously)
Shop (Where the user can buy stadium seats, and maybe various goodies)
Don't know yet exactly (But it will be related to Facebook/Twitter or stuff like that)
For every of theses tabs, I need to download XML data (using initWithContentOfURL). Right. But, that's where my problem is. Should I :
Load every needed xml pages at application start-up, and display a nice loading screen ?
Load every needed xml pages at the exact instant the user needs it in the application ?
In the first case, I get a slower application startup, but then, a faster navigation between tabs.
In the second case, my application starts relatively faster (still needs to load News XML, that's the welcome tab), but switching between tabs won't be as fluent as the first case (only the first time the tab is opened, of course).
Any advice?

Take a look at ASIHttpRequest which does provide some pre built caching mechanisms for you that may be appropriate and generally make interacting with web services easier

Load only what you need when you need it.
Furthermore, I wouldn't use initWithContentsOfUrl. It's a synchronous call, and it will lock your app. Instead, use an NSURLConnection to get the data asynchronously.

Related

iOS - Constant listening to database update implementation

I have a project where I have 4 tab bars, and when i switched tabs, my api to get the API request to update my view is in the method viewDidAppear().
However this will make a very bad UX experience for user as whenever they switch tab, a loading icon and some times it load for 0.5 seconds but that instant appearance and disappearance of the loading icon is really bad for UX perspective. How can i implement a view where whenever the database value change, my view is automatically updating itself?
I have thought of using Timer() to implement where it calls the api every second but this is not practical as it will be constantly calling the API every second.
Does anyone have any suggestion? Thank you
There's a lot to unpack here, but I'll try to provide a generalized answer and point to several possible solutions to the UX problem.
There's several aspects that can play a role here:
Do you control the backend the data comes from, i.e. is it possible to follow paiv's comment and implement push notification? Or perhaps use some other means than pure HTTP(S) requests, like a websocket?
How frequently does data change? Is it realistic that it does so in between switching from one tab to another?
On that note, what do you do when data changes while your user is on one tab? Does that get refreshed in any way? Is it a problem if they don't get informed about this immediately? Is there a refresh button?
Do you persist the data beyond a view's on-screen time at all? Is it scrapped when a user re-visits a tab, i.e. does a tab always start "empty" until the API response is handled or do users see the values from the last time they visited that tab?
What best to do depends a lot on the exact answers to these questions. If you cannot enable the backend to do anything besides serving HTTP requests AND have to keep all data up-to-date constantly then obviously you have to do something like the polling you described. The update-interval depends on how important this is for your users. Even if it is 1 second, be aware that this means they could visit a tab before the next update has been fetched.
If you can adapt the backend and up-to-date data is a must, then push notifications or perhaps websockets are a way to go (keep in mind that websockets mean one open-connection per active user then!).
Push notifications would probably break down when the update interval is too high (i.e. if data gets changed in the backend very quickly and you keep spamming them), but would work nicely otherwise, plus they would update views that are already on screen if used correctly.
In 90 % of the cases I've seen, however, going with regular HTTP requests and a properly designed UI is the best choice. Properly decoupling the UI code from the data loading code and the code that displays the data is also very important. Here's how I would handle this:
Properly persist the data in some way in the app that does not require on views owning the data alone. If you want to persist beyond app runtime that means CoreData (or an equivalent), otherwise an in memory storage may be fine (that is kind of a global state then).
In your UI, show any data you currently have, even if it is "outdated" (in your case: "left over from the last time the user was on this tab"). Design the UI so that this is clearly apparent (grey it out, put tiny activity indicators next to the data while it is being loaded anew/updated, or something similar).
As said in 2. do show if the app is loading data. Initiating the loading when the users go to a tab is okay, but don't make a UI that is completely dominated by it (like one giant, empty view with a spinner on it).
Functionally, the loading should not directly update any views, instead it writes new data to your storage and just informs views and view controllers that they need to update themselves (if you're using CoreData and/or Combine you get a lot of this logic basically for free, especially for a SwiftUI app).
Such a design also lends itself to later being adapted for push notifications: While at first the re-loading is triggered by a tab switch (or a "refresh" button, for example), once (silent) PNs are available, they trigger the reloading. Even websockets can be integrated into this more or less, though there's probably a bit more to do that.
In any way, as said it all depends on your use-case and also available resources, but the gist of it is probably "If the current loading icon you have destroys the UX, redesign it properly". My gut feeling here would be that anything else might be over-engineering for your needs...

Using Parse findObjectInBackground() to set up a View in iOS

I'm stuck between two ways of developing my application and am not sure which is best. I was hoping that somebody with a bit more experience or more understanding of Parse could help me.
I am building an iOS app with Swift and using Parse for my back-end. I really enjoy Parse and it's going well.
My question: Say I'm loading a new view. The view is driven by a Parse object, meaning I am setting up Labels, tables, buttons, etc. with data from the object. I load the object in the page load. In this scenario, should I be using the findObjectInBackgroundWithBlock() method? Or should I just be retrieving it, and not moving forward until I do?
Should I just be doing things in the background when the results do not drive the immediate next steps in my code? I am hoping this makes sense. I am running into an issue where if I find an object in the background, then I can't set a label on my view with data from that object until it is found and I have to set it inside the block.
Doesn't this kind of defeat the purpose of finding the data in the background?
The purpose of find data in background is not to block the thread. As I understood you, you have to wait for parse to finish getting all the informations, because you have to create your interface with these informations.
So what I would recommend is that you let the user wait, until the interface is ready. For example with a wait-screen or something like that. Or you block some elements which take some time to load. For example a large tableview takes quite some time to load from parse. Especially if your internetconnection isn't that good.
So you should use findObjectInBackgroundWithBlock whenever possible but only allow the user to access the view, after you've loaded all necessary data to create your view.
What you also could do is do an initial access to parse. So that you set everything up at app-start. That way, you don't have to bother the user later and the user has to wait only one time at the start of your application(or If he wants to reload the tableview. for example)

(Xcode, Swift) Is it possible to load multiple WKWebViews simultaneously if they are on different viewControllers?

I have 4 viewControllers that all have different WKWebViews. When the user starts up the app and sees the first viewController, I want the WKWebViews of the other viewControllers to load in the background so that the app will seem more seamless when switching from viewController to viewController.
Is this possible? Or would I have to put all the webViews in one viewController?
Nearly all of the delay that you're trying to avoid is due to downloading the data; instantiating a web view once the data is available is fast enough that users won't notice any delay. Given that, what you should really be looking to do is to download the data, not instantiate more web views than you need. The question that BJHStudios suggested in a comment provides a couple options for this, but you should look at NSURLSession rather than NSURLConnection; NSURLSession is very easy to use and offers a lot of flexibility. For example, you can configure a session to download data when the app is inactive.
If your app makes use of a data model, you could incorporate the web resources required by each of the four view controllers into the model. When your app starts up, it would naturally instantiate the model, and the model would then retrieve the necessary resources so that they'd be immediately available for display when needed.

Use of Global Model in ios APp

I am designing an app which manages a tank of hot water. The app makes RESTful API calls to a service to;
Obtain a profile of temperature at various layers in the tank.
Allow a user to work with a timer (like an immersion timer) custom control to set times to turn on/off heating elements.
So, as a first cut, I have two tabs in a nav controller;
1. A graphic, showing a picture of the tank, graduated to show temperature.
2. A custom control, like commercial domestic timers, with two concentric rings, allowing the user to point, and drag 30 minute slots to set times for heating elements.
I have both custom views working well. I'm afraid to say I'm stuck on a very simple point - even after reading all of Apple's ios docs, and would love some help.
The data server (A BeagleBone running embedded Linux) implements 2 sets of RESTful APIs, one dealing with tank temps, and the other set to read and to update timers.
Is it best to start the App with a view controller which instantiates a model, who issues the APIs, and displays "Loading...", then populate a single application wide data model.
Have each view controller (The image of the tank, and the timer controller) to populate their own (separate) model?
And the big question for me (despite years of working in Smalltalk, C++, Java...) what is the recommended way to ;
instantiate a view controller
load / display a view with a "busy"spinner if the model hasn't loaded
My app isn't complicated enough for GCD, or indeed KVO. This is basically, a "show a view, call a web service to read the data", "modify the data", "call a web service to replace the data"
Basically, I believe my question is, when a view comes on screen, what is best practice to determine that the controller has a model, or has a model which is still loading data?
Sorry for the long winded question.
You asked a very good question, about a very common task in an mobile app. My suggestions are
Since your two tabs really have no common data, the problem simply boils down to "how to initialize a view controller with remote data".
If user can't use your app without remote data,
simply show a loading view in [vc viewDidLoad], and start fetching data from server asynchronously; your vc should implement NSURLConnectionDelegate to listen to call back
when data is successfully fetched from server, dismiss the loading view, and render the data to user
if data fetch failed (due to bad network or server downtime), show alert view to user, and retry the data fetching; if fetching fails for several times, tell user to try again later
you can make the loading view more beautiful, to provide a better user experience; note the loading view should cover all the buttons/controls, so user can't mess up your app state during data fetching
If user can use your app without remote data, it's another story. You shouldn't use a loading view in that case, and should silently fetch data in background. Since this does not seem to be your case, I will not complicate the answer by this case.

IOS Saving State For Complex Apps

I'm building a fairly complex business application on the iPad IOS 4.2: 4 tabs, with potentially deep navigational paths on each tab.
In the opinion of some of your more experienced IOS developers, what would the general expectation of a user be with respect to saving application state between launches (i.e. after an app's been fully terminated and subsequently restarted)? I'm using Core Data and have all the data issues covered, but I'm concerned about the application's navigational tree. If the user had left the 1st tab on screen 3, the 2nd tab on screen 4, the third on screen 2, where he left the entry of a new record half-complete, and was, at the time of the app entering the background, working on the 4th tab on screen 3...do you think the average user would expect the application to remember all that the next time it launched? (My gut says yes, though I'm unsure for how long.)
If the answer is yes, can you suggest a general strategy for handling this (and, again, I'm talking about the navigational tree here, not Core Data stuff)? For example, if navigational controllers were used as the root view controller for each tab, it would be simple enough to record enough info about their navigational stacks to be able to restore them later. But what about things like popovers, alert/action sheets, or modal VCs created on the fly? Should each view controller record the state of its UI objects and, if so, what is the recommended way to do this?
I know a lot of this is up to the user, but I'm asking for the general perspective on these issues, i.e. the voice of experience.
It's pretty simple in principle, but it can get quite complex in practice, to go through your navigation hierarchy and storing stuff that can't be derived from the data model.
There's an open source implementation of this called DTResurectionKit. I also documented how I do it in my apps on my website. It's similar to (but simpler than) DTResurectionKit.
In the opinion of some of your more experienced IOS developers, what would the general expectation of a user be with respect to saving application state between launches?
The best way to think about this is to make sure the user never has to figure out why or how they got to where they are when the app first opens.
This depends completely on the type of app you have and the length of time since the last open. It sounds like you have a fairly complex drill-down app so I think it is definitely best to remember the navigation stack, within a pre-determined time frame. I use the three20 framework which does this automatically for me, but if you were to implement it, it would be something like this:
If the user opens up in the past 24 hours, open to the exact spot the left off
If the user opens within a week, open to the main "section" or area of the app they were in
If the user opens after a week has past, open to the root screen.
Now of course, these values will differ based on your apps function and use cases, but you get the idea. By you making some broad assumptions about how people are using your app and when, you can increase the user experience by not shoving them so deep in your app when they won't remember how they got there.
As for implementation, it is all just data.. You dont need to serialize live objects to store the stack, just implement the data needed to recreate the state on the next launch. What you need to store is highly dependent on your own setup... mileage will vary. I use NSUserDefaults to store all instance vars and the navigational stack through Three20. Check out TTNavigator for a great implementation.
I would suggest keeping the state of each tab view. Only at the "page" level. Don't worry about popovers or incomplete data entry (hopefully there's not too much interim state before you're saving it to your core data store.)
Like you said, it's easy enough to remember what tab you're on, and what controller you're navigated to in each tab. More isn't necessary.
It sounds like you've got it under control, but for the benefit of others: 1) when you change tabs, save "active tab", 2) when you navigate within a tab, save "active controller in tab", 3) when you launch the app, set the "active tab", 4) when you change tabs, set/confirm the "active controller in tab".
The reason for 4) is that the view/controllers for the tabs will be delayed in their loading, or perhaps never loaded. You don't want to set the "active controller in tab" for a tab that is not visible and may never be loaded into the app, it would just cause unnecessary loading. It will often happen (after the app has been loaded) that you don't need to change it because it's already in the correct state.
I think your time is better spent elsewhere. Of course, your app might be perfectly suited for this, but in our case data was partly online, could have gone stale, influenced view state in different navigation views in different tabs simultaneously, etc. etc. It's not an insurmountable challenge, but definitely hard and a huge time-sink.
We decided to spend our time on fixing the bugs and improving functionality. If you have to make the same kind of choice, I'm pretty sure which option your users would prefer. Particularly now that your app will survive a phone call in the background.

Resources