networkActivityIndicatorVisible logic issue - ios

so my application connects to a URL (via URLConnectionDelegate), gathers data, which contains image URLs. It then connects to each and every image url (again, via URLConnectionDelegate), and gathers the images for each image.
Everything works perfect, couldn't be happier.
But the problem is that I can't really track the networkActivityIndicator. There are like, 100 connections going off at once, so I don't know when or how to set the networkActivityIndicator to turn off once the last image is done loading.
Does anyone have any suggestions without me having to redo a bunch of code?
Thanks for the help guys

The typical solution is a singleton object that you call [NetworkMonitor increaseNetworkCount] and [NetworkMonitor decreaseNetworkCount] at the appropriate points.
The nicer solution is a toolkit like MKNetworkKit, which will handle this and a bunch of similar things for you (like managing your download queue, since 100 simultaneous connections is actually very bad on iOS).

Related

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)

Alamofire Priority Queue

I am using Alamofire as my networking library for my Swift app. Is there a way to keep a "priority queue" of network requests with Alamofire? I believe I saw this feature in a library in the past but I can no longer find it or find other posts about this.
Let's say I open a page in my application and it starts to make a few requests. First it gets some JSON, which is fast and no problem.
From that JSON, it pulls out some information and then starts downloading images. These images have the potential to be quite large and take many seconds (~30 seconds or more sometimes). But the tricky part is that the user has the option to move on to the next page before the image(s) finish downloading.
If the user moves on to the next page before the image downloading is done, is it possible to move it on to a lower priority queue? So that when the images on the next page start loading they will go faster? I would even be open to pausing the old one entirely until the new requests are finished if that is even possible.
Keep in mind I am open to many suggestions. I have a lot of freedom with my implementation. So if this is a different library, or different mechanism in iOS that is fine. Even if I continue to use Alamofire for JSON and do all my image downloading and management with something else that would be alright too.
Also, probably irrelevant but I will add it here. I'm using https://github.com/rs/SDWebImage for caching my images once they're fully downloaded. Which is why I don't want to cancel the request completely. I need it to finish and then it won't happen again.
TL;DR I want a fast queue and a slow queue with the ability to move things from the fast queue to the slow queue before they are finished.
Have you considered managing a NSOperationQueue? This tutorial might be helpful. In his example, he pauses the downloads as they scroll off the page, but I believe you could adjust the queuePriority property of the NSOperation objects instead.

Passing object/NSData between iOS devices

I'm creating a game, turn based, and I was thinking of using Game Center to handle it, but the passed game-object is evidently max 64kb. Is there another way to pass objects between devices for this use, without having to create a database or storage-server as middle man? The game-object itself for me is probably a lot less than 64kb, but there are some initial variables I would like to send, such as images. With my calculations, the initial data for one game is about 500kb, but after getting those images once, the passed game object is just a couple of kb's, and are never going to include those images again.
Is there a way to send these images directly?
There are a few ways to get around the limit.
This answer mentions Alljoyn which would allow you to transfer that size of files.
You could also send them indirectly by transferring them to your own server, then passing a link to the file to the other player. For a turn based game, this would have good advantages of enhanced reliability as you could put in retries on error for both the upload to the server and the download to the device and control it yourself. I would recommend AFHTTPClient for this, also.
Is there another way to pass objects between devices for this use, without having to create a database or storage-server as middle man?
Without your own server, there isn't.

How to do UITableView operation queues to download concurrently

I am doing a UITableview to download data
the name webservice is very fast, so I use it to populate the table initially, then I start an operation queue for the image.
Then a seperate queue for the rest of data because it loads very slow but that effects the image load time, How can I do the 2 concurrently.
Can you figure out whats slowing the performance there and help me fix it?
As I assume you know, you can specify how many concurrent requests by setting maxConcurrentOperationCount when you create your queue. Four is a typical value.
self.imageDownloadingQueue.maxConcurrentOperationCount = 4;
The thing is, you can't go much larger than that (due to both iOS restrictions and some server restrictions). Perhaps 5, but no larger than that.
Personally, I wouldn't use up the limited number of max concurrent operations returning the text values. I'd retrieve all of those up front. You do lazy loading of images because they're so large, but text entries are so small that the overhead of doing separate network requests starts to impose its own performance penalties. If you are going to do lazy loading of the descriptions, I'd download them in batches of 50 or 100 or so.
Looking at your source code, at a very minimum, you're making twice as many JSON requests as you should (you're retrieving the same JSON in getAnimalRank and getAnimalType). But you really should just alter that initial JSON request to return everything you need, the name, the rank, the type, the URL (but not the image itself). Then in a single call, you get everything you need (except the images, which we'll retrieve asynchronously, and which your server is delivery plenty fast for the UX). And if you decide to keep the individual requests for the rank/type/url, you need to take a look at your server code, because there's no legitimate reason that shouldn't come back instantaneously, and it's currently really slow. But, as I said, you really should just return all of that in the initial JSON request, and your user interface will be remarkably faster.
One final point: You're using separate queues for details and image downloads. The entire purpose in using NSOperationQueue and setting maxConcurrentOperationCount is that iOS can only execute 5 concurrent requests with a given server. By putting these in two separate queues, you're losing the benefit of maxConcurrentOperationCount. As it turns out it takes a minute for requests to time out, so you're probably not going to experience a problem, but still, it reflects a basic misunderstanding of the purpose of the queues.
Bottom line, you should have only one network queue (because the system limitation is how many network concurrent connections between your device and any given server, not how many image downloads and, separately, how many description downloads).
Have you thought about just doing this asyncronously? I wrote a class to do something very similar to what you describe using blocks. You can do this two ways:
Just load async whenever cellForRowAtIndexPath fires. This works for lots of situations, but can lead to the wrong image showing for a second until the right one is done loading.
Call the process to load the images when the dragging has stopped. This is generally the way I do things so that the correct image always shows where it should. You can use a placeholder image until the image is loaded from the web.
Look at this SO question for details:
Loading an image into UIImage asynchronously

Processing uploaded images asynchronously: what to do in the meantime?

I need to accept images uploaded by the users, and do some processing in the background, like generating different size thumbnails, a checksum for the original image, check for duplicates, etc. After that, the user should be able to see his submission.
The problem is that the http response will probably be sent before the processing is finished, so what do I tell to the user?
I can think of 4 options:
Put a dumb placeholder for the thumbnails, with a sign that reads 'processing' or something, plus an explanation somewhere. The user will have to press f5 until he sees the image, unless he already trusts the system and knows it's going to work.
Put a smart placeholder, something like a javascript animation plus recurring ajax calls that will fetch the thumbnails when they are ready. This is great for the user experience, but might generate some overhead in the server.
Do the processing asynchronously to avoid overloading, but block the request until the processing is finished. This one looks like a good choice to deliver the product fast, and iterate later if the server starts getting many upload at the same time.
Web sockets?
Are there other options? Which one looks better to you? Are there any pros/cons I'm not seeing?
I would go with
"Put a smart placeholder, something like a javascript animation plus recurring ajax calls that will fetch the thumbnails when they are ready. This is great for the user experience, but might generate some overhead in the server."
You can then refine this further based on analytics. With time you will know how long each image would takes to transform based on factors like image size, server-load etc. You can incorporate this knowledge to optimize your JS scripts that poll for results.
Don't try to optimize without data points and profiling.

Resources