[IOS open source code] (5): MKNetworkKit, iosmknetworkkit

Source: Internet
Author: User

[IOS open source code] (5): MKNetworkKit, iosmknetworkkit

ASIHTTPRequest (Author: BenCopsey) is a powerful framework that is easy to use and can be used for various simple to complex HTTP requests, or for processing REST services such as Amazon S3 and Rackspace.

Unfortunately, Ben declared as early as September 21, 2011 that it had stopped development and supported the framework (see http://allseeing-i.com/?5brequest_release=5d ;).

Ben recommends many alternative frameworks (such as AFNetworking, RestKit, or LRResty ). But the most promising is the MKNetworkKit of Mugunth Kumar. Mugunth has released many high-quality open-source iOS/Mac code (such as MKStoreKit). It is recommended that you replace ASHTTPRequest: MKNetworkKit. It supports ARC and block, which is easy to use and extremely efficient.

The following is an excerpt from Mugunth's blog. The original Article is located at: http://blog.mugunthkumar.com/products/ios-framework-introducing-mknetworkkit.

 

Suppose there is a network framework that automatically caches respones for you and automatically remembers your operations when you are offline. What do you think?

When you are offline, you can add a tweet page to your favorites or mark a feed as read. When you go online again, the network framework automatically performs these operations, no additional code is required. See my introduction to the MKNetworkKit framework.

 

What is MKNetworkKit?

MKNetworkKitIs a network framework written by a O-C, supporting blocks, ARC and easy to use.

MKNetworkKit integrates two frameworks: ASIHTTPRequest and AFNetworking. In addition to integrating the excellent features of the two, a bunch of new features are also added. In particular, compared with other frameworks, it allows you to write code more easily. It keeps you away from disgusting network code.

Features

Ultra-Lightweight Framework

The entire framework has only two classes and some category methods. Therefore, it is extremely simple to use.

There is only one global queue in the entire program.

Apps highly dependent on Internet connections should give priority to the number of concurrent network threads. Unfortunately, no network framework is doing well in this regard. Therefore, once you do not control the number of concurrent threads in the program, it is easy to cause errors.

Suppose you want to upload a bunch of images to the server. The vast majority of Mobile Networks (3 GB) will not allow you to have more than two concurrent HTTP connections to the same IP address. In other words, on a device, you cannot obtain more than two concurrent HTTP connections from a 3G network. Edge is worse. In most cases, there cannot be more than one Edge. Compared with the home broadband network (Wifi), this limit is much wider (6 ). However, you cannot always use wifi, and you must also consider the connectivity of a limited network (narrowband. More often, iDevice devices can connect to a 3G network. Therefore, you can only upload two images at the same time. However, the real problem is not slow upload speed, but another situation. When you open a view and try to load thumbnails (different views), the upload thread is run to the background. If you do not control the number of threads in the upload queue, your thumbnail loading times out. This is not normal. The correct method is to optimize the thumbnail loading thread, or let the thread wait until the upload is complete and then load the thumbnail. This requires you to have only one queue in the entire program.

MKNetworkKit uses a singleton in each of its instances to ensure this. It does not mean that MKNetworkKit is a Singleton, but that its shared queue is a singleton.

Correctly display network status indication

Many 3rd-party frameworks use a "increase/decrease in the number of Network Connections" method to display the network status. MKNetworkKit automatically displays the network status due to the use of a single-instance shared queue. One thread in the shared queue observes the operationCount attribute at any time in the KVO mode. Therefore, developers generally do not need to worry about network status display.

If (object ==_ sharedNetworkQueue & [keyPath ispath tostring: @ "operationCount"]) {

[UIApplication sharedApplication]. networkActivityIndicatorVisible = ([_ sharedNetworkQueue. operations count] <0 );

}

Automatically change the queue size

As mentioned above, most mobile networks do not allow more than two concurrent connections. Therefore, you must set the queue size to 2 in a 3G network. MKNetworkKit automatically handles this for you. When the network is 3G/EDGE/GPRS, it will adjust the number of concurrency to 2. When the network is in the Wifi network, it is automatically adjusted to 6. When you load thumbnails from a remote server over a 3G network, this adjustment can bring great benefits.

Automatic Cache

MKNetworkKit can automatically cache all your GET requests. When you initiate the same request again, MKNetworkKit can then call the response cache (if available) and pass it to handler for processing. Of course, it also sends a request to the server. Once the server data is obtained, handler is requested again to process the new data. That is to say, you do not need to cache it manually. You only need to use:

[[MKNetworkEngine sharedEngine] useCache];

Of course, you can override this method (subclass) to customize your cache path and the memory overhead occupied by the cache.

Freeze Network Operations

MKNetworkKit can "freeze" network operations. When a network operation is "Frozen", once the network connection is disconnected, it will be automatically serialized and submitted once when the device is connected again. Similar to the twitter client's "drafts ".

When you submit a tweet, if the network is marked as "Frozen", MKNetworkKit will automatically freeze and store these requests. Therefore, this tweet will be postponed in the future. You do not need to write a line of code throughout the process. You can use this feature for other operations, such as adding a tweet to favorites, sharing a post from the Goolge reader client, and adding a link to Instapaper.

Similar requests only execute one operation

When you load thumbnails (for twitter streams), you will eventually create a new request for each actual image. In fact, all the requests you make are the same URL. MKNetworkKit only executes each GET request in the queue once. It cannot cache POST requests.

Image Cache

MKNetworkKit has built-in thumbnail cache. You can set the maximum number of images cached in the memory and save the cached images to the directory. Of course, you can also ignore these methods.

Performance

That is, speed. MKNetworkKit cache is built-in, such as NSCache. When a memory warning is found, data cached in the memory will be written to the cache directory.

Fully supports ARC

Generally, you only use the new network framework in the new project. MKNetworkKit does not mean to discard the existing framework (you can also give up, which is a tedious job ). For new projects, you always want to use ARC. When you see this article, it is likely that MKNetworkKit will be the only network framework that fully supports ARC. Generally, ARC is faster than non-ARC Code.

Usage

OK, I will not "Boast. Let's immediately understand if this framework is used.

Add MKNetworkKit

  1. Drag the MKNetworkKit directory to the Project
  2. Add the following frameworks: CFNetwork. Framework, SystemConfiguration. framework, Security. framework and ImageIO. Framework.
  3. Include the MKNetworkKit. h header file to the PCH file.
  4. For iOS, delete NSAlert + MKNetworkKitAdditions. h
  5. For Mac, delete UIAlertView + MKNetworkKitAdditions. h

A total of five core files are required. It is a powerful network development kit.

MKNetworkKit class

  1. MKNetworkOperation
  2. MKNetworkEngine
  3. Some tool classes (Apple's Reachability) and categories

I like simplicity. Apple has written the most basic and core network code. What the 3rd-party framework needs is to provide an elegant network queue with a maximum of cache. I think the 3rd-side framework should not have more than 10 classes (whether it is network, UIKit or anything else ). Exceeding this number is too bloated. Three20 is an example. Now the same is true for Development Kit. Although they are excellent, they are still huge and bloated. ASIHttpRequest or AFNetworking is lighter than RESTKit, and JSONKit is lighter than TouchJSON (or any TouchCode library. This is my opinion, but when the Code of a third-party library exceeds 1/3 of the program source code, I will not use it.

It is hard to understand the internal working mechanism of the framework, and it is difficult to customize the framework as needed ). Some Frameworks I have written (for example, MKStoreKit, used for in-app purchases) are always easy to use. I think MKNetworkKit should also be like this. For MKNetworkKit, you need to understand the methods exposed in two classes: MKNetworkOperation and MKNetworkEngine. MKNetworkOperation is like the ASIHttpRequest class. It is an NSOperation subclass that encapsulates your request and response classes. For each network operation, you need to create a MKNetworkOperation.

MKNetworkEngine is a pseudo Singleton class that manages network queues in programs. It is a pseudo-Singleton, that is, for simple requests, you can directly use the method in MKNetworkEngine. You should subclass in-depth customization. Each MKNetworkEngine subclass has its own Reachability object to notify it of the reachability notification from the server. For different REST servers, you can consider creating a separate MKNetworkEngine subclass.

It is a pseudo-Singleton, and each request of its subclass shares a unique queue. You can retain this MKNetworkEngine in the application delegate, just like the managedObjectContext class of CoreData. When MKNetworkKit is used, create a MKNetworkEngine subclass to logically group your network requests. For example, put all Yahoo methods in one class, And all Facebook-related methods into another class. Let's look at three practical examples.

Example 1:

Create a "YahooEngine" to capture the currency exchange rate from the Yahoo financial server.

Step 1:The created YahooEngine class inherits from MKNetworkEngine. MKNetworkEngine uses the host name and the specified header (if any) for initialization. The header information can be nil. If you are on your own REST server, you can consider adding a client app version or other information (such as the client ID ).

NSMutableDictionary * headerFields = [NSMutableDictionary dictionary]; [headerFields setValue: @ "iOS" forKey: @ "x-client-identifier"];

Self. engine = [[YahooEngine alloc] initWithHostName: @ "download.finance.yahoo.com" customHeaderFields: headerFields];

 

Note: yahoo does not recognize that you send x-client-identifier to it in the header. This example only demonstrates this feature

Because the ARC code is used, you need to have (strong reference) Engine objects as developers.

Once you create a MKNetworkEngine subclass, Reachability is automatically implemented. When your server fails due to some circumstances and the host name is inaccessible, your request will be frozen automatically. For more information about "freeze", see the "Freeze operation" section.

Step 2:Design Engine classes (focus on separation)

Now, write methods in Yahoo Engine to capture the exchange rate. These methods will be called in ViewController. A good design experience is to ensure that URLs/HTTPHeaders in the engine class are not exposed to callers. Your view should not know the URL or related parameters. That is, you only need to pass the currency type and currency unit to the engine method. The Return Value of the method may be double, that is, the exchange rate and the time when the exchange rate is obtained. Because it is an asynchronous operation, you should return these values in the block. For example:

-(MKNetworkOperation *) currencyRateFor :( NSString *) sourceCurrency

InCurrency :( NSString *) targetCurrency

OnCompletion :( CurrencyResponseBlock) completion

OnError :( ErrorBlock) error;

In the parent class MKNetworkEngine, three block types are defined:

Typedef void (^ ProgressBlock) (double progress );

Typedef void (^ ResponseBlock) (MKNetworkOperation * operation );

Typedef void (^ ErrorBlock) (NSError * error );

In YahooEngine, we use a new block type:CurrencyResponseBlockTo return the exchange rate. It is defined as follows:

Typedef void (^ CurrencyResponseBlock) (double rate );

In other formal apps, you should define your own block similarCurrencyResponseBlock,Used to return data to ViewController.

Step 3:Process Data
Data processing, including converting the data captured from the server (for example, JSON/XML/plists. This should be done in the Engine. Note: Do not complete it in the controller. Your Engine should return data in an array of appropriate model objects or model objects. Convert JSON/XML into a model in the engine. Note that view controller should not be aware of any key used to access the JSON node if the focus is properly separated. This idea leads the engine design. Many network frameworks do not force you to obey the separation of attention because we have taken it into consideration.

Step 4:Implementation Method
Now let's discuss the implementation details. To obtain the exchange rate information from Yahoo, initiate a GET request. The following macro formats the URL string in a specified currency:

We will now discuss the implementationdetails of the method that calculates your currency exchange.

Getting currency information fromYahoo, is as simple as making a GET request.
I wrote a macro to format this URL for a given currency pair.

# Define YAHOO_URL (_ C1 __, _ C2 _) [NSString stringWithFormat: @ "d/quotes.csv? E=.csv & amp; f = sl1d1t1 & amp; s =%@%@= X ", _ C1 __, _ C2 _]

Compile engine class methods in the following order:

  1. Prepare URL based on parameters
  2. Create a MKNetworkOperation object
  3. Set Method Parameters
  4. Set the completion block and error Block of operation (process response in the completation block and convert it to the Model)
  5. (Optional) Add a progress block (or do this in view controller)
  6. If operation is a download, set the download stream (usually a file ). This step is also optional
  7. When operation is complete, process the result, call the method block, and return the data to the caller.

The sample code is as follows:

MKNetworkOperation * op = [selfoperationWithPath: YAHOO_URL (sourceCurrency, targetCurrency)

Params: nil

HttpMethod: @ "GET"];

 

[Op onCompletion: ^ (MKNetworkOperation * completedOperation)

{

DLog (@ "% @", [completedOperation responseString]);

 

// Do your processing here

CompletionBlock (5.0f );

 

} OnError: ^ (NSError * error ){

 

ErrorBlock (error );

}];

 

[Self enqueueOperation: op];

 

Return op;

The above code formats the URL and creates MKNetworkOperation. After the completion and error blocks are set, the operation is added to the queue (through the enqueueOperation method of the parent class), and an operation reference is returned. Therefore, if you call this method in viewDidAppear, cancel operation in the viewWillDisappear method. Canceling operation will release operation to execute operation for other views in the queue (remember that only two operations can be performed simultaneously in the mobile network, canceling operation when it is no longer needed can improve app performance and speed ).

You can also add a progress block in viewcontroller to refresh the UI. For example:

[Self. uploadOperation onUploadProgressChanged: ^ (double progress ){

DLog (@ "%. 2f", progress * 100.0 );

Self. uploadprogpolicar. progress = progress;}];

MKNetworkEngine also has a useful method for creating operation with only URLs. Therefore, you can write 1st lines of code as follows:

MKNetworkOperation * op = [self operationWithPath: YAHOO_URL (sourceCurrency, targetCurrency)];

Note that the requested URL will be automatically added to the Host Name (specified during engine instantiation ).

 

There are many other practical methods such as MKNetworkEngine. You can view the header file.

Example 2:

Upload images to the server (for example, TwitPic ).
Now let's look at an example of uploading images to the server. To upload images, operation is required to encode multi-part form data. MKNetworkKit uses a method similar to ASIHttpRequest.
You can submit a file as multi-part form data in the request using the addFile: forKey: Method of MKNetworkOperation.

MKNetworkOperation also has a method to submit images in NSData mode. That is, addData: forKey: method. It can upload images to the server as NSData. (For example, an image captured directly from the camera ).

Example 3:

Download an object to a local directory (cache)
Using MKNetworkKit to download files from the server and save them to the local directory of the iPhone is very simple.

You only need to set the outputStream of MKNetworkOperation.

[Operation setDownloadStream: [NSOutputStream outputStreamToFileAtPath: @ "/Users/mugunth/Desktop/downloadedfile#" append: YES];

You can set multiple outputstreams to one operation and save the same file to several places (for example, one is your cache directory and the other is your working directory ).

Example 4:

Thumbnail of the cached Image

For downloading images, you may need to provide an absolute URL address instead of a path.
The operationWithURLString: params: httpMethod of MKNetworkEngine creates a network thread based on the absolute URL address.

MKNetworkEngine is rather intelligent. It combines multiple GET requests of the same URL into one. When operation is completed, it notifies all the blocks. This significantly improves the speed of capturing image URLs to render thumbnails.

Subclass MKNetworkEngine and overwrite the cache directory and cache size of the image. If you do not want to customize the two, you can directly call the method in MKNetworkEngine to download the image. This is what I strongly recommend.

Cache operation

By default, MKNetworkKit caches all requests. All you need is to open it in your own engine. When a GET request is executed, if the last response has been cached, the corresponding completion block will be called with the cached response (instantly ). To determine whether response is cached, you can call the isCachedResponse method as follows:

[Op onCompletion: ^ (MKNetworkOperation * completedOperation ){

If ([completedOperation isCachedResponse]) {

DLog (@ "Data from cache ");

} Else {

DLog (@ "Data from server ");

}

DLog (@ "% @", [completedOperation responseString]);

}

OnError: ^ (NSError * error ){

ErrorBlock (error );

}];

Freeze operation

One of the most interesting features of MKNetworkKit is its built-in freeze operation feature. You only need to set the freeesable attribute of operation. Almost nothing to do!

[Op setFreezable: YES];

Freeze means operation is automatically serialized when the network is disconnected and automatically executed after the network is restored. For example, when you are offline, you can also perform the add-to-favorites tweet operation. Then, when you go online again, operation is automatically resumed.

When the application enters the background, the frozen operation will also be persisted to the disk. After the application returns to the foreground, it will automatically resume execution.

Useful methods in MKNetworkOperation

As shown below, MKNetworkOperation exposes some useful methods from which you can obtain response data in various formats:

  1. ResponseData
  2. ResponseString
  3. ResponseJSON (Only on iOS 5)
  4. ResponseImage
  5. ResponseXML
  6. Error

When operation is completed, these methods are used to obtain response data. If the format is incorrect, the method returns nil. For example, the response data is clearly in an HTML format, and you can only obtain nil using the responseImage method. Only responseData can ensure that no matter what format is returned, and other methods must match the corresponding repsone type.

Useful macros

DLog and ALog macro were shamelessly plagiarized from Stackoverflow and I couldn't find the source author. If you wrote it, please let me know.

About GCD

Because the network thread may be able to be stopped or prioritized, I decisively gave up the GCD--GCD's efficiency is higher than NSOperation, but it cannot do this. I recommend that you do not use a GCD-based queue in your network thread.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.