`
isiqi
  • 浏览: 16552091 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

iPhone开发技巧之网络篇(1)--- 解析XML

阅读更多

开发 iPhone 上的网络应用程序的时候时常需要解析XML文档,比如web应用中的SOAP,REST,RSS信息等都是以XML为基础的。掌握XML解析的技术是很重要的。这里我将为大家介绍一下iPhone下解析XML的几种方法,并比较其性能。

iPhone的XML库

iPhone中标准的XML解析库有两个,分贝是libxml2和NSXMLParser。

libxml2由Gnome项目开发、由于是MIT的开放协议,已经移植到许多的平台,在iPhone上也能使用。

libxml2的特点是比较快。另外作为最基本的XML解析器,提供SAX和DOM解析。并且它对应的XML标准最多,比如名称空间、XPath、XPointer、HTML、XInclude、XSLT、XML Schema、Relax NG等。另外它是用C语言写的,比较高速。

NSXMLParser是Cocoa中内含的XML解析器。它只提供了SAX解析的功能。因为是Cocoa的一部分、并且API是Objective-C的,所以与Mac系统兼容性强,使用也相对简单。

XML解析与内存占用

由于iPhone也是一种嵌入式设备,所以与其他的嵌入式设备一样,同样有内存,CPU等资源占用问题。所以在选择代码库的时候需要考虑性能与内存占用的问题。

一般XML的解析器有SAX解析和DOM解析两种方式、相比之下SAX比较小巧精干,耗费的内存小。这是因为其设计思想与DOM完全不一样,一边得到数据一边解析,由回调的方式通知得到的数据,没有了DOM树的概念。

现在的iPhone 3G搭载的RAM是128MB(3GS是256MB)。其中有iPhone OS本身使用的、还有根据用于使用情况不同,比如MP3,邮件,Safari等常驻程序等。基本上自己的程序可使用的内存大小是10MB左右的空间。

开发XML解析程序的时候,需要注意到XML文件一般都比较大,如果使用DOM的话,消费的内存量肯定很多。所以在iPhone中上面这两种解析器只能使用SAX的解析方式。DOM方式只能在模拟器上使用(比如NSXMLDocument类),放到实际设备上就不管用了。(不过,在下面的章节中我将介绍一种使用DOM的第三方方法,对于小的XML文档还是值得一用的。)

libxml2 vs NSXMLParser

一般是使用libxml2的SAX解析器呢,还是使用NSXMLParser能,我们通过下面的SDK中附属的例子XMLPerformance来做个测试。

相同的XML文档由网络下载,然后解析,比较的结果如下 :

下载用时 解析用时 合计
NSXMLParser 1.419s 5.525s 7.134s
libxml2 2.520s 2.247s 2.646s

可以看到,libxml2比NSXMLParser快得多。这与它们处理的方式有些关系,NSXMLParser中调用SAX API的时候,参数是作为字符串传递的,需要先转换为NSString或者是NSDictionary对象,并且它不像libxml2那样是一边下载一边解析,需要整个文件下载完了才开始解析。所以说建议一般使用libxml2。

NSXMLParser的例子

解析的XML代码例子如下:

1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<users>
    <user name="hoge" age="20" />
    <user name="fuga" age="30" />
</users>

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
static NSString *feedURLString = @"http://www.yifeiyang.net/test/test.xml";

- (void)parserDidStartDocument:(NSXMLParser *)parser
{
    // 解析开始时的处理
}

- (void)parseXMLFileAtURL:(NSURL *)URL parseError:(NSError **)error
{
    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:URL];
    [parser setDelegate:self];
    [parser setShouldProcessNamespaces:NO];
    [parser setShouldReportNamespacePrefixes:NO];
    [parser setShouldResolveExternalEntities:NO];
    [parser parse];
    NSError *parseError = [parser parserError];
    if (parseError && error) {
        *error = parseError;
    }
    [parser release];
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    // 元素开始句柄
    if (qName) {
        elementName = qName;
    }
    if ([elementName isEqualToString:@"user"]) {
        // 输出属性值
        NSLog(@"Name is %@ , Age is %@", [attributeDict objectForKey:@"name"], [attributeDict objectForKey:@"age"]);
    }
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    // 元素终了句柄
    if (qName) {
        elementName = qName;
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    // 取得元素的text
}

NSError *parseError = nil;
[self parseXMLFileAtURL:[NSURL URLWithString:feedURLString] parseError:&parseError];

实际使用的时候除最后两行以外,所有的当如一个类中,最后两个是启动该类的代码。

libxml2的例子

项目中添加libxml

首先需要将libxml添加到你的工程项目中。

我们知道,当向项目中添加外部库的时候,如果是程序框架的,比如UIKit.framework,Foundation.framework等放在Sysytem/Library/Frameworks 目录下。SDK放在 /Developer/Platforms/iPhoneOS.platform/Developer/SDKs 目录下。

但是由于libxml是UNIX的库、位于SDK文件夹的usr/lib下。头文件位于 usr/include 下。


iphone libxml2

在 libxml 目录下将 libxml2.2.dylib(或更高版本)添加到项目中。将头文件路径 usr/include/libxml2 也添加到包含路径中。

以下是libxml2.2.dylib的路径
/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS${VER}sdk/usr/lib/libxml2.2.dylib
以下是头文件的路径
/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS${VER}.sdk/usr/include/libxml2


iphone libxml2

libxml中的SAX解析器

用过SAX解析器的朋友都知道,SAX就是事先登录一些处理函数,当XML解析到属性或要素的时候,回调登录的处理函数。

以下是一个例子,DownloadOperation实现网络文件的下载,同时交给libxml2的SAX解析器处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// DownloadOperation.h
#import <Foundation/Foundation.h>
#import <libxml/tree.h>

@interface DownloadOperation : NSOperation
{
    NSURLRequest*           _request;
    NSURLConnection*        _connection;
    xmlParserCtxtPtr        _parserContext;
    BOOL                    _isExecuting, _isFinished;

    BOOL                    _isChannel, _isItem;
    NSMutableDictionary*    _channel;
    NSMutableDictionary*    _currentItem;
    NSMutableString*        _currentCharacters;
}

// Property
@property (readonly) NSDictionary* channel;

// Initialize
- (id)initWithRequest:(NSURLRequest*)request;

@end

首先、#import了libxml/tree.h头文件。然后声明了一个 xmlParserCtxtPtr 变量作为解析器的实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
// DownloadOperation.m

#import "DownloadOperation.h"

@interface DownloadOperation (private)

- (void)startElementLocalName:(const xmlChar*)localname
        prefix:(const xmlChar*)prefix
        URI:(const xmlChar*)URI
        nb_namespaces:(int)nb_namespaces
        namespaces:(const xmlChar**)namespaces
        nb_attributes:(int)nb_attributes
        nb_defaulted:(int)nb_defaulted
        attributes:(const xmlChar**)attributes;

- (void)endElementLocalName:(const xmlChar*)localname
        prefix:(const xmlChar*)prefix URI:(const xmlChar*)URI;

- (void)charactersFound:(const xmlChar*)ch
        len:(int)len;

@end

static void startElementHandler(
        void* ctx,
        const xmlChar* localname,
        const xmlChar* prefix,
        const xmlChar* URI,
        int nb_namespaces,
        const xmlChar** namespaces,
        int nb_attributes,
        int nb_defaulted,
        const xmlChar** attributes)
{
    [(DownloadOperation*)ctx
            startElementLocalName:localname
            prefix:prefix URI:URI
            nb_namespaces:nb_namespaces
            namespaces:namespaces
            nb_attributes:nb_attributes
            nb_defaulted:nb_defaulted
            attributes:attributes];
}

static void endElementHandler(
        void* ctx,
        const xmlChar* localname,
        const xmlChar* prefix,
        const xmlChar* URI)
{
    [(DownloadOperation*)ctx
            endElementLocalName:localname
            prefix:prefix
            URI:URI];
}

static void charactersFoundHandler(
        void* ctx,
        const xmlChar* ch,
        int len)
{
    [(DownloadOperation*)ctx
            charactersFound:ch len:len];
}

static xmlSAXHandler _saxHandlerStruct = {
    NULL,            /* internalSubset */
    NULL,            /* isStandalone   */
    NULL,            /* hasInternalSubset */
    NULL,            /* hasExternalSubset */
    NULL,            /* resolveEntity */
    NULL,            /* getEntity */
    NULL,            /* entityDecl */
    NULL,            /* notationDecl */
    NULL,            /* attributeDecl */
    NULL,            /* elementDecl */
    NULL,            /* unparsedEntityDecl */
    NULL,            /* setDocumentLocator */
    NULL,            /* startDocument */
    NULL,            /* endDocument */
    NULL,            /* startElement*/
    NULL,            /* endElement */
    NULL,            /* reference */
    charactersFoundHandler, /* characters */
    NULL,            /* ignorableWhitespace */
    NULL,            /* processingInstruction */
    NULL,            /* comment */
    NULL,            /* warning */
    NULL,            /* error */
    NULL,            /* fatalError //: unused error() get all the errors */
    NULL,            /* getParameterEntity */
    NULL,            /* cdataBlock */
    NULL,            /* externalSubset */
    XML_SAX2_MAGIC,  /* initialized */
    NULL,            /* private */
    startElementHandler,    /* startElementNs */
    endElementHandler,      /* endElementNs */
    NULL,            /* serror */
};

@implementation DownloadOperation

// Property
@synthesize channel = _channel;

//--------------------------------------------------------------//
#pragma mark -- Initialize --
//--------------------------------------------------------------//

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key
{
    if ([key isEqualToString:@"isExecuting"] ||
        [key isEqualToString:@"isFinished"])
    {
        return YES;
    }

    return [super automaticallyNotifiesObserversForKey:key];
}

- (id)initWithRequest:(NSURLRequest*)request
{
    if (![super init]) {
        return nil;
    }

    // 实例初始化
    _request = [request retain];
    _isExecuting = NO;
    _isFinished = NO;
    _channel = [[NSMutableDictionary dictionary] retain];
    [_channel setObject:[NSMutableArray array] forKey:@"items"];
    _currentItem = nil;

    return self;
}

- (void)dealloc
{
    // 内存释放
    [_request release], _request = nil;
    [_connection cancel];
    [_connection release], _connection = nil;
    [_channel release], _channel = nil;
    [_currentCharacters release], _currentCharacters = nil;

    [super dealloc];
}

//--------------------------------------------------------------//
#pragma mark -- Operating --
//--------------------------------------------------------------//

- (BOOL)isConcurrent
{
    return YES;
}

- (BOOL)isExecuting
{
    return _isExecuting;
}

- (BOOL)isFinished
{
    return _isFinished;
}

- (void)start
{
    // 开始下载
    if (![self isCancelled]) {
        // 创建XML解析器
        _parserContext = xmlCreatePushParserCtxt(&_saxHandlerStruct, self, NULL, 0, NULL);

        // 设定标志
        [self setValue:[NSNumber numberWithBool:YES] forKey:@"isExecuting"];
        _isChannel = NO;
        _isItem = NO;

        // 创建连接
        [NSURLConnection connectionWithRequest:_request delegate:self];
    }
}

- (void)cancel
{
    // 释放XML解析器
    if (_parserContext) {
        xmlFreeParserCtxt(_parserContext), _parserContext = NULL;
    }

    [_connection cancel], _connection = nil;
    [self setValue:[NSNumber numberWithBool:NO] forKey:@"isExecuting"];
    [self setValue:[NSNumber numberWithBool:YES] forKey:@"isFinished"];

    [super cancel];
}

//--------------------------------------------------------------//
#pragma mark -- NSURLConnection delegate --
//--------------------------------------------------------------//

- (void)connection:(NSURLConnection*)connection
        didReceiveData:(NSData*)data
{
    // 添加解析数据
    xmlParseChunk(_parserContext, (const char*)[data bytes], [data length], 0);
}

- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
    // 添加解析数据(结束)
    xmlParseChunk(_parserContext, NULL, 0, 1);

    // 释放XML解析器
    if (_parserContext) {
        xmlFreeParserCtxt(_parserContext), _parserContext = NULL;
    }

    // 设定标志
    _connection = nil;
    [self setValue:[NSNumber numberWithBool:NO] forKey:@"isExecuting"];
    [self setValue:[NSNumber numberWithBool:YES] forKey:@"isFinished"];
}

- (void)connection:(NSURLConnection*)connection
        didFailWithError:(NSError*)error
{
    // 释放XML解析器
    if (_parserContext) {
        xmlFreeParserCtxt(_parserContext), _parserContext = NULL;
    }

    // 设定标志
    _connection = nil;
    [self setValue:[NSNumber numberWithBool:NO] forKey:@"isExecuting"];
    [self setValue:[NSNumber numberWithBool:YES] forKey:@"isFinished"];
}

//--------------------------------------------------------------//
#pragma mark -- libxml handler --
//--------------------------------------------------------------//

- (void)startElementLocalName:(const xmlChar*)localname
        prefix:(const xmlChar*)prefix
        URI:(const xmlChar*)URI
        nb_namespaces:(int)nb_namespaces
        namespaces:(const xmlChar**)namespaces
        nb_attributes:(int)nb_attributes
        nb_defaulted:(int)nb_defaulted
        attributes:(const xmlChar**)attributes
{
    // channel
    if (strncmp((char*)localname, "channel", sizeof("channel")) == 0) {
        _isChannel = YES;

        return;
    }

    // item
    if (strncmp((char*)localname, "item", sizeof("item")) == 0) {
        _isItem = YES;

        _currentItem = [NSMutableDictionary dictionary];
        [[_channel objectForKey:@"items"] addObject:_currentItem];

        return;
    }

    // title, link, description
    if (strncmp((char*)localname, "title", sizeof("title")) == 0 ||
        strncmp((char*)localname, "link", sizeof("link")) == 0 ||
        strncmp((char*)localname, "description", sizeof("description")) == 0)
    {
        // 创建字符串
        [_currentCharacters release], _currentCharacters = nil;
        _currentCharacters = [[NSMutableString string] retain];
    }
}

- (void)endElementLocalName:(const xmlChar*)localname
        prefix:(const xmlChar*)prefix URI:(const xmlChar*)URI
{
    // channel
    if (strncmp((char*)localname, "channel", sizeof("channel")) == 0) {
        _isChannel = NO;

        return;
    }

    // item
    if (strncmp((char*)localname, "item", sizeof("item")) == 0) {
        _isItem = NO;
        _currentItem = nil;

        return;
    }

    // title, link, description
    if (strncmp((char*)localname, "title", sizeof("title")) == 0 ||
        strncmp((char*)localname, "link", sizeof("link")) == 0 ||
        strncmp((char*)localname, "description", sizeof("description")) == 0)
    {
        NSString*   key;
        key = [NSString stringWithCString:(char*)localname encoding:NSUTF8StringEncoding];

        NSMutableDictionary*    dict = nil;
        if (_isItem) {
            dict = _currentItem;
        }
        else if (_isChannel) {
            dict = _channel;
        }

        [dict setObject:_currentCharacters forKey:key];
        [_currentCharacters release], _currentCharacters = nil;
    }
}

- (void)charactersFound:(const xmlChar*)ch
        len:(int)len
{
    // 添加解析到的字符串
    if (_currentCharacters) {
        NSString*   string;
        string = [[NSString alloc] initWithBytes:ch length:len encoding:NSUTF8StringEncoding];
        [_currentCharacters appendString:string];
        [string release];
    }
}

@end

连接开始的时候(start函数)使用 xmlCreatePushParserCtxt 创建解析器实例,这里注意第二个参数,将DownloadOperation 的实例传到解析器内,这个正是回调函数中的第一个参数 — 作为回调函数的句柄调用类成员函数(当然,不使用实例方法,将回调函数设置成类方法也是可行的。但是当你使用到DownloadOperation中的成员等会有些不便,所以从OO的角度出发,还是传递回调函数的对象实例为佳)。

开始下载的时候,因为数据是顺序得到的,所以一边下载,一边用 xmlParseChunk 传递给解析器。

libxml的SAX句柄函数在xmlSAXHandler结构中定义。这个构造体内有30多个句柄定义,一般我们只需要登录其中几个就够了。比如例子中的 startElementNsSAX2Func、endElementNsSAX2Func、charactersSAXFunc 等,他们的定义如下:

最后,因为用SAX解析,需要知道当前解析的位置,所以标记参数需要合理的使用。

使用DOM解析

上面我们已经介绍了,iPhone 中的XML解析器都是SAX的,如果仅仅对于比较小的XML文档,或者说想得到DOM树结构的XML文档来说,使用DOM解析还是有一定价值的(比如针对简单的SOAP,REST文档解析等)。

s
评论

相关推荐

    iphone开发xml解析

    ### iPhone开发中的XML解析详解 在移动应用开发领域,尤其是针对iPhone的应用开发中,XML(Extensible Markup Language)解析是一项关键技术。...希望本文能帮助开发者更好地理解并掌握iPhone开发中的XML解析技巧。

    iphone 解析XML的demo

    1. **NSXMLParser**: 这是iOS SDK中用于解析XML的主要类。开发者需要创建一个NSXMLParser实例,然后设置代理以处理解析过程中的各种事件,如开始解析、遇到元素开始和结束、遇到字符数据等。 2. **XML解析代理方法*...

    iPhone3开发基础教程

    - **网络通信**:详解了如何利用NSURLSession进行网络请求,以及如何解析JSON、XML等数据格式。 #### 4. 实战案例 - **完整项目开发**:通过一个完整的项目实例,展示了从需求分析到设计、编码、测试直至发布的全...

    Head-First iphone development

    《Head-First iPhone开发》是一本专为有编程基础的学习者设计的教程,旨在通过简单、逐步的方法,帮助读者快速掌握构建iPhone应用程序的核心技术。本书并非试图覆盖所有的知识点,而是聚焦于让读者直接进入iPhone...

    iOS网络高级编程 iPhone和iPad的企业应用开发 PDF

    《iOS网络高级编程:iPhone和iPad的企业应用开发》是一本专为iOS开发者设计的专业书籍,主要探讨了在iOS平台上进行企业级应用开发时涉及到的网络技术。这本书的高清PDF版本提供了丰富的学习资源,旨在帮助开发者深入...

    iPhone开发秘籍:第2版(The iPhone Developer's Cookbook)

    ### iPhone开发秘籍:第2版(The iPhone Developer's Cookbook) #### 书籍概述 《iPhone开发秘籍:第2版》是一本专为iPhone开发者准备的技术指南书籍,它基于第一版进行了全面修订与大量扩充,提供了更为丰富的内容...

    iPhone开发(淘宝客户端源代码)

    本篇文章将详细剖析一款开源的淘宝客户端源码,帮助开发者理解并掌握iPhone应用开发的核心技术,包括POST请求、XML解析以及MD5加密。这些知识点对于任何iOS开发者来说都是至关重要的基础。 首先,让我们关注POST...

    iPhone开发基础教程_(美)Dave_Mark_中文高清版

    ### iPhone开发基础教程知识点概述 #### 一、书籍基本信息 - **书名**:《iPhone开发基础教程》 - **作者**:Dave Mark & Jeff LaMarche - **出版社**:人民邮电出版社 - **版本**:中文高清版 - **文件大小**:...

    iphone sdk3 开发指南 源代码

    还有可能包含的是网络请求和数据解析的例子,比如使用NSURLConnection进行HTTP请求,或者使用NSXMLParser解析XML数据。这些代码展示了如何在iOS应用中获取远程数据,并将其显示给用户。 此外,对于游戏开发者,可能...

    Iphone开发基础教程源码

    4. ** 数据存储:** 包括使用UserDefaults、Core Data或者SQLite进行轻量级的数据存储,以及JSON或XML数据的解析。 5. ** 网络通信:** 演示如何使用URLSession进行HTTP请求,获取和发送网络数据,可能还会涉及API...

    iPhone开发基础教程

    【iPhone开发基础教程】 在移动应用开发领域,iOS平台凭借其稳定的系统性能和庞大的用户群体,一直是开发者关注的焦点。本教程将引导你逐步踏入iPhone应用程序的开发世界,通过深入浅出的方式,让你掌握必要的技能...

    从Xml中读取信息

    Xml(Extensible Markup Language)是一种标记语言,常用于数据交换、配置存储以及简化网络通信等场景。本教程将深入探讨如何从Xml文件中提取信息,特别是以手机收藏信息为例进行练习,帮助你掌握基本的Xml格式和...

    iPhone开发书籍C#

    6. **网络编程**:掌握使用MonoTouch进行HTTP请求、JSON解析、XML处理,以及与服务器交互的技巧。 7. **多媒体支持**:学习如何在应用中集成图像、音频和视频,使用Core Graphics和Core Image进行图像处理。 8. **...

    iPhone开发源码

    这份教程包含了丰富的实例,涵盖了iPhone开发的基础到高级技巧,是初学者和进阶者提升技能的理想资料。 一、iOS开发环境搭建 在开始iPhone开发之前,你需要安装Apple的集成开发环境(Xcode)。Xcode提供了编写、调试...

    iPhone与iPad开发实战(iPhone and iPad in Action )

    - **数据解析**:掌握JSON和XML等格式的数据解析技巧。 - **WebSocket通信**:实现客户端与服务器间的实时双向通信。 #### 七、高级框架与技术 - **Game Kit框架**:用于开发多人游戏,支持玩家账号管理、游戏配对...

    iOS游戏应用源代码——lhunath-Cocos2D-iPhone.old-9ab3d34.zip

    《深入解析iOS游戏开发:基于lhunath-Cocos2D-iPhone.old-9ab3d34源码》 在iOS游戏开发领域,Cocos2D-iPhone是一个广受欢迎的开源框架,它为开发者提供了创建2D游戏、教育应用、演示和其他互动内容的强大工具。这个...

    iOS网络高级编程 iPhone和iPad的企业应用开发

    《iOS网络高级编程:iPhone和iPad的企业应用开发》是一本深度探讨iOS平台上网络技术与企业应用开发的专业书籍。这本书全面覆盖了iOS应用中网络通信的各种关键技术和实践,旨在帮助开发者构建高效、稳定且安全的企业...

    iphone开发cocoa教材中文pdf

    6. **网络编程**:学习使用URLSession进行网络请求,获取JSON或XML数据,并解析成模型对象。 7. **多线程**:iOS开发中,GCD(Grand Central Dispatch)和Operation Queues是实现多线程的重要工具,它们能帮助优化...

    swift-iPhone7大陆零售店预约店取监控formacOS

    在“标签”中,“Swift开发-其它杂项”暗示了这个项目可能包含了一些非标准或者特定场景的Swift开发技巧,例如可能涉及到网络请求、数据解析、用户界面设计等。Swift开发通常包括以下几个方面: 1. **网络请求**:...

Global site tag (gtag.js) - Google Analytics