Will NSURLRequest timeout value overrides NSURLSessionConfiguration timeoutIntervalForRequest value? - nsurlrequest

I am creating a NSURLSession object with timeoutIntervalForRequest configuration = 120 seconds. After this I am creating a NSURLSessionDataTask object and calling the method dataTaskWithRequest:completionHandler. Here one input parameter is a NSURLRequest. Again while I create a NSURLRequest, I can specify a some of parameters like timeout, cachePolicy etc. But these were already mentioned while I created NSURLSessionConfiguration. So if I use different values for a NSURLRequest, will those values override NSURLSessionConfiguration values?

In short, YES.
According to Apple's document:
In some cases, the policies defined in this configuration may be overridden by policies specified by an NSURLRequest object provided for a task. Any policy specified on the request object is respected unless the session’s policy is more restrictive. For example, if the session configuration specifies that cellular networking should not be allowed, the NSURLRequest object cannot request cellular networking.

My recollection is that yes, the value in the request takes precedence over the session's value. With that said, I'm not 100% certain, so I would try it and make sure, assuming it actually matters.

Related

Setting timeoutInterval on Alamofire DataRequest

I'm making a custom class that takes an Alamofire DataRequest in it's initializer. Now I want to add a timeoutInterval to it, but I'm getting the compiling error
Value of type 'DataRequest' has no member 'timeoutInterval'
Here is the code:
init(request: DataRequest, timeoutInterval: Double = 10) {
request.timeoutInterval = timeoutInterval // <- compile error here
self.request = request
}
Obviously Alamofire DataRequest doesn't have that property. But is there any other way to specify the timeout to a request in this way (without using a SessionManager preferable)? URLRequest has it, so it should be possible somehow, but I cannot figure out how.
I know that this question has been asked before here on Stack Overflow, but I cannot find any answer that fits this situation.
In Alamofire 5.1 we've added a requestModifier parameter to the top level request methods that gives you access to the URLRequest that will be performed.
In Alamofire 4 you have a few, less elegant options. One straightforward way to set it is to use a RequestAdapter that will set it as part of the request pipeline. Another, more involved option, is to move from the top level request method that takes individual parameters, such as headers, to the API that takes a URLRequestConvertible value. That way you have full control over the URLRequests that are performed by Alamofire on your behalf.

Measuring total response time for NSURLSession's dataTaskWithRequest

When using NSURLSession's dataTaskWithRequest how can total response time be measured in the event that many NSURLSessionDataTask are created and will not necessarily be executed immediately? Storing a starting time and calculating the difference within the block doesn't account for time that a task may have been waiting for an available thread. IE:
let startTime = NSDate();
let task = session.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
let responseTime = NSDate().timeIntervalSinceDate(startTime);
}
I think you can probably do this with a fairly trivial custom NSURLProtocol.
In your canInitWithRequest: method, call the setProperty:forKey:inRequest: method on NSURLProtocol to set a custom start time key for the request. Then reject the request (by returning NO) and allow the normal HTTP protocol to handle the request normally.
When you get a response, call property:forKey:inRequest: to get the start time.
With that said, there's no guarantee that the request really will start immediately after the call to canInitWithRequest:, and because there's no good way to subclass the original HTTP protocol handler class (to wrap the startLoading method), this may or may not be precise enough. I'm not sure.
So if that doesn't work, then to improve the accuracy, you would have to create a full-blown protocol that:
Returns YES in canInitWithRequest: (except if the start time has already been set for that request)
Creates a new URL session in its startLoading method (to ensure that the request will start instantly)
Adds the start time to the request
Begins the request in that new session
But even that will not necessarily give you precise timing if the request is happening while the app is in the background or if the discretionary flag is set on the session configuration. That approach also won't work very easily if you're using more than one session with different configurations. It is, however, probably the best you can do in terms of accuracy, because I doubt that there's any way to swizzle the built-in HTTP protocol class (if such a class even exists).

Architectural approach to HTTP communications and the parsing of returned JSON in iOS

Good evening guys,
My question is more of an engineering/design pattern approach than specifically technical.
I am developing an app that requires lots of interaction with a remote API returning JSON objects. The retrieval, parsing and utilisation of the data is not a problem and is working very smoothly. I am wanting to get some direction on the best design approach for this sort of scenario.
I will explain what I have so far (in pseudo code and declarations) and see if you can help:
A HTTP Fetcher class implementing the necessary NSURLConnection delegate methods. I initialise the class with the callback method selector like so for returning to the calling class on completion
#implementation HTTPFetcher{
- (id)initWithUrlRequest:(NSURLRequest *)aRequest receiver:(id)aReceiver action:(SEL)aReceiverAction
{
//set the member variables etc..
}
//all NSURLConnection delegate methods
- (void)connectionDidFinishLoading...
{
[receiver performSelector:action withObject:self];
}
}
I then have a Singleton HTTPController class for calling the HTTPFetcher:
- (void)postWithRequestString:(NSString *)aRequestString
{
[urlRequest setHTTPBody:[aRequestString dataUsingEncoding:NSUTF8StringEncoding]];
fetcher = [[HTTPFetcher alloc]initWithUrlRequest:urlRequest receiver:self action:#selector(receivedDataFromService:)];
[fetcher start];
}
- (void)receivedDataFromService:(HTTPFetcher *)aFetcher{
//handle the received data and split the parent object into an NSMutableDictionary
}
Now this approach works fantastically well for the app I have especially given the separate entities that I have to model (I will basically have a Singleton HTTPController for each entity).
My issue is where to handle the custom parsing of the JSON. Currently, I am doing the parsing the in ViewController where the data is required but this is too close to the source and needs to be abstracted out further but I am unsure how.
Should I include the methods to facilitate the parsing within the Singleton classes or should I create further controllers for parsing actions?
I look forward to hearing from you
Thanks
I would recommend you build on an existing JSON parsing library, in particular John Engelhart's JSONKit, considering it's arguably the highest performance JSON parsing library out there for iOS. Saves you implementing custom JSON parsing at all, but especially saves you implementing code which turns out to be too slow for your needs and then you will need to iteratively refine it until it gets fast enough for you to use.
For HTTP requests, I know you've implemented the behaviour already, but you might want to investigate ASIHTTPRequest or AFNetworking as general purpose networking libraries which have a reputation for being quite robust. Note AFNetworking uses the above JSONKit library for JSON parsing.
The way ASIHTTPRequest (the library I use in my projects) works is by using a delegate object implementing the protocol ASIHTTPRequestDelegate, which you assign after creating a request with a URL. There's a global network queue which is just an NSOperationQueue, and that handles asynchronous or multiple concurrent active requests.
You can setDelegate: for the object to start checking whether your delegate has implemented any of the methods at different points, such as didReceiveData: or requestDidFinish: by default, but you can also set a custom selector path to check by using the methods for individual operations (setDidFinishSelector:#selector(downloadComplete:)).
What you could do when, for example, the didReceiveData: callback happens, is pass the newly received data into a buffer stored in a wrapper class for an ASIJSONRequest (or use AFNetworking, which already encapsulates this). When the buffer is such that there is a complete JSON object in there which can be parsed correctly, then you call out to JSONKit to do the grunt work and then maybe send another callback yourself to an ASIJSONRequestDelegate for didReceiveData:, but now the data is in a format which is readable by the rest of your application.
Another method of using ASIHTTPRequest is with blocks. There is support for setting a completion block for a request, a block that is called when data is received, etc. For this design pattern you don't even need a wrapper class, just set the code block up to do the parsing itself and return any new data parsed to its desired destination.
One possibility would be for the View or view controller to ask a Model object for any state that it needs (including stuff from a remote server). The Model object would be told when there was any new data from the server, and it could then call any required data munging routines required to update its internal state (converting plists or json into a more canonical dictionary format, for instance).

Is it safe to use the "hash" method to track NSURLConnections in memory?

My question is related to this discussion: http://www.cocoabuilder.com/archive/cocoa/202211-how-to-get-nsurl-form-nsurlconnection.html
I am sending several NSURLConnections to transmit data and need to be able to tell which specific connection failed or succeeded. There are NSURLDelegate methods (didFailWithError, etc) which return the related NSURLConnection. The problem is that there is no NSURLRequest returned in the delegate methods (and there is no NSURL accessor in the NSURLConnection).
The solution I've implemented is to maintain a NSMutableDictionary which pairs the URL string that was sent with the result of this NSURLConnection's "hash" method.
I've tested it and it seems to work - the hash of the NSURLConnection that is returned in the delegate method is the same as the hash from the NSURLConnection that was sent initially.
My question: is it safe to do this? Is there a better key to use than the hash? I'm asking because in my naive understanding, the hash is somehow associated with the address of that object in the memory, and it seems possible that backgrounding the app or turning the phone off and on may change this value as things are rewritten to memory.
Thanks very much!
I generally use ASIHTTPRequest, and when issuing multiple connections (concurrently in queue or parallel) I use the userInfo dictionary to pass around context.
The "hash IVAR" you refer to is actually defined in the NSObject protocol - as a method. It is intended to be used in a hash table, and as such should be sufficient for your needs.
I'd still prefer a more first-class approach to this problem, whilst making it more explicit which request is finishing/erroring-out.

how to manage multiple asynchronous NSURLConnection delegates?

I have a class that makes multiple asynchronous connections where each connection performs its own logic in the delegate methods.
Because the delegate is the class itself, how can I implement this separation in logic in the NSURLConnection delegate methods?
My vote is for creating a different class for each operation you're doing. It may sound like a lot more work, but your code is going to be a heck of a lot cleaner which will probably lead to less bugs.
March 2014 edit - Don't use the delegate methods, use blocks.
Sounds to me like you need to better represent your objects in terms of object orientation.
You should have one class that manages multiple classes that each manage their own URL connection.
Either check the passed in NSURLConnection against a saved value to see which connection is responsible; or make the delegate different objects; or make the callback behave in a generic manner.
I ran into this problem like this. I have a class that does the same thing. I worked around it by storing each NSURLConnection object in a mutable dictionary instance var with its hash as the key. I then added a cancelAllConnections method in the class and I call it in each view controller's viewDidUnload method. The method removes all the connection objects in the mutable dictionary. Then I added a check in NSURLConnection's connectionDidFinishLoading to check for the hash key in the mutable dictionary. If the hash value doesn't exist, that means the connection was canceled, and the the callback selector won't be performed on a garbage object.