I want to use NSURLSession to upload photos to cloud server(like OneDrive) and I hope the app can do works in background.
But NSURLSession just support "fromFile" not "fromData" in background mode, and I don't know how to get the NSURL of photos, so I write the photo's data into a file...
I think this is not a good way.
From the comments above, it seems like you'll be uploading several photos at a time and for that a "fromData" approach does not seem like a good idea.
Firstly, high resolution photos have several megabytes in size. If your loading a 5mb photo into memory, using NSData, you're probably fine. But loading 10 photos would then mean you'd need 50mb of memory to hold them all.
Secondly, uploading large chunks of data, such as photos, is also a computationally intensive task. You should most definitely not try to upload them all at the same time. This means you're going to have to build an upload queue that only starts uploading the next photo once the last one has finished. What happens then if internet connectivity is lost midway through the process? And what happens if the user closes the app all of the sudden?
Thus, I'd suggest you grab all the images' data and write them to a temporary folder somewhere. Then you start the upload process, which would find a file on the temporary folder, upload it, delete it once the upload finishes successfully and start over with the next file.
This way you're minimising your app's memory footprint, making it more resilient in the face of the many adversities an app may face (no internet connection, being prematurely closed by the user and so on) and also abiding by the APIs that are provided to you.
Related
I'm developing a chat app with Firebase. Am currently still in development phase.
Profile pictures of test users are uploaded to Firebase Storage, and are downloaded in the home screen (with all the pictures). I realized that with that I very quickly used up storage download requests (easily hit 3,000 requests in one night, and hit the free plan quota!).
What are some best practices I could use to minimize download requests? Just to be sure I'm doing it right - I'm sending a GET request to the Firebase Storage url directly: https://firebasestorage.googleapis.com/... to download the image. Is that the right way to do it?
Two suggestions that might help:
Cache your images! If you keep requesting the same images over and over again over the network, that's going to use up your quota pretty fast. Not to mention your user's battery and network traffic. After you retrieve an image from the network, save it locally, and then the next time you need an image, look for it locally before you make another network request. Or consider using a library like PINRemoteImage that does most of the work for you. (Both on the retrieving as well as the caching side)
Consider uploading smaller versions of your image if you think you might be using them often. If your chat app, for instance, saves profile pictures as 1024x768 images, but then spend most of its time showing them as 66x50 thumbnails, you're probably downloading a lot of data you don't need. Consider saving both the original image and a thumbnail, and then grabbing the larger one only if you need it.
Hope that helps...
My app is downloading large 90 MB video files from a server. Many customers in rural areas complain about inability to download them. Downloads always restart from scratch when the connection breaks for too long.
Is there a library that can download large files in very low and interrupted bandwidth conditions over the course of several days if necessary? Such that it resumes an unfinished download and keeps adding bit by bit until it is complete?
It has to be very, very robust.
NSURLSession supports this. When a download fails you can obtain an object that can be used to resume the download later. Read the doc for more infos.
You can also make use of a background session if you want to perform a long download in the background. See the doc and this question : NSURLSession background download - resume over network failure
Here is the point: I've got an app that runs with a set of images in very low resolution. Nothing special here.
When the app starts, I'd like it starts the synch download of full resolution photos set process (photos are downloaded off a remote server).
As the file is typically large (>1Gb), I need a way to resume from a potential stop (whatever the reasons), so that it eventually have 100% of photo set on the device without having to start over from the start.
How would you do that?
Your question does not tells about the data in details. There are 2 cases possible :
You are downloading all the images as a single file(like .zip) or in a single request : In this case you can use NSURLSession which has the pause and resume facility inbuilt.
You are downloading the images one by one : In this case you need to have track of the images with some id or index to start the download from a particular file in a sequential manner. For each file pause and resume facility you can use NSURLSession.
Most apps I see have loading screens, presumably to prevent hiccups in the game and to pre-load all of the data needed later in the game. I am currently working on a game that skips every few frames, presumably because the image data for the objects being rendered to the screen are not being held in memory. What do programmers actually do to hold this data in memory throughout the time the app is running? I can think of using arrays, such as NSArray or NSMutableArray to hold the images, however I still struggle to see how that would improve the performance of the app. Perhaps I am totally going off on a tangent here. A word of advice from someone with experience in the area would be greatly appreciated.
EDIT:
For the person who voted to close the question, my question, more specifically, is this: What is a typical method in which an ios game loads its data into active memory to enable easy and low-overhead access during run time?
I have seen several application that downloads configuration and metadata on application load, some also download images and audio files.
Usually they store the data in the documents or cache folder, so the they will not have to wait for download during the game.
Another technique I encountered is downloading a zip file and expanding it in the cache directory. Most of these apps do not load the files the next time unless something new is needed.
Do not load the images to the memory, not inside an nsarray nor nsmutabearray. You do not have enough memory to cache images like this. You should just predownload them
Edit:
You can use the application loading stage to download more resources from your servers (images, audio, plist files) but after they are download and stored in the file system they should be treated like resources that exists in your IPA. They should be loaded into memory only when they are needed
Let's say I want to preserve the full resolution of a photo on the iPhone, and then upload it to a web service for storing. Quality is critical. Unfortunately, the size of a 3200x2400 photo taken with the iPhone camera is approximately 10-12MB for a PNG, and 1-3MB for a JPG (as of my latest tests).
Here we have a dilemma. On a 3G connection, a 12MB upload is an eternity (relatively speaking, of course). So I've explored a few options, including streams/chunking and background uploading. Still, it's not ideal. I'd like the upload to be as fast as possible. See edit.
So my question is this: would it be possible to split an image into separate data chunks, upload them all concurrently using multiple asynchronous connections, and then re-assemble them server side? Does an implementation exist for this?
EDIT: So speed is capped by bandwidth as has been discussed in the comments. But there are other uses for chunking/splitting that I would like to explore. So the question still stands.
What you can do is actually split the image into several pieces, and upload each, then reassemble later.
I guess a benefit of that would be getting a partial image on failed connection, then continuing uploading the remaining pieces afterwards.