- 浏览: 340281 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
leslie89757:
[img][img][img][img][img][img][ ...
CocoaPods 安装使用 -
hanmeizhi:
very useful to me. Thanks
Dismissing MPMoviePlayerViewController the right way -
luzj:
这个考虑不周全, 在iOS5的键盘高度就不是这个值了,这样写死 ...
UITextView: move view when keyboard appears -
xjg19870111:
不错。
objective-c NSString 常用操作 -
juedui0769:
现在已经不行了!
android源码下载
原文地址:http://akosma.com/2011/09/20/a-proposed-architecture-for-network-bound-ios-apps/
One of my most popular answers in StackOverflow is the one I gave to the following question: “What is the best architecture for an iOS application that makes many network requests?”
The problem is the following: let’s consider a relatively complex application, which has to connect to, and retrieve and send data from different remote resources (from the same origin or from different ones), all while handling as gracefully as possible different problems such as “network not available”, “500″ errors, etc, while at the same time notifying the app about showing popups, enabling and disabling fields, with many different screens (usually each with its own controller), and so on.
This article will describe in detail a solution for this problem using ASIHTTPRequest, my favorite HTTP library for iOS. The solution involves a bit of object oriented code, and there is a sample implementation in our Senbei project in Github that I am going to refer to in this article.
I want to point out that I do not consider this the “best” architecture by any means; it is simply a pattern or structure that has given me excellent results in many different applications, and which has evolved over time from many other approaches. If someone else has a better idea, I’d be glad to try it! This architecture also has the advantage of being easy to document, understand, maintain and extend.In the answer on StackOverflow I just enumerated the different elements of the architecture; here I will explain the rationale behind every decision.
SINGLETON, “CLASS CLUSTER”
As I said in the answer, this architecture involves a single object taking care of network connectivity, which I will call a “network manager”. Typically this object is a singleton (created using Matt Gallagher’s Cocoa singleton macro). Basically this is because it’s a good way to centralize all the network logic in a single component, and it is also a very common Cocoa design pattern.
This object can also be seen as a class cluster, because it uses an army of individual classes that perform the real work behind the scenes.
In Senbei, this singleton object is the SBNetworkManager class. All the controllers of the application use the methods of this class to trigger asynchronous requests to the remote FFCRM server used by the application. All of these controllers, as well as the application delegate, are notified of events by means of ad hoc notifications (defined in the SBNotifications.h file).
NETWORK QUEUES
The network manager wraps an instance of ASINetworkQueue, and also acts as its delegate. Network queues are interesting in mobile apps, given that the available bandwidth varies drastically when the device is connected through a wifi connection or a low-speed GPRS mobile network. The network queue will automatically change the number of requests sent by unit of time depending on the current connectivity, without clogging the device.
In our example, SBNetworkManager has a private ivar (well, as private as Objective-C allows ivars to be) pointing to an instance of ASINetworkQueue, itself a subclass of NSOperationQueue.
ONE SUBCLASS PER REQUEST
I create subclasses of ASIHTTPRequest for each kind of network request that my app requires (typically, for each backend REST interaction or SOAP endpoint).
I also create a base class for all the requests of the application; this allows to centralize some shared behavior in the base class, which proves handy while extending and refactoring your network code.
In our example, Senbei has a base class for all the GET requests in the application, called SBBaseRequest. There is another base request, called SBBaseFormDataRequest, which is used for requests that use the POST and PUT verbs (used to create and modify resources on the server).
There is also a category on ASIHTTPRequest, to add some methods to any request create on the system; this is required because SBBaseRequest inherits from ASIHTTPRequest, while SBFormDataRequest inherits from ASIHTTPFormDataRequest, which also inherits from ASIHTTPRequest. The category on the latter allows to inject some common behavior in a way that classic inheritance does not allow per se.
For every network interaction in the server, there is a dedicated class available for the SBNetworkManager; the code is easy to understand, and the responsibilities are separated and well defined. Should the system be extended in the future, the extension mechanism will naturally fit any new request, in a horizontal fashion.
The following class diagram (generated from the Xcode project using the excellent OmniGraffle application) shows how the system is structured (you can click the diagram to see a larger version).
POLYMORPHISM TO THE RESCUE
The network manager doesn’t know what to do with the result of each request; hence, it just calls a method on the request. Remember, requests are subclasses of ASIHTTPRequest, so you can just put the code that manages the result of the request (typically, deserialization of JSON or XML into real objects, triggering other network connections, updating Core Data stores, etc). Putting the code into each separate request subclass, using a polymorphic method with a common name accross request classes, makes it very easy to debug and manage them.
In our example, the SBNetworkManager calls the “processResponse” method in each subclass. This method has an empty implementation in our category for ASIHTTPRequest, and each individual subclass performs a different set of operations; some will parse XML, some will just post a notification; the separation of the logic in each subclass makes it easy to debug, document, maintain and extend the system.
USAGE
Every time one of my controllers requires some data (refresh, viewDidAppear, etc), the network manager creates an instance of the required ASIHTTPRequest subclass, and then adds it to the queue.
Whenever a request finishes or fails, the network manager is called (remember, the network manager is the queue’s delegate). In turn, the network manager calls a method on the request itself, delegating the task of the processing of the response to each subclass.
In Senbei, every method of the SBNetworkManager class just creates an instance of a dedicated SBBaseRequest subclass, and pushes it into the wrapped network queue.
NOTIFICATIONS
The network manager notifies the controllers above about interesting events using notifications; using a delegate protocol is not a good idea, because in your app you typically have many controllers talking to your network manager, and notifications are more flexible.
However, as with always with notifications, using them requires planning, naming conventions and documentation. Code using notifications might be complex to maintain, because the dependencies are not obvious at first hand; that’s the price of their flexibility. In Senbei, notifications are all defined in the same file, so that different components can use the same constants throughout the application. The names of the notifications are clear and express the purpose and circumstance of each one.
Since iOS 4 there is also the possibility of using blocks as callback notifications, but then again, I think they just offer an alternative to delegate protocols; notifications are much more flexible, as many different objects can be notified of the same event (and receive the same information through userInfo dictionaries) at once.
CONCLUSION
This is how I’ve been writing many network-bound apps for the past few years, and frankly it has worked pretty well so far. I can extend the system horizontally, adding more ASIHTTPRequest subclasses as I need them, and the core of the network manager stays intact. The responsibilities is clearly separated, and the class and notification names give a pretty good idea of the purpose of each request.
One problem that I haven’t yet solved with this architecture (and one that a commenter of my StackOverflow answer points out) is finding a way to test the system; probably using mock objects, we could simulate different network conditions, and integrate this knowledge with automated tests.
I hope that this architecture is useful to you too! I look forward to read your comments below.
One of my most popular answers in StackOverflow is the one I gave to the following question: “What is the best architecture for an iOS application that makes many network requests?”
The problem is the following: let’s consider a relatively complex application, which has to connect to, and retrieve and send data from different remote resources (from the same origin or from different ones), all while handling as gracefully as possible different problems such as “network not available”, “500″ errors, etc, while at the same time notifying the app about showing popups, enabling and disabling fields, with many different screens (usually each with its own controller), and so on.
This article will describe in detail a solution for this problem using ASIHTTPRequest, my favorite HTTP library for iOS. The solution involves a bit of object oriented code, and there is a sample implementation in our Senbei project in Github that I am going to refer to in this article.
I want to point out that I do not consider this the “best” architecture by any means; it is simply a pattern or structure that has given me excellent results in many different applications, and which has evolved over time from many other approaches. If someone else has a better idea, I’d be glad to try it! This architecture also has the advantage of being easy to document, understand, maintain and extend.In the answer on StackOverflow I just enumerated the different elements of the architecture; here I will explain the rationale behind every decision.
SINGLETON, “CLASS CLUSTER”
As I said in the answer, this architecture involves a single object taking care of network connectivity, which I will call a “network manager”. Typically this object is a singleton (created using Matt Gallagher’s Cocoa singleton macro). Basically this is because it’s a good way to centralize all the network logic in a single component, and it is also a very common Cocoa design pattern.
This object can also be seen as a class cluster, because it uses an army of individual classes that perform the real work behind the scenes.
In Senbei, this singleton object is the SBNetworkManager class. All the controllers of the application use the methods of this class to trigger asynchronous requests to the remote FFCRM server used by the application. All of these controllers, as well as the application delegate, are notified of events by means of ad hoc notifications (defined in the SBNotifications.h file).
NETWORK QUEUES
The network manager wraps an instance of ASINetworkQueue, and also acts as its delegate. Network queues are interesting in mobile apps, given that the available bandwidth varies drastically when the device is connected through a wifi connection or a low-speed GPRS mobile network. The network queue will automatically change the number of requests sent by unit of time depending on the current connectivity, without clogging the device.
In our example, SBNetworkManager has a private ivar (well, as private as Objective-C allows ivars to be) pointing to an instance of ASINetworkQueue, itself a subclass of NSOperationQueue.
ONE SUBCLASS PER REQUEST
I create subclasses of ASIHTTPRequest for each kind of network request that my app requires (typically, for each backend REST interaction or SOAP endpoint).
I also create a base class for all the requests of the application; this allows to centralize some shared behavior in the base class, which proves handy while extending and refactoring your network code.
In our example, Senbei has a base class for all the GET requests in the application, called SBBaseRequest. There is another base request, called SBBaseFormDataRequest, which is used for requests that use the POST and PUT verbs (used to create and modify resources on the server).
There is also a category on ASIHTTPRequest, to add some methods to any request create on the system; this is required because SBBaseRequest inherits from ASIHTTPRequest, while SBFormDataRequest inherits from ASIHTTPFormDataRequest, which also inherits from ASIHTTPRequest. The category on the latter allows to inject some common behavior in a way that classic inheritance does not allow per se.
For every network interaction in the server, there is a dedicated class available for the SBNetworkManager; the code is easy to understand, and the responsibilities are separated and well defined. Should the system be extended in the future, the extension mechanism will naturally fit any new request, in a horizontal fashion.
The following class diagram (generated from the Xcode project using the excellent OmniGraffle application) shows how the system is structured (you can click the diagram to see a larger version).
POLYMORPHISM TO THE RESCUE
The network manager doesn’t know what to do with the result of each request; hence, it just calls a method on the request. Remember, requests are subclasses of ASIHTTPRequest, so you can just put the code that manages the result of the request (typically, deserialization of JSON or XML into real objects, triggering other network connections, updating Core Data stores, etc). Putting the code into each separate request subclass, using a polymorphic method with a common name accross request classes, makes it very easy to debug and manage them.
In our example, the SBNetworkManager calls the “processResponse” method in each subclass. This method has an empty implementation in our category for ASIHTTPRequest, and each individual subclass performs a different set of operations; some will parse XML, some will just post a notification; the separation of the logic in each subclass makes it easy to debug, document, maintain and extend the system.
USAGE
Every time one of my controllers requires some data (refresh, viewDidAppear, etc), the network manager creates an instance of the required ASIHTTPRequest subclass, and then adds it to the queue.
Whenever a request finishes or fails, the network manager is called (remember, the network manager is the queue’s delegate). In turn, the network manager calls a method on the request itself, delegating the task of the processing of the response to each subclass.
In Senbei, every method of the SBNetworkManager class just creates an instance of a dedicated SBBaseRequest subclass, and pushes it into the wrapped network queue.
NOTIFICATIONS
The network manager notifies the controllers above about interesting events using notifications; using a delegate protocol is not a good idea, because in your app you typically have many controllers talking to your network manager, and notifications are more flexible.
However, as with always with notifications, using them requires planning, naming conventions and documentation. Code using notifications might be complex to maintain, because the dependencies are not obvious at first hand; that’s the price of their flexibility. In Senbei, notifications are all defined in the same file, so that different components can use the same constants throughout the application. The names of the notifications are clear and express the purpose and circumstance of each one.
Since iOS 4 there is also the possibility of using blocks as callback notifications, but then again, I think they just offer an alternative to delegate protocols; notifications are much more flexible, as many different objects can be notified of the same event (and receive the same information through userInfo dictionaries) at once.
CONCLUSION
This is how I’ve been writing many network-bound apps for the past few years, and frankly it has worked pretty well so far. I can extend the system horizontally, adding more ASIHTTPRequest subclasses as I need them, and the core of the network manager stays intact. The responsibilities is clearly separated, and the class and notification names give a pretty good idea of the purpose of each request.
One problem that I haven’t yet solved with this architecture (and one that a commenter of my StackOverflow answer points out) is finding a way to test the system; probably using mock objects, we could simulate different network conditions, and integrate this knowledge with automated tests.
I hope that this architecture is useful to you too! I look forward to read your comments below.
发表评论
-
IOS7.1 企业应用 证书无效 已解决
2014-05-10 10:53 774http://www.cocoachina.com/bbs/r ... -
xCode Find&Replace快捷键
2013-10-28 10:44 907As for Find & Replace, they ... -
iOS整合zxing需要注意的地方
2013-08-02 23:34 2106Well, at last I got it working. ... -
iOS 自定义Tabbar
2013-07-30 22:55 1191http://www.appcoda.com/ios-prog ... -
Apple Push Notification Service总结
2013-07-29 22:39 1115苹果推送通知服务使用总结 1. 在 Mac 上从 KeyCha ... -
iOS 消息推送原理及实现
2013-07-12 13:40 856链接: http://www.dapps.net/dev/ ... -
GIMP IMAGE MAP
2013-05-29 16:13 853使用GIMP 制作 IMAGE MAP 1. 选择图片,用G ... -
INSPIRATION
2013-05-27 18:21 813http://www.patternsofdesign.co. ... -
iOS 自定义控件系列
2013-05-27 17:09 1481iOS自定义控件 自定义UITableViewCell ht ... -
CocoaPods 使用教程
2013-05-27 14:49 768http://mobile.tutsplus.com/tuto ... -
IOS 开发之设置UIButton的title
2013-05-11 22:03 1207btn.frame = CGRectMake(x, y, wi ... -
REActivityViewController 使用 备忘
2013-04-22 21:38 1058REActivityViewController Out o ... -
VPS配置二级域名
2013-04-18 23:08 7881. 域名解析商配置泛解析 主机记录 * 记录类型 A 2. ... -
ios 开发NewsStand指南
2013-04-13 21:44 1324http://www.viggiosoft.com/blog/ ... -
Python Django mod_wsgi Windows 部署过程 备忘
2013-04-10 18:28 1587部署环境:Windows2003Server 1. 安装Ap ... -
网站迁移 备忘
2013-04-10 14:58 7511. 备份数据库。。。导出的格式和编码要注意 2. 完全导出网 ... -
Windows下命令行查看端口占用
2013-04-09 23:42 723在windows命令行窗口下执行: C:\>netst ... -
带预览功能又可分页的UIScrollView
2013-04-05 12:56 823带预览功能又可分页的UIScrollView http:// ... -
25 iOS App 性能优化
2013-04-05 10:51 695http://www.raywenderlich.com/ ... -
UIScrollView滚动, 中间显示整图, 前后露出部分图
2013-04-04 00:12 1200UIScrollView *scrollowView = [[ ...
相关推荐
a twofold Siamese network, named SA-Siam, for real-time object tracking. SA-Siam is composed of a semantic branch and an appearance branch. Each branch is a similarity- learning Siamese network. An ...
To reduce annotation efforts, self-supervised semantic segmentation is recently proposed to pre-train a network without any human-provided labels. The key of this new form of learning is to design a ...
problems is to construct a binary classifier for each label, resulting in a set of independent bi- nary classification problems. Since multiple labels share the same input space, and the seman- tics ...
根据提供的文件内容,我们可以提取以下知识点: 1. IEEE 802.16d技术背景及应用: IEEE 802.16d是一种宽带无线接入系统标准,其特点是提供高带宽接入以及服务质量(QoS)连接到核心网络的能力。...
Non-negative matrix factorization (NMF) can be formulated as a minimization problem with bound constraints. Although bound-constrained optimization has been studied extensively in both theory and ...
Logarithmic Voltage-to-Time Converter for Analog-to-Digital Signal ConversionThis book presents a novel logarithmic conversion architecture based on cross-coupled inverter. An overview of the current ...
we propose a low-cost sequential and high performance architecture for the implementation of CORDIC algorithm in two computation modes. It suited for serial operation that performs conversion between ...
5. 基础设施网络:项目提出的"Proposed Network"旨在改善现有封闭系统,创建未来Patroon Greenway,连接中央大道、办公园区、西部大道和华盛顿大道等,这反映了对城市基础设施的重新配置和优化,以提升城市交通效率...
The results show that the proposed approach achieves consistent and substantial improvements, compared to six state-of-the-art systems. In particular, our approach outperforms the best reported error ...
In relation extraction for knowledge-based question answering, searching from one entity to another entity via a single relation is called “one hop”. In related work, an exhaustivesearchfromallone-...
To achieve this, we incorporate these statistical correlations into deep neural networks to facilitate scene graph generation by developing a Knowledge-Embedded Routing Network. More specifically, ...
A buffer allocation algorithm based on self-similar queuing model is proposed, with the consideration of self-similar communication characteristics of Networks-on-Chip and virtualchannels. It ...
Most real-world recommender services measure their ...demonstrate that the proposed model is a generalization of several well-known collaborative filtering models but with more flexible components.
In this paper, a general probable 5G cellular network architecture is proposed, which shows that D2D, small cell access points, network cloud, and the Internet of Things can be a part of 5G cellular ...
Network intrusion detection systems (NIDSs) play a crucial role in defending computer networks. However, there are ...
To exploit the parallelism of optics in data processing, a suitable number system and an efficient encoding/decoding scheme for handling the data are very essential. In the field of optical computing ...