I was looking at the NSURLConnection class which could be used to establish a sync or async connection to an URL and then retrieve its data... a lot of changes have been made to this class with IOS 5 and I've seen they introduced some formal protocols related to authentication or download, but I don't see, for example, if the connection:didReceiveResponse: message (that was previously sent to the delegate and that it is no more available) is still available in some protocols.. How do you implement an async connection and retrieve, for example, HTTP headers as soon as the Response is received? I'm sure there is a way better than using NSURLConnection along with the connection:didReceiveResponse: message.. methods like stringWithContentsOfURL do always load content synchronously? What do you use to implement async downloads in your apps avoiding deprecated methods and reacting to events such as _http response received_m etc ? Do you launch synchronous downloads in background tasks, if possible?
NSURLConnectionDelegate has become a formal protocol (it was an informal protocol in previous versions). In this protocol, the following (non-deprecated) methods are declared:
connection:didFailWithError:
connectionShouldUseCredentialStorage:
connection:willSendRequestForAuthenticationChallenge:
Furthermore, there are two subprotocols that conform to NSURLConnectionDelegate:
NSURLConnectionDataDelegate is used for delegates that load data to memory, and declares the following methods, some of which I’m sure you’ll find familiar:
connection:willSendRequest:redirectResponse:
connection:didReceiveResponse:
connection:didReceiveData:
connection:needNewBodyStream:
connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:
connection:willCacheResponse:
connectionDidFinishLoading:
NSURLConnectionDownloadDelegate is used for delegates that store data directly to a disk file, and declares the following methods:
connection:didWriteData:totalBytesWritten:expectedTotalBytes:
connectionDidResumeDownloading:totalBytesWritten:expectedTotalBytes:
connectionDidFinishDownloading:destinationURL:
As you can see, you can still use your previous delegates, possibly with some minor modifications.
For more information, see the iOS 4.3 to iOS 5.0 API Differences document and NSURLConnection.h in your local Xcode installation. When a new SDK version is released, it’s not uncommon for the documentation inside the header files to be more reliable than the documentation available on the developer library. It takes a while for the latter to be up-to-date.
I just encountered this same issue. Looks like sending an asynchronous request is more simplified with blocks and NSOperationQueue.
+ (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue *)queue completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler
This means that the delegate is now only used for authentication and failure issues.
NO!
They are NOT limited to use for authentication and failure issues if you look carefully through the Apple's library.
Since introducing +(void)sendAsynchronousRequest:queue:completionHandler: to NSConnection class object, Many things which can perform as many NSConnectionDelegate method as before can now be used in formal protocols called "NSConnectionDataDelegate" & NSConnectionDownloadDelegate, opening a new room to add more feature to NSURLConnection methods. (from iOS5 on)
So I think it is an improvement, not limiting their use.
Even I havent found the documentation on the Apple website
https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html
https://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSURLConnectionDelegate_Protocol/Reference/Reference.html
It should have been available over here
Related
Since iOS 11, when the device is offline, network requests are most often fail quickly with a “The Internet connection appears to be offline.” error message (code -1009). Previously – as was the case for iOS version < 11 – request would first try and go through (parts of) the URL loading system.
To serve content to UIWebViews while offline, I rely on a custom subclass of NSURLCache, that returns cached data first, and requests the actual resource from the server afterwards in the background (only if needed/updated), to store for the next request.
I would like to force my app – particular my UIWebViews I’d like to work offline – to still go through the URL loading system, so that my custom NSURLCache is asked for a cached response every time (as was the case before iOS 11). Is this possible?
More background
While the request attempt fails immediately on iOS 11 when the device doesn’t have an internet connection, the OS also introduced the waitsForConnectivity-flag to NSURLSession. This does exactly what I want. However, this only works for my simpler requests that load a single file and that I was able to easily port from a NSURLConnection-request to a NSURLSession-request.
UIWebView still uses NSURLConnection, and so I can’t use NSURLSession and waitsForConnectivity. But: is there another way to force going through the URL loading system and hit my custom NSURLCache implementation?
In my web views, I simply request pages like this:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#“some/url.html" relativeToURL:[NSURL URLWithString:#“https://www.example.com/"]] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30];
[self.webView loadRequest:request];
So, the above used to work and still works for iOS versions < 11. No luck with iOS 11.
I tried several values for the cachePolicy parameter, including NSURLRequestReturnCacheDataDontLoad. Still no luck.
And it’s not as simple as loading/requesting a single HTML file. The pages have lots of resources: CSS files, JS, images etc. And this was all transparently cached by my custom NSURLCache. Sadly no more with iOS 11.
(Now: I’m using a custom subclass of NSURLCache in the first place, because I couldn’t rely on the standard NSURLCache implementation, no matter what configuration and cachePolicy settings. If anyone has a suggestion for a different solution (without a custom NSURLCache) to my problem, I’m definitely listening.)
I'm the maintainer of the Miniprofiler Glimpse plugin and with the latest Miniprofiler versions I'm not able to push data to Glimpse because the Profiler is not yet populated (in previous versions it was) when the GetData() method of the tab is called.
Right now what I do is wrap the Miniprofiler Storage and when the Save() method is called, all the needed information is there but it's too late and I don't know how to send it to the tab.
So, what is the best approach (if possible) to add this information to a tab when it's ready in Miniprofiler?
Unfortunately EndRequest is currently the last moment you can subscribe on to return the necessary data. That is the moment when Glimpse will finalize its monitoring for the given request and the moment it will persist that information to the persistence store.
Although in v1 it is possible to add data after the EndRequest but only when using the default in memory store. So you could return your wrapper, which will be empty at that moment, and it will be stored in memory, allowing you to change the wrapped content afterwards.
But the above will not work for other persistence stores. We might also change this in v2 to make it deterministic, independent of the persistence store being used.
Maybe you could have your wrapper ask MiniProfiler to calculate the results at that moment, so they can be stored, even though those results might not be 100% complete?
We have a long established, greatly multiplatform codebase that is currently being ported to WinRT. One of the challenges we're facing is how to handle WinRT's asynchronous style.
For example, we are unsure how to handle WinRT's async file operations. Unsurprisingly, our codebase's API is synchronous. A typical example is our File::Open function which attempts to open a file and return with success or failure. How can we call WinRT functions and yet keep the behavior of our functions the same?
Note that we are unfortunately constrained by legacy: we cannot simply go and change the API to become asynchronous.
Thanks!
I assume you wish to reimplement the library to support WinRT apps while not changin the definitions of the APIs so that existing applications remain compatible.
I think that if you don't include the await keyword when calling an async method you will not do an async operation, it should execute in a synchronous way. But it really doesn't work if the method returns a value (in my experience).
I've been using this code to make a file operation synchronous:
IAsyncOperation<string> contentAsync = FileIO.ReadTextAsync(file);
contentAsync.AsTask().Wait();
string content = contentAsync.GetResults();
If you want to share your code with a platform that does not support async/await - you are probably better off having a different API for the old platform and the new one with switches like
#if SILVERLIGHT
#elif NETFX_CORE
#elif WPF
#endif
Eventually the async APIs are likely to show up in older platforms and you could actually wrap the non-async calls into Tasks to make them async if they don't. Forcing async method to work synchronously is bound to bite you back rather quickly. Your WinRT app might become unresponsive for a few seconds for example and get killed by the OS. Or you could get deadlocks waiting for tasks to complete and blocking the thread they try to complete on.
I am currently using the NinevehGL engine to develop a simple app. This engine has a class called NGLMesh that stores openGL data for an instance of this class. From NinevehGL's documentation for the copyInstance method located at http://nineveh.gl/docs/Protocols/NGLCopying.html it says:
"The NGLCopying is an extension of Cocoa protocol NSCopying.
It defines two basic copying modes to NinevehGL objects:
Copy: Makes a new clone, copying all the used memory.
Copy Instance: Makes a new clone, but clonning just the superficial memory."
I would like to copy one of my NGLMeshs into a new NGLMesh instance using this method, however Im having a hard time understanding protocols and how to call them. Could someone offer some explanation? The internet has proved to be a little confusing thus far.
From what I gather (although Im most likely wrong) I need to "adopt" the NGLCopying protocol in the class that I want to use it with. I cant seem to find much information on how to accomplish this.
A protocol is just a list of messages that a class can respond to. Think of it as an extension of the class's #interface block, only it can be shared by several classes. If you are just trying to copy another class that already conforms to this protocol (such as NGLMesh), you don't need to do anything special — just do [yourNGLMeshObject copy] or [yourNGLMeshObject copyInstance].
I'm new to Qt. I installed Qt for VS2008 and integrated with my VS2010. I just want to know how to make HTTP requests. I've read about QtNetwork but QtHttp is obselete.
I also know about libcurl and curlpp, but I have problems installing it, and making it work with Qt.
What do you recommend, QtNetwork or curlpp? If QtNetwork, can you please give me a sample function or piece of code (and what class to use). If curlpp(libcurl), can you please point me to somewhere where I can find the steps to install it for Qt (or kindly explain)?
Thank you very much.
libcurl and curlpp are great libraries, but using them adds a dependency to your project that probably you can avoid.
Recent versions of Qt recommend to use QNetworkAccessManager to make network requests (included http requests) and receive replies.
The simplest possible way to download a file is:
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl("http://stackoverflow.com")));
When the replyFinished slot is called, the QNetworkReply object that it takes as parameter will contain the downloaded data as well as meta-data (headers, etc.).
A more complete example can be found in the Qt examples, you can read here its source code.
Giuseppe is right, you don't need to use libcurl, curlpp and similar libraries.
There is no need for that, Qt has a simple and working class on it own.
Keep in mind that the standard way of sending request and retrieving reply is asynchronous.
You always have to connect the manager finished(QNetworkReply*) signal to a slot.
If you send multiple requests and don't want to add a slot for each reply, you can always run an event loop, and connect the managers signal to event loops quit() slot.
Something like this:
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QEventLoop *eventLoop = new QEventLoop();
QObject::connect(manager, SIGNAL(finished(QNetworkReply*)), eventLoop, SLOT(quit());
manager->get(QNetworkRequest(QUrl("http://stackoverflow.com")));
eventLoop->exec(QEventLoop::ExcludeUserInputEvents);
QByteArray replyData = reply->readAll();
... //do what you want with the data your receive from reply
Btw. don't know what are you doing. But if its a mobile app, I would recommend you switch from VS to QtCreator IDE. It has a nice simulator and a complete toolchain for mobile device testing.