I'm not sure why my NSURLSession is retaining the controller if I am using weakSelf. I know the block still gets executed regardless, but when I set breakpoints in the delegate methods (i.e. didReceiveData), I see self is not nil even though the controller was dismissed already.
Would appreciate any thoughts.
Thanks!
Please see my code snippet below
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
delegate:weakSelf
delegateQueue: nil];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
[task resume];
[weakSelf.imagesAndTasks setObject:image forKey:task];
});
Related
I try to download a zip-archive using NSURLSessionDataTask.
I am aware that there is a NSURLSessionDownloadTask, but the point is I want a didReceiveData callback (to show the progress).
The code is:
NSURLRequest *request = [NSURLRequest requestWithURL:#"..."
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSOperationQueue *myQueue = [NSOperationQueue new];
myQueue.underlyingQueue = dispatch_get_main_queue();
NSURLSession *session = [NSURLSession sessionWithConfiguration:config
delegate:self
delegateQueue:myQueue];
NSURLSessionDataTask* task = [session dataTaskWithRequest:request
completionHandler:^( NSData *data, NSURLResponse *response, NSError *error){ ... }
[task resume];
My class conforms to NSURLSessionDataDelegate.
When I call the method, after several seconds debugger goes to completionHandler with nil data and nil error.
What am I doing wrong?
I also tried:
calling without completionHandler, then debugger goes to didReceiveResponse callback with 200 response and that's all.
using [NSOperationQueue new] for the queue
using [NSURLSession sharedSession] - didn't get any response
using [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: #"..."] - falls saying that I can't use a completionHandler, but without it - also no response.
So I have found the answer and it's not quite obvious from documentation:
I had several callbacks, and among them didReceiveResponse.
Turns out I have to call completion handler in order for the future callbacks to work, i.e:
completionHandler(NSURLSessionResponseAllow);
And one more thing: didCompleteWithError is actually the delegate that tells about successful finish, too, although the name implies that this is the error handler.
What it means: when a download is successfully finished, this function is called with error = nil.
Hope this will be useful for somebody someday.
I have the following code for NSURLSession
NSURL * url = [NSURL URLWithString:urlString];
HomeViewController* hvc= [self.storyboard instantiateViewControllerWithIdentifier:#"HomeViewController"];
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate:hvc delegateQueue: [NSOperationQueue mainQueue]];
NSURLSessionDataTask * dataTask = [defaultSession dataTaskWithURL:url ];
[dataTask setAccessibilityLabel:#"UserProfiling"];
[dataTask resume];
The compiler shows a warning at this statement:
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate:hvc delegateQueue: [NSOperationQueue mainQueue]];
and the warning is :
Sending 'HomeViewController *' to parameter of incompatible type 'id<NSURLSessionDelegate>'
How do I remove this warning?
I have confirmed to the delegates by writing:
#interface ProfileTabView : UIViewController <NSURLSessionDataDelegate, NSURLSessionDelegate, NSURLSessionTaskDelegate>
{
}
Basically, I am calling a NSURLSessionDataTask and the delegates are in another ViewController as you see above.
(From a comment, making answer for posterity.)
HomeViewController is not the class you've added the protocol conformance to (ProfileTabView).
I have a NSURLSession dataTask created using the following method:
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate:hvc delegateQueue: [NSOperationQueue mainQueue]];
NSURLSessionDataTask * dataTask = [defaultSession dataTaskWithURL:url ];
[dataTask setAccessibilityLabel:#"UserProfiling"];
[dataTask resume];
Here, hvc is another ViewController where I am handling the delegate for this server data task call.
I see that the dataTask is making multiple calls to the server continuously.
Is there a way to ensure that only one call is made?
This has been solved and answered below.
I am answering my own question here.
By mistake, I was writing the above code in another method which was being called repeatedly. It was the Corelocation framework that was continuously updating the user's location.
I am requesting an API that takes some time to give response, so during that time no other operation can be performed. e.g. back button or Tabs are not pressed. I am Using the following code:
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];
NSURL * url = [NSURL URLWithString:urlString];
NSURLSessionDataTask * dataTask = [defaultSession dataTaskWithURL:url
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(error == nil)
{
}else{
}
}];
[dataTask resume];
Can anyone Suggest why my app is freezing during this operation. Thanks in advance.
Because you are performing operation in main thread, you need to do this task in background thread.
For this you can use NSOperationQueue and add a operation of you api calling.
see belo links
NSOperation and NSOperationQueue working thread vs main thread
How To Use NSOperations and NSOperationQueues
Working with the NSOperationQueue Class
or you can also use DispatchQueue
see : Multithreading and Grand Central Dispatch on iOS for Beginners Tutorial
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// simply call your function here
});
you are doing operation on main thread swhich interrupt app execution. you should do this operation in background through GCD by creating async request to download data in background it will not interrupt your app execution.
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
NSURL * url = [NSURL URLWithString:urlString];
NSData *response = [[NSData alloc] initWithContentsOfURL:url];
// above code will download data in background
dispatch_async(dispatch_get_main_queue(), ^{
// here you can access main thread of application and do something here
});
});
I have a program that download a video from a url using NSURLSession, but i'm not able to do multiple download at the same time.
How can i do it?
How can i manage multiple simultaneous download?
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];
NSURLSessionDownloadTask *getVideo = [session downloadTaskWithURL:fileURL
completionHandler:^(NSURL *location,
NSURLResponse *response,
NSError *error) {
// 2
receivedData = [NSData dataWithContentsOfURL:location];
dispatch_async(dispatch_get_main_queue(), ^{
// do stuff with image
NSLog(#"%s receiveData:%d",__FUNCTION__,[receivedData length]);
});
}];
[getVideo resume];
From the code you have provided above you are not using any of the properties of NSURLSessionConfiguration class that would enable better download performance.
First of all I would look suggest using your own delegate queue. If you do not provide a queue then the session creates a serial operation queue for all delegate and completion handler calls see the "Creating a Session" section of the NSURLSession Class Reference document for more detail. You can look at the following properties of NSOperationQueue to help improve performance;
qualityOfService
maxConcurrentOperationCount
Next I would look at NSURLSessionConfiguration properties that may help.
HTTPMaximumConnectionsPerHost
HTTPShouldUsePipelining
Finally you should review the section "Life Cycle of a URL Session with Custom Delegates". You should confirm whether your using the delegate methods of NSURLSessionTaskDelegate and NSURLSessionDownloadTaskDelegate or just the completion handler.
You need to put more time into configuring NSURLSession to support the work you want to do.