I'm developping a little image sharing app for my company. Everything works pretty fine except for one thing : when I upload an image to the server, and switch the app to background, a part of the image is corrupted (all gray).
It seems that the image data is sent correctly as long as the app is live. As soon as I switch to background, it sends nothing as it seems.
For the record, I use ASIHttpRequest, the shouldContinueWhenAppEntersBackground is set to YES and I'm running the app from iOS 4.3 to iOS 6.0. I'm using ARC.
I tried to "retain" (through a strong reference) both the image and the data, nothing there too.
Here are parts of the code :
The
Webservice that sends the image
- (void)sendImage:(UIImage*)image forEmail:(NSString*)email
{
NSString* uploadImage = [NSString stringWithFormat:[self completeUrlForService:SEND_PHOTO], email];
NSURL* url = [NSURL URLWithString:[uploadImage stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"uploadImage %#", uploadImage);
// setting that we will send a JSON object
[self setRequestType:WebServiceWrapperTypePOSTRequest];
// when posting a picture, it could take more time...
self.request.timeOutSeconds = 4*60;
[self.request setShouldContinueWhenAppEntersBackground:YES];
// setting up the POST data
[self addPostData:image forKey:#"fileContents"];
// start the request
[self startRequestForUrl:url userInfo:[NSDictionary dictionaryWithObject:SEND_PHOTO forKey:URL_KEY]];
}
the actual part of ASIHttpRequest class
self.request = [ASIHTTPRequest requestWithURL:url];
[self.request setShouldContinueWhenAppEntersBackground:YES];
NSString* key = [[self.postDictionnary allKeys] objectAtIndex:0];
UIImage* value = [self.postDictionnary valueForKey:key];
__strong NSData* data = UIImageJPEGRepresentation(value, 1.0);
if (!data) data = UIImagePNGRepresentation(value);
[self.request appendPostData:data];
[self.request setPostLength:data.length];
[self.request setUserInfo:userInfo];
[self.request setDelegate:self];
[self.request startAsynchronous];
If any of you guys has the tinyest idea, I'll take it!
Thanks.
Finally I decided to use a different library (MKNetworkKit) and instead of sending an UIImage, I save the image on disk to the tmp folder and send the file instead. When the download is complete, I just delete the image on disk. It worked liked a charm :)
Related
In my app I load some static JSON string from some server.
Every now and then the JSON file is updated and then I want the app to reload the data.
Now, that I updated the file on the server the app does not reflect the change. If I take the URL to that file from the app's code and copy it into a browser and fetch the file there, I clearly see the updates. But when I run the app and log the json string to the debug console, then I clearly see an outdated version of the file's content.
Is there any caching involved? Can I force the iOS to actually reload it?
This is how I load it now:
NSURL * url = [NSURL URLWithString:[DOWNLOAD_URL stringByAppendingString:DOWNLOAD_FILE]];
NSError * error;
NSData *jsonData = [NSData dataWithContentsOfURL:url options:NSDataReadingUncached error:&error];
NSLog(#"JSON: %#", [NSString stringWithUTF8String:[jsonData bytes]]);
The option NSDataReadingUncached should prevent the system from caching the data.
PS: When I run the app on a different device, then it receives the current data. But when I again let it run on the original device - on which I observe this behaviour - then the data "received" is still outdated. So it really looks like some cashing issue to me.
Here is an idea. Try calling
[[NSURLCache sharedURLCache] removeAllCachedResponses];
For more granular control on cashing use NSURLConnection or NSURLSession.
I did try Mundi's suggestion, to try clearing the cache, but this didn't make any difference in my iPhone app.
So, I tried a trick which I use in my Angular webapps, and appended the current time (in ticks) to the URL I'm attempting to open, and that did work:
NSString* originalURL = #"http://somewebservices/data/1234";
NSString* newURL = [NSString stringWithFormat:#"%#?t=%f", originalURL,
[[NSDate date] timeIntervalSince1970]];
NSLog(#"Loading data from: '%#'", newURL);
NSURL *url = [NSURL URLWithString:newURL];
if (url == nil)
return false;
NSError *error;
NSData* urlData = [NSData dataWithContentsOfURL:url options:NSDataReadingUncached error:&error];
(Sigh.)
I'm getting too old for this stuff....
I need help, I have an application that collects my profile picture facebook, the problem is that if I change this profile picture on facebook and then go to my application, I still shows the old image, but the service returns me good url with the updated image, which can be happening?
if ([session sessionType] == MASTFacebook) {
NSLog (# "fbPictureURL:% #", [(MAFacebookSession *) session fbPictureURL]);
[self.userImgView setImageWithURL [(MAFacebookSession *) session fbPictureURL]];
}
Because you are caching image, try to use NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:-1]; and use method like setImageWithURLRequest to set your UIImageView.
In your case, the code should be like followings if you are using UIImageView+AFNetworking
if ([session sessionType] == MASTFacebook) {
NSLog (# "fbPictureURL:% #", [(MAFacebookSession *) session fbPictureURL]);
NSURL *url = [(MAFacebookSession *) session fbPictureURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:-1];
// if you are using UIImageView+AFNetworking. the method is as follows
[self.userImgView setImageWithURLRequest:request placeholderImage:nil success:nil failure:nil]];
}
Because you are using setImageWithURL so it will cache your image automatically by url , so you should also update image url after update image.
best way will be once you get the image url from Facebook convert it into UIImage and save it. depending on your requirement(app delegate , UserDefaults). Then assign it to ImageView. So that you can use image in any view controller as the your profile pic is already convert into Image it will not take time to convert(not caching but works as cache). when ever you login you can get the updated profile pic.
ex:
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
[defaults setObject:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"your image url" forKey:#"profileImage"];
Here you can saving Data (In UserDefaults we can not save image so we save data).
UIImageView *view =[[UIImageView alloc]initWithData:[defaults objectForKey:#"profileImage"]];
I use IOS7
I start download and i lock screen, and i open screen. My program is shutdown...
Is there some can help me ?
This is major code:
init download url:
NSURL *url = [NSURL URLWithString:dictionaryUrl];
ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:url];
set ASIHTTPRequest delegate:
request.delegate = self;
init file save path:
NSString *savePath = [path stringByAppendingPathComponent:name];
bool b=[ fileManager createFileAtPath :savePath contents : nil attributes : nil ];
if (b){
fileHandle=[ NSFileHandle fileHandleForWritingAtPath :savePath];
}
[request setAllowResumeForFileDownloads:NO];
[request setDelegate:self];
[request setDidFinishSelector:#selector(requestDone:)];
[request setDidFailSelector:#selector(requestWentWrong:)];
[request setDataReceivedBlock :^( NSData * data){
[fileHandle seekToEndOfFile ];
[fileHandle writeData :data];
[ label setText :[ NSString stringWithFormat : #"downloading...%.1f %%" , process . progress * 100 ]];
}];
[request setDownloadProgressDelegate:process];
add to ASINetworkQueue:
[self.netWorkQueue addOperation:request];
relase request:
[request release];
First, you need to enable the request to run at background. add this :
[request setShouldContinueWhenAppEntersBackground:YES];
for quick task it's possible, works like charm. but for long running task, just like you wanted, to keep continue download, you need to add a bit code, to enable this request from being terminated because run too long.
I've answered question for location update by adding timer and fire API every x seconds indefinitely. using UIBackgroundTaskIdentifier and NSTimer. This should give you an idea. should be same concept of what you are doing.
How do I get a background location update every n minutes in my iOS application?
When your screen gets lock your app goes to background.You can perform tasks for a limited time after your application is directed to go to the background, but only for the duration provided. Running for longer than this will cause your application to be terminated. See the "Completing a Long-Running Task in the Background" section of the iOS Application Programming Guide for how to go about this.
For iOS7 you can check this link https://stackoverflow.com/a/19355437/1372368.
And the code snippet to run task in background you can find various links like:How to keep an iPhone app running on background fully operational
I am currently developing an iOS application and am implementing the Box.Net SDK. I have gotten everything to work except the ability to move files around, which is not a native feature of the SDK. I am trying to twist my way through it.
If you are familiar with the structure of Box.Net, each file/folder has an ID number for itself, and an ID its parent. From what I understand if I want to move a file, I am supposed to change the parent ID number on the file which will point it to the new location. I can't seem to get it to work properly though. My application seems to keep crashing.
This is what I have so far, generalized.
BoxObject *boxObject = [[[Box objectWithID:(ID#ofParent)] children] objectAtIndex:i];
[boxObject parent].boxID = 0; // <-- Problem (causes crash)
I also tried this.
[boxObject setParent:[Box folderWithID:[BoxID numberWithInt:i]]];
The boxObject variable is the file that I want to move. I am setting its parent ID equal to 0, which is supposed to be the root folder. However, my application crashes when I try to reassign the parent ID for the file. Any ideas on how to successfully move files/folders? Any help is much appreciated! Thanks in advance!
Okay. I suppose there wasn't a way to do fix this in-house with the SDK. So, I had to send out an external PUT request. I used the following code to handle moving files.
- (void)moveItem:(BoxObject *)object toParentFolderWithID:(BoxID *)parentID
{
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"https://api.box.com/2.0/files/%#", object.boxID]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"PUT"];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *auth = [NSString stringWithFormat:#"BoxAuth api_key=%#&auth_token=%#",[Box boxAPIKey],[defaults objectForKey:#"box-api-auth-token"]];
NSString *payload = [NSString stringWithFormat:#"{\"parent\": {\"id\": %#}}", parentID];
[request setHTTPBody:[NSMutableData dataWithData:[payload dataUsingEncoding:NSUTF8StringEncoding]]];
[request setValue:auth forHTTPHeaderField:#"Authorization"];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
[connection start];
}
Just as a reminder if you are new to the Box SDK, you will most likely need to update/refresh the data after moving the files. If not handled, your application could crash if the file doesn't exist. Hope this helps to anyone was not sure about this.
I need you to humor me during this question. This is somewhat pseudo code because the actual situation is quite complex. I wouldn't load an image this way unless I needed to. Assume that I need to.
NSURL *bgImageURL = [NSURL URLWithString:#"https://www.google.com/images/srpr/logo3w.png"];
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:bgImageURL]];
[self.anIBOutletOfUIImageView setImage:img];
but I crash out with
-[__NSCFData _isResizable]: unrecognized selector sent to instance 0x9508c70
How can I load an image from a URL into NSData and then load that NSData into a UIImage and set that UIImage as the image for my UIImageView?
Again, I realize this sounds like nonsense, but due to an image caching system I'm using I have to do things this way :(
How I usually handle this situation (not compiled, not tested):
NSURL * url = [NSURL URLWithString:#"https://www.google.com/images/srpr/logo3w.png"];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue currentQueue]
completionHandler:^(NSURLResponse * resp, NSData * data, NSError * error) {
// No error handling - check `error` if you want to
UIImage * img = [UIImage imageWithData:data];
[self.imageView performSelectorOnMainThread:#selector(setImage:) withObject:img waitUntilDone:YES];
}];
This avoids the long-running network request implied by the call to dataWithContentsOfURL:, so your app can continue doing things on the main thread while the data downloads for the image.
As a side note, you seem to be running into the same error as this question; you might want to check that you're not running into object allocation problems.
I plugged this code into a new, iPad "Single view application" template:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSURL *bgImageURL = [NSURL URLWithString:#"https://www.google.com/images/srpr/logo3w.png"];
NSData *bgImageData = [NSData dataWithContentsOfURL:bgImageURL];
UIImage *img = [UIImage imageWithData:bgImageData];
[[self Imageview] setImage:img];
}
I got the image to load up properly. I even tried different content modes for the UIImageView, and they all worked as expected.
If you start from scratch, do you get the same problem?
The error message indicates that you're sending a message of "_isResizable" to an NSData object. Maybe you're inadvertently setting the UIImageView's image property equal to the NSData instead of the UIImage.
Edit/Update
I even went back and tried different versions of "one-lining" the code to see if any of that mattered, since my "working" copy was slightly altered from your non-working copy. I couldn't get the code to break. My guess would be that the code in question isn't broken, but something nearby is...