I'm planning my first iPhone app and I'd like to get some inputs as to how to build it, right from the start. The iPhone app is being built to be paired with a public facing web application that is already built in PHP.
我正在计划我的第一个iPhone应用程序,我想从一开始就得到一些关于如何构建它的输入。iPhone应用程序正在与一个已经用PHP构建的面向公众的web应用程序进行配对。
I'd like the web platform to be central (data is housed in a mySQL database), and have the iPhone clients talk to it and use REST'ful methods to perform the functions of the site (fetching latest content, posting content, voting, account management as examples).
我希望web平台是中心的(数据存储在mySQL数据库中),让iPhone客户端与之对话,并使用REST方法来执行站点的功能(获取最新内容、发布内容、投票、帐户管理等示例)。
I'd like the clients to get a local copy of the data in a SQLite database, but refresh to get the latest version of the feed (similar to the Twitter app).
我希望客户端在SQLite数据库中获得数据的本地副本,但是请刷新以获得提要的最新版本(类似于Twitter应用程序)。
Couple of thoughts I have right now:
我现在有几个想法:
-
Use something like ASIHTTPRequest to send/recieve data to PHP files on the server listening for requests
使用ASIHTTPRequest之类的工具将数据发送/接收到服务器上监听请求的PHP文件
-
JSON - would I be better off to send the GET/POSTS to a PHP that returns JSON objects, and work with some sort of wrapper that manages the data and communicates changes to the local SQLite database?
JSON——我最好将GET/POSTS发送到返回JSON对象的PHP,并使用某种包装器来管理数据并将更改传递到本地SQLite数据库吗?
-
Am I totally off in how I should be building this thing to communicate with the web? Is there a best practice for this?
我是否完全不知道我应该如何构建这个东西来与网络交流?有什么最佳实践吗?
I'd really appreciate any input on how you would architect this sort of a setup.
我非常感谢您对如何构建这种设置的任何建议。
Thank you,
谢谢你!
EDIT: After reading my own post again, I know it sounds like a Twitter client, but it is NOT, although it has similar features/structure of a Twitter type setup. Thanks!
编辑:我再次阅读了我自己的帖子,我知道它听起来像Twitter客户端,但它不是,尽管它有类似Twitter类型设置的特性/结构。谢谢!
6 个解决方案
#1
17
As you already outlined in your plan, XML and REST are a great way to communicate with a web application. I want to suggest few details about how to actually design and build it, or what you should keep in mind.
正如您在计划中已经介绍的,XML和REST是与web应用程序通信的一种很好的方式。关于如何设计和构建它,或者您应该记住什么,我想提出一些细节。
First of all, I believe it's important to stick with MVC. I've seen people creating HTTP connections in view-controllers, controllers being NSXMLParser's delegate, controllers containing data in member variables. I've even seen UITableCells establishing HTTP connections. Don't do it!
首先,我认为坚持使用MVC非常重要。我见过有人在视图控制器中创建HTTP连接,控制器是NSXMLParser的委托,控制器包含成员变量中的数据。我甚至见过UITableCells建立HTTP连接。不要这样做!
Your model and its basic manipulation code should be as much extracted from user interface as possible. As you already have created the model in your web-application, try to recreate the entities in your iPhone project. Don't be afraid of having some simple methods in entity classes, but do not make them use external resources, especially tcp connections. As an example of methods in entity class you might have methods that formats data in specific ways (dates as an example, or returning fullname as concatenation of firstname and surname), or you can even have a method like - (void)update
that would act as a wrapper to call class responsible to update the model.
模型及其基本操作代码应该尽可能多地从用户界面中提取。既然已经在web应用程序中创建了模型,那么尝试在iPhone项目中重新创建实体。不要害怕在实体类中有一些简单的方法,但是不要让它们使用外部资源,特别是tcp连接。作为实体类中的方法的一个例子你可能格式数据的方法在具体方面(日期作为一个例子,或返回fullname firstname和姓)的连接,或者你甚至可以有一个方法- - -(void)更新,将作为一个包装器类负责更新模型。
Create another class for updating the model - fetching the XMLs from web-app. Do not even consider using synchronous connections, not even from a dedicated thread. Asynchronous connections with delegate is the way to go. Sometimes multiple requests need to be made to get all required data. You might want to create some kind of state-machine to keep the information about in which stage of downloading you are, and progress from stage to stage, skipping to the end if error occurs, re-executing from failed stage after some moments.
创建另一个类来更新模型——从web应用程序获取xml。甚至不要考虑使用同步连接,甚至不要使用专用线程。使用委托进行异步连接是可行的。有时需要发出多个请求来获取所有必需的数据。您可能想要创建某种状态机,以保存关于您在哪个阶段下载的信息,并从一个阶段进行到另一个阶段,如果发生错误就跳转到最后,然后在失败的阶段中重新执行。
Download data somewhere temporarily, and first when you have it all, make a switch and update user interface. This helps responsiveness during launching the app - user gets to work immediately with data stored locally, while the update mechanism is downloading the new data.
暂时从某处下载数据,当您拥有所有数据时,首先进行切换并更新用户界面。这有助于启动应用程序时的响应能力——用户可以立即使用本地存储的数据,而更新机制正在下载新数据。
If you need to download lots of files, try to download them simultaneously, if dependencies between files allow for that. This involves creating a connection per request, probably delegate instance for each of them. You can of course have only one delegate instance for all of those connections, but it gets a bit more complex to track the data. Downloading simultaneously might decrease latency considerably, making the mechanism much faster for the user.
如果需要下载大量文件,请尝试同时下载,如果文件之间的依赖关系允许的话。这涉及到为每个请求创建一个连接,可能为每个请求分配实例。当然,对于所有这些连接,只能有一个委托实例,但是跟踪数据会变得有点复杂。同时下载可能会大大降低延迟,使用户的机制更快。
To save the time and bandwidth, consider using HTTP's If-Modified-Since
and/or ETag
headers. Remember the time or tag when you requested the data the last time, and next time send it in HTTP's header. Your web-application should return HTTP code 304 if content has not been changed. iPhone app should react on this code accordingly in connection:didReceiveResponse:
.
为了节省时间和带宽,考虑使用HTTP的If-Modified-Since和/或ETag头。请记住上次请求数据时的时间或标记,下次再将它发送到HTTP头。如果内容没有更改,您的web应用程序应该返回HTTP代码304。iPhone应用程序在连接:didReceiveResponse:时应该对该代码做出相应的反应。
Create a dedicated class to parse the XML and update the model. You can use NSXMLParser, but if your files are not huge I strongly recommend TouchXML, it's such a pleasure to work with XML as document (it also supports XPath), instead of an event based API. You can use this parser also when files are downloaded to check their validity - re-download if parsing fails. That's when dedicated class for parsing comes handy.
创建一个专用类来解析XML并更新模型。您可以使用NSXMLParser,但如果您的文件不是很大,我强烈建议使用TouchXML,那么使用XML作为文档(它也支持XPath)而不是基于事件的API是非常愉快的。当下载文件检查其有效性时,也可以使用此解析器——如果解析失败,则重新下载。这时解析专用类就派上用场了。
If your dataset is not huge, if you do not need to persist downloaded data on iPhone forever, you probably don't need to store them in SQLite database, you can simply store them in XML format - just a simple caching. That at least might be the way for a twitter app. It gets easier that way, but for bigger data sets XML consumes lots of memory and processing power - in that case SQLite is better.
如果您的数据集不是很大,如果您不需要在iPhone上永久保存下载的数据,您可能不需要将它们存储在SQLite数据库中,您可以简单地以XML格式存储它们——只需一个简单的缓存。这至少可能是twitter应用程序的一种方式。
I'd suggest using Core Data, but you mention this is your first iPhone app, so I suggest you don't use it. Yet.
我建议使用Core Data,但是你提到这是你的第一个iPhone应用,所以我建议你不要使用它。然而。
Do not forget about multitasking - your app can go to sleep in the middle of download, you need to cancel connections, and cleanup your update mechanisms. On app's wake-up you might want to resume the update.
不要忘记多任务处理——你的应用程序可以在下载过程中休眠,你需要取消连接,并清理更新机制。在应用程序的唤醒,你可能想要恢复更新。
Regarding the view part of the application - use Interface Builder. It might be painful in the beginning, but it pays off in the long run.
关于应用程序的视图部分——使用接口构建器。一开始可能会很痛苦,但从长远来看会有回报。
View controllers are the glue between model and views. Do not store data in there. Think twice about what to implement where, and who should call it.
视图控制器是模型和视图之间的粘合剂。不要在那里存储数据。在哪里实现什么,以及谁应该调用它时,请三思。
This is not related to architecture of the app, but I want to remind that Objective-C is very expressive language. Code should read much like a sentence. Extend classes with protocols. As an example the other day I needed first line of a string. Sure, you can write a one-liner where you find first occurrence of a new-line, and get a substring from beginning till there. But it doesn't look right. I've added - (NSString*)firstLine
into my NSString's protocol. Code looks so much better this way, it doesn't need any comments.
这与app的架构没有关系,但我想提醒大家Objective-C是一种很有表现力的语言。代码应该读起来像一个句子。扩展类和协议。有一天,我需要一个字符串的第一行。当然,您可以编写一行代码,在其中找到新行的第一次出现,并从开始到那里获得子字符串。但看起来不太对。我在NSString的协议中添加了- (NSString*)第一行。代码以这种方式看起来更好,不需要任何注释。
There are lots of things to consider in both architecture and design of any project, they both should go hand in hand. If one is causing trouble to the other, you need to adapt. Nothing is written in stone.
在任何项目的架构和设计中都需要考虑很多东西,它们都应该同时进行。如果其中一个给另一个带来麻烦,你需要适应。没有东西是用石头写的。
#2
3
I'm currently working on an app that sounds similar to yours. I'd also suggest ASIHTTPRequest, and probably something like TouchJSON for JSON parsing, or extending/making a delegate of NSXMLParser if you want to parse XML.
我正在开发一个听起来和你的很相似的应用。我还建议使用ASIHTTPRequest,可能还建议使用TouchJSON解析,或者扩展/创建NSXMLParser委托(如果你想解析XML的话)。
As suggested by JosephH, depending on how your app works you may want to consider alternate authentication methods: I'd take a look at something token-based like OAuth, which has ready-made libraries for people to dig in to.
正如JosephH所建议的,取决于你的应用程序的工作方式,你可能需要考虑其他的认证方法:我想看看像OAuth这样的基于标记的东西,它有现成的库供人们挖掘。
SQLite is totally viable for feed caching, although I prefer NSCoding so that you can freeze-dry your custom data structures.
SQLite完全可以用于提要缓存,尽管我更喜欢NSCoding,这样您就可以对自定义数据结构进行冻干。
As a general suggestion, make sure to spend a lot of time thinking about every use case and corner case for connections: it's easy to assume a user will only contact the server in certain ways and at certain times, and then after you throw in multitasking/incoming calls/lock screen/memory warnings, things can get hairy without any planning.
一般建议,一定要花大量的时间思考每个用例和角落的连接:很容易假设一个用户只会联系服务器以某种方式,在某些时候,你之后扔在多任务/来电/锁屏/内存警告,事情可能会变得毛没有任何计划。
All in all, you seem to be on the right track, just make sure you plan out everything beforehand :)
总而言之,你似乎走在了正确的道路上,只要事先做好计划就可以了。
#3
3
Apple have a brand new in depth piece of sample code - MVCNetworking that shows in depth how to use subclasses of NSHTTPRequests and NSOperationQueues.
苹果有一个全新的深入的示例代码——MVCNetworking,它深入地展示了如何使用nshttprequest和NSOperationQueues的子类。
#4
2
As others mentioned, I think you are asking the right questions and are heading in the right direction. All of the replies above are valuable advice. Here is my advice, and I hope you'll find it useful.
正如其他人提到的,我认为你们提出的问题是正确的,并且正在朝着正确的方向前进。以上所有的回答都是宝贵的建议。这是我的建议,我希望你会觉得它有用。
No matter which method/library you choose to talk to your web services, I think it's important to make a clean separation in the way you design your data model on the phone VS. the data model in your web application. You have 3 major distinctions to keep in mind for your design:
无论您选择哪种方法/库与web服务进行对话,我认为在设计电话上的数据模型与web应用程序中的数据模型的方式之间进行清晰的分离是很重要的。你的设计需要记住三个主要的区别:
-
Data model on the web application (reflected by your existing mySQL database)
web应用程序上的数据模型(由现有的mySQL数据库反映)
Since this is already there, there is not much to say about it, except that it will influence a lot your design for the following 2 parts. I suggest to make this model the 'master reference' for how your data is represented across platforms.
既然它已经存在了,就没什么好说的了,除了它会对你接下来的两个部分的设计产生很大的影响。我建议将此模型作为跨平台表示数据的“主引用”。
-
Data model on the iPhone app (reflected by the information you need to display in the iPhone app)
iPhone应用的数据模型(体现在你需要在iPhone应用中显示的信息上)
This is where the fun begins. First, you need a good understanding of what data you need to display in the phone app. So have a good, high level design of your app first (use pen and paper, draw mock-ups of each view and the interactions between them, model the navigation between your view controllers etc.). It really helps to understand the interactions between your view controllers and the various bits and pieces of data you want to show in the app. This will help you create the requirements for the data model on the phone. Based on these requirements, map the existing (web) data model to a new model, suited to your iPhone app. This new model may or may not include all tables and fields found in your web app. But the general representation of the 2 models should be very similar (e.g. relationships, data types, etc.)
这就是乐趣的开始。首先,你需要很好地理解你需要在手机应用中显示什么数据。因此,首先要对你的应用进行好的、高水平的设计(使用笔和纸,绘制每个视图的实物模型以及它们之间的交互,建模视图控制器之间的导航等等)。理解视图控制器和你想要在应用中显示的各种数据之间的交互非常有帮助。这将帮助你在手机上创建数据模型的需求。基于这些需求,现有的(网络)数据模型映射到一种新的模式,适合你的iPhone应用程序。这个新模型可能或不可能包括所有的表和字段中发现您的web应用程序。但2模型的一般表示应该非常相似(如关系、数据类型等)。
-
Data model used to communicate between the 2 above (this is your 'data exchange protocol')
用于在上述2之间通信的数据模型(这是您的“数据交换协议”)
Once you have the 2 representations of your data above, you need to 'translate' from one to the other, both ways. Design your data exchange protocol to be as simple and compact as possible. You don't want to waste bytes on useless information, as transmissions over the network are costly. (As a side note, you might think of compressing the transmitted data later on, but it's just as important to have a good design from the beginning). It's probably best to begin with a protocol in which the metadata is the same as the one in your web application model (e.g. same relationships, names of tables, attributes, etc.). But remember, you'll only have to serialize/de-serialize those entities and relationships that you listed in point 2) above. So design accordingly. Your exchange protocol may also include session tokens, authentication info, a version number, or other metadata, if you need it.
一旦你有了上面两个数据的表示,你需要从一个“翻译”到另一个,两种方式。设计你的数据交换协议尽可能简单和紧凑。您不希望将字节浪费在无用的信息上,因为通过网络传输是昂贵的。(作为附带说明,您可能会考虑稍后对传输的数据进行压缩,但是从一开始就有一个好的设计也是同样重要的)。最好从一个协议开始,其中元数据与web应用程序模型中的元数据是相同的(例如,相同的关系、表的名称、属性等等)。但是请记住,您只需要序列化/反序列化上面第2点列出的那些实体和关系。所以相应的设计。您的exchange协议还可以包括会话令牌、身份验证信息、版本号或其他元数据,如果您需要的话。
Remember: your data exchange protocol is what will de-couple your web application and iPhone application models. I found that it's best to de-couple them because they may both evolve over time. The data model on the iPhone for example, may evolve a lot especially when you will find that you need to re-model some relationships or add/remove attributes from your entities in order to improve application responsiveness, or the user experience, the navigation, or whatever.
请记住:您的数据交换协议将消除您的web应用程序和iPhone应用程序模型。我发现最好将它们分开,因为它们可能随着时间的推移而进化。例如,iPhone上的数据模型可能会有很大的变化,尤其是当您发现需要重新建模某些关系或从实体中添加/删除属性以提高应用程序响应性、用户体验、导航或其他功能时。
Since this is a whole concern in and by itself, well, you need to design a generic serialization/de-serialization mechanism on top of your (JSON/XML/whatever parser you choose) that is flexible enough to sustain the potential differences between your 2 data models. These differences might be: entity/attribute/relationship names, primary key identifier names, data types, attributes to ignore, and the list goes on. I would definitely implement a serializer/de-serializer utility class in the iPhone app, backed by a .plist configuration file containing all supported entities, concerns, aliases you might have. Of course, each model object should 'know' how to serialize, de-serialize itself and its relationships (i.e. the required object graph depth).
由于这本身就是一个需要考虑的问题,您需要在您的(JSON/XML/任何您选择的解析器)之上设计一个通用的序列化/反序列化机制,该机制足够灵活,能够支持两个数据模型之间的潜在差异。这些差异可能是:实体/属性/关系名称、主键标识符名称、数据类型、忽略的属性,以及列表。我肯定会在iPhone应用程序中实现一个serializer/de-serializer实用工具类,它由一个.plist配置文件支持,该文件包含所有可能支持的实体、关注点和别名。当然,每个模型对象都应该“知道”如何序列化、反序列化自身及其关系(即所需的对象图深度)。
One last note, since you will end up with 2 representations of your data, you will need a way to uniquely identify an object on both sides. So for example, think of adding a
uuid
attribute to all data that needs to be exchanged, or use any other approach that suits your needs.最后要注意的是,由于您将得到数据的两个表示形式,因此您需要一种方法来惟一地标识两边的对象。例如,考虑为需要交换的所有数据添加uuid属性,或者使用任何满足您需求的其他方法。
I am building an app that has similar requirements to yours, and these are the approaches I found to be best so far. Also, you might find this video useful (it inspired me a lot on how to implement some of the issues I mentioned above and is especially interesting if you're using CoreData) :
我正在开发一个应用程序,它和你的程序有相似的需求,这些是我发现到目前为止最好的方法。此外,你可能会发现这段视频很有用(它启发了我很多关于如何实现我上面提到的一些问题的想法,如果你使用CoreData,它会特别有趣):
http://itunes.apple.com/ca/podcast/linkedin-important-life-lessons/id384233225?i=85092597 (see the lecture entitled "LinkedIn: Important Life Lessons on CoreData & GameKit (March 12, 2010)" )
http://itunes.apple.com/ca/podcast/linkedin-important-life-lessons/id384233225?i=85092597(参见“LinkedIn: CoreData & GameKit上的重要人生课程”讲座,2010年3月12日))
Good luck!
好运!
#5
1
It's quite a broad question, and I think you're going in the right way anyway, however I'll do my best to give some advice:
这是一个很宽泛的问题,我认为你的方法是正确的,但是我将尽力给出一些建议:
JSON, ASIHTTPRequest and POSTs to PHP scripts sound like a great way to go.
JSON、ASIHTTPRequest和PHP脚本的发布听起来是一个不错的选择。
If the data is not really sensitive, I'd use http most of the time, and use https only for a login page that either sets a cookie or returns a "token" that you use in subsequent requests. (HTTPS can be quite slow over a 3G connection as the overhead in terms of number of packets to setup an SSL connection is higher than a plain TCP connection.)
如果数据不是非常敏感,我大多数时候都会使用http,并且只对登录页面使用https,登录页面可以设置cookie或返回在后续请求中使用的“token”。(在3G连接上,HTTPS的传输速度可能会相当慢,因为设置SSL连接的数据包数量比普通的TCP连接要高。)
You should make sure you correctly pass any data from the input to the PHP scripts to the database, to avoid any SQL injection attacks - ie. used parameterised SQL, don't create sql queries by doing "SELECT * from users where username="+$_GET['username']
"
您应该确保正确地将输入的任何数据传递给PHP脚本到数据库,以避免任何SQL注入攻击——即。使用参数化的SQL,不要通过在用户名= +$_GET['username']的用户中执行"SELECT * "来创建SQL查询。
#6
0
I would do this like I have done with a lot of AJAX web-page stuff. i.e.:
我可以像做很多AJAX web页面那样做。例如:
-
Have a URL on your server side package the information to be transmitted into XML format. (This can be through a CGI/PHP script or whatever). Your transmitting XML in the message body - so it's easy to human read and debug with a standard web browser.
在服务器端设置一个URL,将要传输到XML格式的信息打包。(这可以通过CGI/PHP脚本或其他什么)。在消息体中传输XML——因此使用标准web浏览器进行人工读取和调试很容易。
-
Use the standard iPhone NSXMLParser methods to parse out the individual data fields from the XML doc, and write it back to your database. This method is equiped to both fetch the data from a URL and parse it in one call - like:
使用标准的iPhone NSXMLParser方法解析XML文档中的单个数据字段,并将其写回数据库。该方法既可以从URL获取数据,又可以在一次调用中解析数据:
NSURL *xmlURL = [NSURL URLWithString:@"http://www.example.com/livefeed.cgi"]; NSXMLParser *myParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
- Walk through the data hierarchy with the NSXMLParser methods and populate your database accordingly.
- 使用NSXMLParser方法遍历数据层次结构并相应地填充数据库。
#1
17
As you already outlined in your plan, XML and REST are a great way to communicate with a web application. I want to suggest few details about how to actually design and build it, or what you should keep in mind.
正如您在计划中已经介绍的,XML和REST是与web应用程序通信的一种很好的方式。关于如何设计和构建它,或者您应该记住什么,我想提出一些细节。
First of all, I believe it's important to stick with MVC. I've seen people creating HTTP connections in view-controllers, controllers being NSXMLParser's delegate, controllers containing data in member variables. I've even seen UITableCells establishing HTTP connections. Don't do it!
首先,我认为坚持使用MVC非常重要。我见过有人在视图控制器中创建HTTP连接,控制器是NSXMLParser的委托,控制器包含成员变量中的数据。我甚至见过UITableCells建立HTTP连接。不要这样做!
Your model and its basic manipulation code should be as much extracted from user interface as possible. As you already have created the model in your web-application, try to recreate the entities in your iPhone project. Don't be afraid of having some simple methods in entity classes, but do not make them use external resources, especially tcp connections. As an example of methods in entity class you might have methods that formats data in specific ways (dates as an example, or returning fullname as concatenation of firstname and surname), or you can even have a method like - (void)update
that would act as a wrapper to call class responsible to update the model.
模型及其基本操作代码应该尽可能多地从用户界面中提取。既然已经在web应用程序中创建了模型,那么尝试在iPhone项目中重新创建实体。不要害怕在实体类中有一些简单的方法,但是不要让它们使用外部资源,特别是tcp连接。作为实体类中的方法的一个例子你可能格式数据的方法在具体方面(日期作为一个例子,或返回fullname firstname和姓)的连接,或者你甚至可以有一个方法- - -(void)更新,将作为一个包装器类负责更新模型。
Create another class for updating the model - fetching the XMLs from web-app. Do not even consider using synchronous connections, not even from a dedicated thread. Asynchronous connections with delegate is the way to go. Sometimes multiple requests need to be made to get all required data. You might want to create some kind of state-machine to keep the information about in which stage of downloading you are, and progress from stage to stage, skipping to the end if error occurs, re-executing from failed stage after some moments.
创建另一个类来更新模型——从web应用程序获取xml。甚至不要考虑使用同步连接,甚至不要使用专用线程。使用委托进行异步连接是可行的。有时需要发出多个请求来获取所有必需的数据。您可能想要创建某种状态机,以保存关于您在哪个阶段下载的信息,并从一个阶段进行到另一个阶段,如果发生错误就跳转到最后,然后在失败的阶段中重新执行。
Download data somewhere temporarily, and first when you have it all, make a switch and update user interface. This helps responsiveness during launching the app - user gets to work immediately with data stored locally, while the update mechanism is downloading the new data.
暂时从某处下载数据,当您拥有所有数据时,首先进行切换并更新用户界面。这有助于启动应用程序时的响应能力——用户可以立即使用本地存储的数据,而更新机制正在下载新数据。
If you need to download lots of files, try to download them simultaneously, if dependencies between files allow for that. This involves creating a connection per request, probably delegate instance for each of them. You can of course have only one delegate instance for all of those connections, but it gets a bit more complex to track the data. Downloading simultaneously might decrease latency considerably, making the mechanism much faster for the user.
如果需要下载大量文件,请尝试同时下载,如果文件之间的依赖关系允许的话。这涉及到为每个请求创建一个连接,可能为每个请求分配实例。当然,对于所有这些连接,只能有一个委托实例,但是跟踪数据会变得有点复杂。同时下载可能会大大降低延迟,使用户的机制更快。
To save the time and bandwidth, consider using HTTP's If-Modified-Since
and/or ETag
headers. Remember the time or tag when you requested the data the last time, and next time send it in HTTP's header. Your web-application should return HTTP code 304 if content has not been changed. iPhone app should react on this code accordingly in connection:didReceiveResponse:
.
为了节省时间和带宽,考虑使用HTTP的If-Modified-Since和/或ETag头。请记住上次请求数据时的时间或标记,下次再将它发送到HTTP头。如果内容没有更改,您的web应用程序应该返回HTTP代码304。iPhone应用程序在连接:didReceiveResponse:时应该对该代码做出相应的反应。
Create a dedicated class to parse the XML and update the model. You can use NSXMLParser, but if your files are not huge I strongly recommend TouchXML, it's such a pleasure to work with XML as document (it also supports XPath), instead of an event based API. You can use this parser also when files are downloaded to check their validity - re-download if parsing fails. That's when dedicated class for parsing comes handy.
创建一个专用类来解析XML并更新模型。您可以使用NSXMLParser,但如果您的文件不是很大,我强烈建议使用TouchXML,那么使用XML作为文档(它也支持XPath)而不是基于事件的API是非常愉快的。当下载文件检查其有效性时,也可以使用此解析器——如果解析失败,则重新下载。这时解析专用类就派上用场了。
If your dataset is not huge, if you do not need to persist downloaded data on iPhone forever, you probably don't need to store them in SQLite database, you can simply store them in XML format - just a simple caching. That at least might be the way for a twitter app. It gets easier that way, but for bigger data sets XML consumes lots of memory and processing power - in that case SQLite is better.
如果您的数据集不是很大,如果您不需要在iPhone上永久保存下载的数据,您可能不需要将它们存储在SQLite数据库中,您可以简单地以XML格式存储它们——只需一个简单的缓存。这至少可能是twitter应用程序的一种方式。
I'd suggest using Core Data, but you mention this is your first iPhone app, so I suggest you don't use it. Yet.
我建议使用Core Data,但是你提到这是你的第一个iPhone应用,所以我建议你不要使用它。然而。
Do not forget about multitasking - your app can go to sleep in the middle of download, you need to cancel connections, and cleanup your update mechanisms. On app's wake-up you might want to resume the update.
不要忘记多任务处理——你的应用程序可以在下载过程中休眠,你需要取消连接,并清理更新机制。在应用程序的唤醒,你可能想要恢复更新。
Regarding the view part of the application - use Interface Builder. It might be painful in the beginning, but it pays off in the long run.
关于应用程序的视图部分——使用接口构建器。一开始可能会很痛苦,但从长远来看会有回报。
View controllers are the glue between model and views. Do not store data in there. Think twice about what to implement where, and who should call it.
视图控制器是模型和视图之间的粘合剂。不要在那里存储数据。在哪里实现什么,以及谁应该调用它时,请三思。
This is not related to architecture of the app, but I want to remind that Objective-C is very expressive language. Code should read much like a sentence. Extend classes with protocols. As an example the other day I needed first line of a string. Sure, you can write a one-liner where you find first occurrence of a new-line, and get a substring from beginning till there. But it doesn't look right. I've added - (NSString*)firstLine
into my NSString's protocol. Code looks so much better this way, it doesn't need any comments.
这与app的架构没有关系,但我想提醒大家Objective-C是一种很有表现力的语言。代码应该读起来像一个句子。扩展类和协议。有一天,我需要一个字符串的第一行。当然,您可以编写一行代码,在其中找到新行的第一次出现,并从开始到那里获得子字符串。但看起来不太对。我在NSString的协议中添加了- (NSString*)第一行。代码以这种方式看起来更好,不需要任何注释。
There are lots of things to consider in both architecture and design of any project, they both should go hand in hand. If one is causing trouble to the other, you need to adapt. Nothing is written in stone.
在任何项目的架构和设计中都需要考虑很多东西,它们都应该同时进行。如果其中一个给另一个带来麻烦,你需要适应。没有东西是用石头写的。
#2
3
I'm currently working on an app that sounds similar to yours. I'd also suggest ASIHTTPRequest, and probably something like TouchJSON for JSON parsing, or extending/making a delegate of NSXMLParser if you want to parse XML.
我正在开发一个听起来和你的很相似的应用。我还建议使用ASIHTTPRequest,可能还建议使用TouchJSON解析,或者扩展/创建NSXMLParser委托(如果你想解析XML的话)。
As suggested by JosephH, depending on how your app works you may want to consider alternate authentication methods: I'd take a look at something token-based like OAuth, which has ready-made libraries for people to dig in to.
正如JosephH所建议的,取决于你的应用程序的工作方式,你可能需要考虑其他的认证方法:我想看看像OAuth这样的基于标记的东西,它有现成的库供人们挖掘。
SQLite is totally viable for feed caching, although I prefer NSCoding so that you can freeze-dry your custom data structures.
SQLite完全可以用于提要缓存,尽管我更喜欢NSCoding,这样您就可以对自定义数据结构进行冻干。
As a general suggestion, make sure to spend a lot of time thinking about every use case and corner case for connections: it's easy to assume a user will only contact the server in certain ways and at certain times, and then after you throw in multitasking/incoming calls/lock screen/memory warnings, things can get hairy without any planning.
一般建议,一定要花大量的时间思考每个用例和角落的连接:很容易假设一个用户只会联系服务器以某种方式,在某些时候,你之后扔在多任务/来电/锁屏/内存警告,事情可能会变得毛没有任何计划。
All in all, you seem to be on the right track, just make sure you plan out everything beforehand :)
总而言之,你似乎走在了正确的道路上,只要事先做好计划就可以了。
#3
3
Apple have a brand new in depth piece of sample code - MVCNetworking that shows in depth how to use subclasses of NSHTTPRequests and NSOperationQueues.
苹果有一个全新的深入的示例代码——MVCNetworking,它深入地展示了如何使用nshttprequest和NSOperationQueues的子类。
#4
2
As others mentioned, I think you are asking the right questions and are heading in the right direction. All of the replies above are valuable advice. Here is my advice, and I hope you'll find it useful.
正如其他人提到的,我认为你们提出的问题是正确的,并且正在朝着正确的方向前进。以上所有的回答都是宝贵的建议。这是我的建议,我希望你会觉得它有用。
No matter which method/library you choose to talk to your web services, I think it's important to make a clean separation in the way you design your data model on the phone VS. the data model in your web application. You have 3 major distinctions to keep in mind for your design:
无论您选择哪种方法/库与web服务进行对话,我认为在设计电话上的数据模型与web应用程序中的数据模型的方式之间进行清晰的分离是很重要的。你的设计需要记住三个主要的区别:
-
Data model on the web application (reflected by your existing mySQL database)
web应用程序上的数据模型(由现有的mySQL数据库反映)
Since this is already there, there is not much to say about it, except that it will influence a lot your design for the following 2 parts. I suggest to make this model the 'master reference' for how your data is represented across platforms.
既然它已经存在了,就没什么好说的了,除了它会对你接下来的两个部分的设计产生很大的影响。我建议将此模型作为跨平台表示数据的“主引用”。
-
Data model on the iPhone app (reflected by the information you need to display in the iPhone app)
iPhone应用的数据模型(体现在你需要在iPhone应用中显示的信息上)
This is where the fun begins. First, you need a good understanding of what data you need to display in the phone app. So have a good, high level design of your app first (use pen and paper, draw mock-ups of each view and the interactions between them, model the navigation between your view controllers etc.). It really helps to understand the interactions between your view controllers and the various bits and pieces of data you want to show in the app. This will help you create the requirements for the data model on the phone. Based on these requirements, map the existing (web) data model to a new model, suited to your iPhone app. This new model may or may not include all tables and fields found in your web app. But the general representation of the 2 models should be very similar (e.g. relationships, data types, etc.)
这就是乐趣的开始。首先,你需要很好地理解你需要在手机应用中显示什么数据。因此,首先要对你的应用进行好的、高水平的设计(使用笔和纸,绘制每个视图的实物模型以及它们之间的交互,建模视图控制器之间的导航等等)。理解视图控制器和你想要在应用中显示的各种数据之间的交互非常有帮助。这将帮助你在手机上创建数据模型的需求。基于这些需求,现有的(网络)数据模型映射到一种新的模式,适合你的iPhone应用程序。这个新模型可能或不可能包括所有的表和字段中发现您的web应用程序。但2模型的一般表示应该非常相似(如关系、数据类型等)。
-
Data model used to communicate between the 2 above (this is your 'data exchange protocol')
用于在上述2之间通信的数据模型(这是您的“数据交换协议”)
Once you have the 2 representations of your data above, you need to 'translate' from one to the other, both ways. Design your data exchange protocol to be as simple and compact as possible. You don't want to waste bytes on useless information, as transmissions over the network are costly. (As a side note, you might think of compressing the transmitted data later on, but it's just as important to have a good design from the beginning). It's probably best to begin with a protocol in which the metadata is the same as the one in your web application model (e.g. same relationships, names of tables, attributes, etc.). But remember, you'll only have to serialize/de-serialize those entities and relationships that you listed in point 2) above. So design accordingly. Your exchange protocol may also include session tokens, authentication info, a version number, or other metadata, if you need it.
一旦你有了上面两个数据的表示,你需要从一个“翻译”到另一个,两种方式。设计你的数据交换协议尽可能简单和紧凑。您不希望将字节浪费在无用的信息上,因为通过网络传输是昂贵的。(作为附带说明,您可能会考虑稍后对传输的数据进行压缩,但是从一开始就有一个好的设计也是同样重要的)。最好从一个协议开始,其中元数据与web应用程序模型中的元数据是相同的(例如,相同的关系、表的名称、属性等等)。但是请记住,您只需要序列化/反序列化上面第2点列出的那些实体和关系。所以相应的设计。您的exchange协议还可以包括会话令牌、身份验证信息、版本号或其他元数据,如果您需要的话。
Remember: your data exchange protocol is what will de-couple your web application and iPhone application models. I found that it's best to de-couple them because they may both evolve over time. The data model on the iPhone for example, may evolve a lot especially when you will find that you need to re-model some relationships or add/remove attributes from your entities in order to improve application responsiveness, or the user experience, the navigation, or whatever.
请记住:您的数据交换协议将消除您的web应用程序和iPhone应用程序模型。我发现最好将它们分开,因为它们可能随着时间的推移而进化。例如,iPhone上的数据模型可能会有很大的变化,尤其是当您发现需要重新建模某些关系或从实体中添加/删除属性以提高应用程序响应性、用户体验、导航或其他功能时。
Since this is a whole concern in and by itself, well, you need to design a generic serialization/de-serialization mechanism on top of your (JSON/XML/whatever parser you choose) that is flexible enough to sustain the potential differences between your 2 data models. These differences might be: entity/attribute/relationship names, primary key identifier names, data types, attributes to ignore, and the list goes on. I would definitely implement a serializer/de-serializer utility class in the iPhone app, backed by a .plist configuration file containing all supported entities, concerns, aliases you might have. Of course, each model object should 'know' how to serialize, de-serialize itself and its relationships (i.e. the required object graph depth).
由于这本身就是一个需要考虑的问题,您需要在您的(JSON/XML/任何您选择的解析器)之上设计一个通用的序列化/反序列化机制,该机制足够灵活,能够支持两个数据模型之间的潜在差异。这些差异可能是:实体/属性/关系名称、主键标识符名称、数据类型、忽略的属性,以及列表。我肯定会在iPhone应用程序中实现一个serializer/de-serializer实用工具类,它由一个.plist配置文件支持,该文件包含所有可能支持的实体、关注点和别名。当然,每个模型对象都应该“知道”如何序列化、反序列化自身及其关系(即所需的对象图深度)。
One last note, since you will end up with 2 representations of your data, you will need a way to uniquely identify an object on both sides. So for example, think of adding a
uuid
attribute to all data that needs to be exchanged, or use any other approach that suits your needs.最后要注意的是,由于您将得到数据的两个表示形式,因此您需要一种方法来惟一地标识两边的对象。例如,考虑为需要交换的所有数据添加uuid属性,或者使用任何满足您需求的其他方法。
I am building an app that has similar requirements to yours, and these are the approaches I found to be best so far. Also, you might find this video useful (it inspired me a lot on how to implement some of the issues I mentioned above and is especially interesting if you're using CoreData) :
我正在开发一个应用程序,它和你的程序有相似的需求,这些是我发现到目前为止最好的方法。此外,你可能会发现这段视频很有用(它启发了我很多关于如何实现我上面提到的一些问题的想法,如果你使用CoreData,它会特别有趣):
http://itunes.apple.com/ca/podcast/linkedin-important-life-lessons/id384233225?i=85092597 (see the lecture entitled "LinkedIn: Important Life Lessons on CoreData & GameKit (March 12, 2010)" )
http://itunes.apple.com/ca/podcast/linkedin-important-life-lessons/id384233225?i=85092597(参见“LinkedIn: CoreData & GameKit上的重要人生课程”讲座,2010年3月12日))
Good luck!
好运!
#5
1
It's quite a broad question, and I think you're going in the right way anyway, however I'll do my best to give some advice:
这是一个很宽泛的问题,我认为你的方法是正确的,但是我将尽力给出一些建议:
JSON, ASIHTTPRequest and POSTs to PHP scripts sound like a great way to go.
JSON、ASIHTTPRequest和PHP脚本的发布听起来是一个不错的选择。
If the data is not really sensitive, I'd use http most of the time, and use https only for a login page that either sets a cookie or returns a "token" that you use in subsequent requests. (HTTPS can be quite slow over a 3G connection as the overhead in terms of number of packets to setup an SSL connection is higher than a plain TCP connection.)
如果数据不是非常敏感,我大多数时候都会使用http,并且只对登录页面使用https,登录页面可以设置cookie或返回在后续请求中使用的“token”。(在3G连接上,HTTPS的传输速度可能会相当慢,因为设置SSL连接的数据包数量比普通的TCP连接要高。)
You should make sure you correctly pass any data from the input to the PHP scripts to the database, to avoid any SQL injection attacks - ie. used parameterised SQL, don't create sql queries by doing "SELECT * from users where username="+$_GET['username']
"
您应该确保正确地将输入的任何数据传递给PHP脚本到数据库,以避免任何SQL注入攻击——即。使用参数化的SQL,不要通过在用户名= +$_GET['username']的用户中执行"SELECT * "来创建SQL查询。
#6
0
I would do this like I have done with a lot of AJAX web-page stuff. i.e.:
我可以像做很多AJAX web页面那样做。例如:
-
Have a URL on your server side package the information to be transmitted into XML format. (This can be through a CGI/PHP script or whatever). Your transmitting XML in the message body - so it's easy to human read and debug with a standard web browser.
在服务器端设置一个URL,将要传输到XML格式的信息打包。(这可以通过CGI/PHP脚本或其他什么)。在消息体中传输XML——因此使用标准web浏览器进行人工读取和调试很容易。
-
Use the standard iPhone NSXMLParser methods to parse out the individual data fields from the XML doc, and write it back to your database. This method is equiped to both fetch the data from a URL and parse it in one call - like:
使用标准的iPhone NSXMLParser方法解析XML文档中的单个数据字段,并将其写回数据库。该方法既可以从URL获取数据,又可以在一次调用中解析数据:
NSURL *xmlURL = [NSURL URLWithString:@"http://www.example.com/livefeed.cgi"]; NSXMLParser *myParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
- Walk through the data hierarchy with the NSXMLParser methods and populate your database accordingly.
- 使用NSXMLParser方法遍历数据层次结构并相应地填充数据库。