Preload data from xml, table view doesn't reload - ios

I have following problem. In my app I'm downloading .xml file from server and then parsing it. I call both methods (get and parse) from application:willFinnishLaunchingWithOptions.
Right after parsing is posted notification. In main table view controller is observer and selector is supposed to reload table view. But it doesn't. ViewDidLoad in TVC is called before parsing is completed, also before launching screen disappears.
So my question is: Is possible to freeze application:didFinishLaunchingWithOption till all data are parsed? Thanks

No its not possible. What you could do:
Don't show your TVC. Show a loading Controller. This Controller will do the work with loading the data and parsing it. When its done you can call your TVC
For Example:
LoadingController has a instance of a Manager Class
The Manager downloads your file. ( Extra Communicator or something else)
Your provide success and failure blocks to the manager calls. Means, build a function with func downloadXML(success: blockStuff, failure: blockstuff). In the success your provide the parsing
When parsing is finished you show your TBV with the data
Feel free to ask or comment :)

Related

Scrolling tableview while updating its datasource fetched from CoreData crash

Here is my context:
When I launch my app I fetch local data from CoreData and fill a tableview with it. At the same time I send an asynchronous request to my webservice to fetch what will be the new content of my tableview.
As soon as the request sends me a response I delete all the instances of the current NSManagedObjects and create new ones with the new data I got. Then I replace the datasource of my tableview to an array of the new NSManagedObjectContexts instances.
My problem:
I'm getting an error : CoreData could not fulfill a fault for ... if I scroll my tableview when the request finished and is triggering the deletion/creation of my tableview's data source.
I understand that this problem occurs because I'm trying to access an old NSManagedObject instance while doesn't exist anymore as it is explained in the doc : Apple doc. But I have no idea of what are the best practices in my case.
I don't want to block the user until my request finished but I have to prevent any error if he accesses "old" data while the request didn't finish (e.g : what if the user taps on a cell and I pass an instance of an NSManagedObject to another viewcontroller but when the request finishes this object doesn't exist anymore ?)
I would appreciate any help !
I highly recommend you to use NSFetchedResultsController since it's sole purpuse is:
You use a fetched results controller to efficiently manage the results returned from a Core Data fetch request to provide data for a UITableView object.
When using a fetched results controller it is much easier to handle the Core Data events like insert, delete, update.
You say you have three sections in your table view? That's no problem, NSFetchedResultsController can handle all of that.
Take a look at this. Apple provides a very nice set of instructions on how to configure and use NSFetchedResultsController.

Init object with asynchronously downloaded data

I have an object that needs to be initialised with data from network and doesn't really make sense without the downloaded data. But it seems to me that doing an asynchronous network call in its init method is not a good idea because the object will not be ready to user right away and it might cause confusion. Should I only use a basic init method that will alloc init all its properties to create an empty object, and have other (non-init) methods populate the data from the network which will be called explicitly by other objects (such as the view controller using this object)? What would be a good way to approach this?
I think that the solution comes from having the right order of code running:
1) Go to network and fetch data (show the user acivity indicator in this time)
2) Server return response -> fetch the response into your object
3) Show the data or use it

Asynchronous Data Download Procedural Break

Following up with the post: Can AFNetworking return data synchronously (inside a block)?
One of the comments in that post was:
The trick to asynchronous programming is to break the procedural,
synchronous assumption that data is there when you ask for it.
Instead, with async, when you ask for something, you give it a
callback to perform when the data finally is ready. In this case, you
would call the block in the success block of the JSON operation.
Rather than the method returning data, it's told what to do when the
data is finished downloaded.
Although I'm using GCD and asynchronous downloading on iOS, I do not really understand how to implement this "procedural break" when programming with async.
For example, assume I need to download some JSON data, which includes lots of data including an image URL. I will have to download the actual image afterwards.
Each cell in the table takes in the data from the JSON/images downloaded. How would I implement this procedural break in this case?
While your data has not arrived, your table view dataSource tells its table view that it has zero rows, and displays a spinner. When the callback is fired, you store the data somewhere, remove the spinner, and call [tableView reloadData]. Basically, that's all there is to it.

iOS Managing Async Blocks for Remote Requests

Not sure how to best explain this - If I use blocks to load images for UITableViewCells, how best can I ensure that when an image actually finishes loading - it is the correct image for the cell. Say I'm making an app with user icons - so cell 5 is for John and it starts loading John's image. Say that request gets hung up and by the time it returns, that cell has been reused for Bill at cell 23. We obviously don't want to load John's icon - we just want Bill's.
This is a simplified explanation. I know that we can check if a cell is visible in the block before setting the image - but say in a different scenario I have a method that makes a remote request when called. When the remote request is done, it calls a block defined in that method that updates the UI. If I call it and before it returns I call it again and only want the most recent call's block executed. Is there a good pattern for doing this?
Currently, I try to store a variable that has some state in the method so that when it returns I can check if that state is still valid. Just thought I'd see if there was a better way. Thanks.
Just checking if any updates on this.

iOS: Running database query in viewDidLoad only works once

So let's see if I can write a clear enough description of my problem...
I'm developing an application for a museum, where the user can find artworks either through an id or by scanning a qr tag...
Once either an id is entered or a tag scanned, the application sends the user from the search view, to the info view.
The info view gathers information about the artwork from an SQLite database...
My problem is, that in the info view, I call the function from the database class as such:
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *paintingInfo = [[PaintingDatabase database] findPaintingByID];
(additional code)
}
And I have no problem getting the info... works fine...
But my problem is, that if I go back to the search view and enter a new id or scan a new tag, the call/search isn't run again, since the view is still in memory...
So, how would I go about running
NSArray *paintingInfo = [[PaintingDatabase database] findPaintingByID];
every time I enter the view...?
I've tried placing it in viewDidAppear instead, but I get an EXC_BAD_ACCESS error...
I think you are close to answering your own question. Since viewDidLoad only gets called when your view loads, if you are using the same ViewController you will not get the results you are looking for. One option may be to destroy and create a new ViewController each time. This probably would be acceptable, performance-wise. Another option (that you seem to have explored) is to put your code in viewWillAppear. I would probably look into this more, and figure out what is causing your crash.
It's a bit difficult to tell from a brief description, but this feels to me like it's more of an application architecture issue than a problem with a specific bit of functionality.
You might be better off with an alternative approach, running the query from outside the info view, and then update the properties of the view through a delegate method. That's more of an MVC approach - the controller retrieves the data from the model, then passes the data over to the view to be displayed.
As you've described it, it seems like your info view is taking both view and controller functions - which could be why you're running into problems trying to get different data once the initial view is finished with.
The crash doesn't sound like a problem with the view, though - I'd second the advice to track that down and nail it as a separate issue.

Resources