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.
Related
I'm trying to do a simple get in iOS (Objective C) using a simulator and not a real device.
NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:theGetURL]
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:10];
[newRequest setHTTPMethod: #"GET"];
NSError *requestError2;
NSURLResponse *urlResponse2;
NSData *response2 = [NSURLConnection sendSynchronousRequest:newRequest returningResponse:&urlResponse2 error:&requestError2];
NSString* secondResponse = [[NSString alloc] initWithData:response2 encoding:NSUTF8StringEncoding];
NSLog(#"error = %#",requestError.localizedDescription);
NSLog(#"response=%#",secondResponse);
NSLog(#"url response = %#",urlResponse);
This code works perfectly when I'm passing a simple url. When I try the code with a longer (around 4000 characters) url, the code doesn't work (no error is printed).
I am aware that a post is better for this kind of thing, but my question is, is this expected from a get request?
Also, my url works perfectly in my mac and iOS browsers.
As you suspect, I think you need to consider moving to use POST rather then GET. The server side limit is 8K, however it seems this can be much less for the client side.
The following discussion sums everything up well. It also seems to imply the limit for Safari is 2K, which probably means it is the same or less for iOS, which would explain your problem with 4000 characters.
maximum length of HTTP GET request?
I think your URL query parameter might have any character that is not encoded. Try to ensure it.
For encoding you may try this code
- (NSString *)encodeQueryParameter:(NSString *)str
{
CFStringRef ref = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(__bridge CFStringRef)str,
NULL,
CFSTR(":/=,!$&'()*+;[]##?"),
kCFStringEncodingUTF8);
NSString *result = (__bridge_transfer NSString *)ref;
return result;
}
I'm having a crash but only in the ad hoc version. The debug build works fine but the adhoc crashes. This is being compiled with ARC but to use this library I have "-fno-objc-arc" set for compiler flags. Crash report is here: http://pastebin.com/edasCJbb
-(void)executePostRequestWithEndpoint:(NSString *)pathMethod usingVariables:(NSDictionary *)dict completion:(BWObjectBlock)completion failure:(BWFailureBlock)failure {
NSURL *url = [NSURL URLWithString:pathMethod];
__unsafe_unretained __block ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
NSLog(#"It gets to this NSLog and then crashes");
[request addRequestHeader:#"User-Agent" value:kMyUserAgent];
NSLog(#"It DOES NOT get to this NSLog");
NSMutableDictionary *params = dict ? [NSMutableDictionary dictionaryWithDictionary:dict] : [NSMutableDictionary dictionary];
if (params.count > 0) {
for (NSString *key in [params allKeys]) {
[request setPostValue: [[[params objectForKey:key] description] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] forKey: key];
}
}
[request setCompletionBlock:^{
id json =[[request responseString] JSONValue];
if ([json isKindOfClass:[NSDictionary class]]) {
completion(json);
}else{
failure(json,nil);
}
}];
[request setFailedBlock:^{
id o = [[request responseString] JSONValue];
failure(o,request.error);
}];
[request startAsynchronous];
}
I fully admit that I don't really understand exactly what those compiler flags do or what the __unsafe_unratained __block does either. But I'm assuming that request is being immediately released and then bad access when used. This method is crashing on the first use in the app, but normally could get called several times in a row to access different things from my server, log in, etc. So I can't use a property for that request as it would get overwritten on the 2nd request.
Of course this is using ASIHttpRequest library from Ben Copsey which is not ARC while the rest of my app is.
Xcode 5.0
Tested and crashes on all devices from iPhone4S to 5S - but only when compiled under Archive. Debug builds don't crash.
Deployment target is 5.0 but could be raised to 6.0 if it would help.
Just hoping that someone can explain this __unsafe... stuff to me and help me figure out how to fix this.
UPDATE- The crash was solved by using this answer:
ASIHTTPRequest / ASIFormDataRequest - referencing request object within blocks under ARC
But the block isn't working. Still is working different on a debug build than on a ad hoc build, which is a PITA.
I changed:
__unsafe_unretained __block ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
to:
ASIFormDataRequest * __weak request = [ASIFormDataRequest requestWithURL:url];
And variable is now retained long enough to prevent a crash. But what gets returned to the caller is either NULL or it never comes out of it.
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'm an iOS newb (.NET professional), so this may be a simple issue but I couldn't find anything through the SO search or Google (and maybe not looking for the right terms).
I'm writing an app that displays information from a DD-WRT router through it's web interface. I have no problem displaying the initial page and navigating through any of the other pages, but if I make any change on a form (and it redirects to apply.cgi or applyuser.cgi), the UIWebView is blank - it's supposed to display the same page, with the form submission changes. The site works fine in Mobile Safari, which I find intriguing, but I guess UIWebView isn't totally the same.
I think the iOS code is pretty standard for display a webpage, but I'll list it below. I can't give you access to my router because, well, that's not a good idea :) Hopefully someone with a DD-WRT router can help (or know what my issue is anyway).
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *sURL = #"http://user:pass#XXX.XXX.X.X";
NSURL *url = [NSURL URLWithString:sURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
self.webView.delegate = self ;
}
And I'm doing a few things with Javascript in the webViewDidFinishLoad method, but I know that's not the culprit because it still happens when I comment it out.
Well I figured out the problem on my own. I think part of it was putting the username & password in the URL (which was just a temporary measure) because I found that method provided the same results in mobile Safari and desktop Chrome.
So I added MKNetworkKit to my project that provided a simple way to add authentication to my request, and found I had to make a specific request to POST the data, then reloaded the page the to see the changes.
In the (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType method, I check if ([request.HTTPMethod isEqualToString:#"POST"]) and do this:
NSString *sPostData = [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding];
NSArray *aPostData = [sPostData componentsSeparatedByString:#"&"];
NSMutableDictionary *dPostData = [[NSMutableDictionary alloc] init];
//i don't know if this is the best way to set a dictionary, but it works
for (id apd in aPostData)
{
NSString *key = [apd componentsSeparatedByString:#"="][0];
NSString *val = [apd componentsSeparatedByString:#"="][1];
[dPostData setValue:val forKey:key];
}
MKNetworkEngine *engine = [[MKNetworkEngine alloc] init];
MKNetworkOperation *op = [engine operationWithURLString:[request.URL description] params:dPostData httpMethod:#"POST"];
[op setUsername:#"myUserName" password:#"myPassword" basicAuth:YES];
self.postedRequest = TRUE; //a bool I set so, when it comes to webViewDidFinishLoad, I reload the current page
[op start]; //send POST operation
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 :)