NSURLConnection for iOS network development and programming
Well-known third-party libraries at the iOS network layer, such as ASIHTTPRequest, AFNetworking, and MKNetworkKit. As the ASI is no longer updated, the landlord has basically followed the large army to use AF. AF uses the Cocoa-layer API-NSURLConnection.
I used NSURLConnection in the past. I am not very familiar with many related methods. I took the time to study the NSURLConnection and summarized the usage of NSURLConnection in the evening.
1. attributes and methods of NSURLConnection.
Go to NSURLConnection. h to introduce all methods from top to bottom.
@ Interface NSURLConnection: NSObject
{
@ Private
NSURLConnectionInternal * _ internal;
}
/* Designated initializer */
/*
Create an NSURLConnection. Only the connection is established and no data is downloaded.
Request: request content
Delegate: NSURLConnectionDelegate, the NSURLConnection instance will strongly reference delegate until the callback didFinishLoading, didFailWithErrorNSURLConnection. cancel call. (During the download the connection maintains a strong reference to
delegate. It releases that strong reference when the connection finishes loading, fails, or is canceled)
StartImmediately: whether to download data immediately. YES: download the data immediately and add the connection to the current runloop. NO, only establish connections, do not download data, need to manually
[Connection start] starts to download data.
*/
-(Instancetype) initWithRequest :( NSURLRequest *) request delegate :( id) delegate startImmediately :( BOOL) startImmediately NS_AVAILABLE (10_5, 2_0 );
/*
Actually, [self initWithRequest: request delegate: delegate startImmediately: YES];
Call [connection start] When you do not need to display]
*/
-(Instancetype) initWithRequest :( NSURLRequest *) request delegate :( id) delegate;
/*
Actually, [self initWithRequest: request delegate: delegate startImmediately: YES];
Call [connection start] When you do not need to display]
*/
+ (NSURLConnection *) connectionWithRequest :( NSURLRequest *) request delegate :( id) delegate;
/*
Requests used to establish a connection
*/
@ Property (readonly, copy) NSURLRequest * originalRequestNS_AVAILABLE (10_8, 5_0 );
/*
The authentication protocol for connection establishment requests may change.
As the connection performs the load,
This request may change as a result of protocol
Canonicalization or due to following redirects.
-CurrentRequest can be used to retrieve this value.
*/
@ Property (readonly, copy) NSURLRequest * currentRequestNS_AVAILABLE (10_8, 5_0 );
/*
Start to download data. Use-(instancetype) initWithRequest :( NSURLRequest *) request delegate :( id) delegate startImmediately :( BOOL) startImmediately to call the connection start]
*/
-(Void) startNS_AVAILABLE (10_5, 2_0 );
/*
Disconnect the network and cancel the request. The cancel method cannot guarantee that the proxy callback will not be called immediately (it should be the requested data and can only be passed to the proxy). cancel will release delegate
*/
-(Void) cancel;
/*
Add the connection instance callback to a runloop. The NSURLConnectionDelegate callback will respond in this runloop.
Note that this method cannot be set at the same time as setDelegateQueue. You can only select one.
*/
-(Void) scheduleInRunLoop :( nsunloop *) aRunLoop forMode :( NSString *) modeNS_AVAILABLE (10_5, 2_0 );
/*
Cancel the callback in this runloop.
*/
-(Void) unscheduleFromRunLoop :( nsunloop *) aRunLoop forMode :( NSString *) modeNS_AVAILABLE (10_5, 2_0 );
/*
If a queue is set, the callback will be performed on this queue. A callback is similar to adding an NSBlockOperation to the queue.
Note that this method cannot be set at the same time as scheduleInRunLoop. You can only select one.
*/
-(Void) setDelegateQueue :( NSOperationQueue *) queueNS_AVAILABLE (10_7, 5_0 );
@ Interface NSURLConnection (NSURLConnectionSynchronousLoading)
/*
Class to create a synchronization request. This method is based on Asynchronization and then blocks the implementation of the current thread.
Response: response Header Information, passing a two-dimensional pointer
Error: status of the request result
*/
+ (NSData *) sendSynchronousRequest :( NSURLRequest *) request returningResponse :( NSURLResponse **) response error :( NSError **) error;
@ End
@ Interface NSURLConnection (NSURLConnectionQueuedLoading)
/*
Initiate an asynchronous request
Queue: completionHandler will run in this queue
CompletionHandler: Request callback block
*/
+ (Void) sendAsynchronousRequest :( NSURLRequest *) request
Queue :( NSOperationQueue *) queue
CompletionHandler :( void (^) (NSURLResponse * response, NSData * data, NSError * connectionError) handlerNS_AVAILABLE (10_7, 5_0 );
@ End
Ii. NSURLConnection usage
The above method is almost introduced. Try writing a few demos.
First, define some basic configurations.
Static char * const URLSTRING = "http://f.hiphotos.baidu.com/image/h%3D200/sign=a1217b1330fa828bce239ae3cd1f41cd/0e2442a7d933c895cc5c676dd21373f082020081.jpg ";
-(NSURLRequest *) request {
NSString * urlString = [nsstringstringwithuf8string: URLSTRING];
NSURL * url = [NSURLURLWithString: urlString];
NSURLRequest * request = [NSURLRequestrequestWithURL: url
CachePolicy: NSURLRequestReloadIgnoringLocalAndRemoteCacheData
TimeoutInterval: 30.f];
Return request;
}
In addition, an NSURLConnectionDelegate class is abstracted to implement NSURLConnectionDelegate. In this way, you do not need to write a lot of protocols when using NSURLConnection elsewhere.
# Import
Typedefvoid (^ NSURLConnectionCompeletionBlock) (id );
@ Interface NSURLConnectionDelegate: NSObject
@ Property (nonatomic, strong, readonly) NSOutputStream * OS;
@ Property (nonatomic, assign, readonly) BOOL isFinish;
@ Property (nonatomic, strong, readonly) NSMutableData * buffer;
@ Property (nonatomic, assign, readonly) NSUInteger contentLength;
@ Property (nonatomic, strong) NSURLConnectionCompeletionBlock completionBlock;
@ End
# Import "NSURLConnectionDelegate. h"
@ Implementation NSURLConnectionDelegate
-(Void) dealloc
{
NSLog (@ "__% s _" ,__ FUNCTION __);
}
-(Void) connectionDidFinishLoading :( NSURLConnection *) connection {
If (self. completionBlock ){
Self. completionBlock ([self. ospropertyForKey: NSStreamDataWrittenToMemoryStreamKey]);
}
[Self. osclose];
_ IsFinish = YES;
}
-(Void) connection :( NSURLConnection *) connection didReceiveResponse :( NSURLResponse *) responsez {
If ([responsez isKindOfClass: [NSHTTPURLResponseclass]) {
NSHTTPURLResponse * hr = (NSHTTPURLResponse *) responsez;
If (hr. statusCode = 200 ){
_ ContentLength = hr. expectedContentLength;
// _ OS = [NSOutputStream outputStreamToFileAtPath: [NSHomeDirectory () stringByAppendingPathComponent: @ "Documents/image.jpg"] append: NO];
_ OS = [NSOutputStreamoutputStreamToMemory];
[_ Osopen];
}
}
}
-(Void) connection :( NSURLConnection *) connection didFailWithError :( NSError *) error {
If (self. completionBlock ){
NSError * error = [NSErrorerrorWithDomain: error. domain
Code: error. code
UserInfo: error. userInfo];
Self. completionBlock (error );
}
_ IsFinish = YES;
[Self. osclose];
}
-(Void) connection :( NSURLConnection *) connection didReceiveData :( NSData *) data {
If (! Self. buffer ){
_ Buffer = [NSMutableDatadataWithCapacity: self. contentLength];
}
[Self. bufferappendData: data];
//
NSUInteger totalLength = data. length;
NSUInteger totalWirte = 0;
Const uint8_t * datas = data. bytes;
While (totalWirte <totalLength ){
/*
The number of bytes actually written, or-1 if an error occurs. more information about the error can be obtained with streamError. if the specified er is a fixed-length stream and has reached its capacity, 0 is returned.
*/
NSInteger writeLength = [self. oswrite: & datas [totalWirte] maxLength :( totalLength-totalWirte)];
If (writeLength =-1 ){
[Connectioncancel];
Break;
}
TotalWirte + = writeLength;
NSLog (@ "totalLenght = % lu, totalWirte = % lu", totalLength, totalWirte );
}
}
Write NSOperation together
# Import
@ Interface NSURLConnectionOperation: NSOperation
@ Property (nonatomic, strong) NSURLRequest * request;
@ Property (nonatomic, strong) NSData * buffer;
-(Instancetype) initWithRequest :( NSURLRequest *) request;
-(Void) startAsync;
@ End
# Import "NSURLConnectionOperation. h"
# Import "NSURLConnectionDelegate. h"
@ Interface NSURLConnectionOperation ()
@ Property (nonatomic, assign, getter = isExecuting) BOOL executing;
@ Property (nonatomic, assign, getter = isFinished) BOOL finished;
@ Property (nonatomic, assign, getter = isConcurrent) BOOL concurrent;
@ Property (nonatomic, strong) NSThread * thread;
@ Property (nonatomic, strong) NSURLConnection * connection;
@ End
@ Implementation NSURLConnectionOperation
@ Synthesize executing = _ executing, finished = _ finished, concurrent = _ concurrent;
-(Void) dealloc
{
NSLog (@ "% s" ,__ FUNCTION __);
}
-(Instancetype) initWithRequest :( NSURLRequest *) request {
Self = [superinit];
If (self ){
Self. request = request;
}
Return self;
}
-(Void) start {
If (! Self. thread ){
_ Thread = [NSThreadcurrentThread];
}
Self. finished = NO;
Self.exe cuting = YES;
_ WeakNSURLConnectionOperation * wkSelf = self;
NSURLConnectionDelegate * delegate = [NSURLConnectionDelegatenew];
Delegate. completionBlock = ^ (id data ){
If (! WkSelf. buffer ){
WkSelf. buffer = data;
}
// Broadcast the notification and execute completionBlock
WkSelf. finished = YES;
WkSelf.exe cuting = NO;
};
_ Connection = [[NSURLConnectionalloc] initWithRequest: self. request
Delegate: delegate // keep delegate strongly referenced
StartImmediately: NO];
// Manually set runloop to default before start
[_ ConnectionscheduleInRunLoop: [nsunloopcurrentrunloop] forMode: NSDefaultRunLoopMode];
[_ Connection start];
While (! Self. isFinished ){
[[Nsunloopcurrentrunloop] runMode: NSDefaultRunLoopModebeforeDate: [NSDatedistantFuture];
}
NSLog (@ "start end !! ");
}
-(Void) startAsync {
_ Thread = [[NSThreadalloc] initWithTarget: selfselector: @ selector (start) object: nil];
[Self. threadstart];
}
-(Void) setFinished :( BOOL) finished {
[SelfwillChangeValueForKey: @ "isFinished"];
_ Finished = finished;
[SelfdidChangeValueForKey: @ "isFinished"];
}
-(Void) setExecuting :( BOOL) executing {
[SelfwillChangeValueForKey: @ "isExecuting"];
_ Executing = executing;
[SelfdidChangeValueForKey: @ "isExecuting"];
}
-(BOOL) isConcurrent {
Return YES;
}
@ End
Synchronous request:
-(IBAction) sync :( id) sender {
[SelfprintGO];
//
NSURLResponse * response = nil;
NSError * error = nil;
NSData * data = [NSURLConnectionsendSynchronousRequest: [selfrequest]
ReturningResponse: & response
Error: & error];
NSLog (@ "get sync data! ");
If ([response isKindOfClass: [NSHTTPURLResponseclass]) {
NSHTTPURLResponse * hr = (NSHTTPURLResponse *) response;
If (hr. statusCode = 200 ){
NSLog (@ "sync repsonse head: \ n % @", hr. allHeaderFields );
Self. imageView. image = [UIImageimageWithData: data];
}
}
[SelfprintEnd];
}
-(IBAction) sync :( id) sender {
[SelfprintGO];
NSURLConnectionOperation * operation = [[NSURLConnectionOperationalloc] initWithRequest: [selfrequest];
_ Weak NSURLConnectionOperation * wkOp = operation;
Operation. completionBlock = ^ {
_ StrongNSURLConnectionOperation * sOp = wkOp; // prevents wkOp from being released and strongly referenced
NSLog (@ "set? ");
Dispatch_async (dispatch_get_main_queue (), ^ {
Self. imageView. image = [uiimagewithdata: sOp. buffer];
});
};
[Operationstart];
[SelfprintEnd];
}
Asynchronous request:
-(IBAction) async :( id) sender {
[SelfprintGO];
// **************************** NSURLConnection async
// This method can only initiate a simple request and wait for the result, which is inconvenient for statistics.
[NSURLConnectionsendAsynchronousRequest: [selfrequest]
Queue: self. queue // completionHandler run on this queue
CompletionHandler: ^ (NSURLResponse * response, NSData * data, NSError * connectionError ){
If ([response isKindOfClass: [NSHTTPURLResponseclass]) {
NSHTTPURLResponse * hr = (NSHTTPURLResponse *) response;
If (hr. statusCode = 200 ){
[SelfprintCurrentThread];
Self. imageView. image = [UIImageimageWithData: data];
}
}
}];
[SelfprintEnd];
}
-(IBAction) async :( id) sender {
[SelfprintGO];
NSURLConnectionDelegate * connectionDelegate = [NSURLConnectionDelegatenew];
ConnectionDelegate. completionBlock = ^ (id data ){
[SelfprintCurrentThread];
If ([data isKindOfClass: [NSDataclass]) {
[[NSOperationQueuemainQueue] addOperationWithBlock: ^ {
Self. imageView. image = [UIImageimageWithData: data];
}];
}
};
NSURLConnection * connection = [[NSURLConnectionalloc] initWithRequest: [selfrequest] delegate: connectionDelegate];
// The delegate callback is completed in the thread opened by the current operationqueue
// [Connection scheduleInRunLoop: [nsunloop currentRunLoop] forMode: NSDefaultRunLoopMode];
[ConnectionsetDelegateQueue: self. queue];
[Connectionstart];
[SelfprintEnd];
}