尼古拉·特斯拉说“真正有价值的是直觉;在探索的道路上智力用处不大。”
初学ios,一直都是断断续续,最连续一段就是照一本书写了乒乓球的游戏,实质并未掌握和理解ios编程,本以为,可以通过写博客来促使自己好好了解这一块,谁知,一注册,就写了个随笔,便无其它。当初凭直觉,应该学ios编程,初时,狂买一堆书,后发现自己对ios版本的更新给忽略了,发现好几本都是跟自己电脑版本不符,有些api早无不用,界面也变,照着书弄,可谓是,鸭听雷,一个简单的例子,发了好长时间。一直以来,自己都有些惰性,很多东西,都是浅尝则止,最后徒劳无功。但心理一直告诉自己,这一块应该学习,个人觉得,学好ios网络编程这方向,对自己是极好。
ios网络编程几个步骤(注以下部分来源于http://www.cocoachina.com/bbs/read.php?tid=54338&keyword=%CD%F8%C2%E7%B1%E0%B3%CC):
三:使用NSXMLParser解析xml文件
一:确认网络环境3G/WIFI
1. 添加源文件和framework
开发Web等网络应用程序的时候,需要确认网络环境,连接情况等信息。如果没有处理它们,是不会通过Apple的审查的。
Apple 的 例程 Reachability 中介绍了取得/检测网络状态的方法。要在应用程序程序中使用Reachability,首先要完成如下两步
1.1. 添加源文件:
在你的程序中使用 Reachability 只须将该例程中的 Reachability.h 和 Reachability.m 拷贝到你的工程中。如下图:
1.2.添加framework:
将SystemConfiguration.framework 添加进工程。如下图:
2. 网络状态
Reachability.h中定义了三种网络状态:
1 typedef enum { 2 NotReachable = 0, //无连接 3 ReachableViaWiFi, //使用3G/GPRS网络 4 ReachableViaWWAN //使用WiFi网络 5 } NetworkStatus;
因此可以这样检查网络状态:
1 Reachability *r = [Reachability reachabilityWithHostName:@“www.apple.com”]; 2 switch ([r currentReachabilityStatus]) { 3 case NotReachable: 4 // 没有网络连接 5 break; 6 case ReachableViaWWAN: 7 // 使用3G网络 8 break; 9 case ReachableViaWiFi: 10 // 使用WiFi网络 11 break; 12 }
3.检查当前网络环境
程序启动时,如果想检测可用的网络环境,可以像这样
1 // 是否wifi 2 + (BOOL) IsEnableWIFI { 3 return ([[Reachability reachabilityForLocalWiFi] currentReachabilityStatus] != NotReachable); 4 } 5 // 是否3G 6 + (BOOL) IsEnable3G { 7 return ([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] != NotReachable); 8 } 9 例子: 10 - (void)viewWillAppear:(BOOL)animated { 11 if (([Reachability reachabilityForInternetConnection].currentReachabilityStatus == NotReachable) && 12 ([Reachability reachabilityForLocalWiFi].currentReachabilityStatus == NotReachable)) { 13 self.navigationItem.hidesBackButton = YES; 14 [self.navigationItem setLeftBarButtonItem:nil animated:NO]; 15 } 16 }
4. 链接状态的实时通知
网络连接状态的实时检查,通知在网络应用中也是十分必要的。接续状态发生变化时,需要及时地通知用户:
Reachability 1.5版本
1 Reachability 1.5版本 2 // My.AppDelegate.h 3 #import "Reachability.h" 4 @interface MyAppDelegate : NSObject <UIApplicationDelegate> { 5 NetworkStatus remoteHostStatus; 6 } 7 @property NetworkStatus remoteHostStatus; 8 @end 9 // My.AppDelegate.m 10 #import "MyAppDelegate.h" 11 @implementation MyAppDelegate 12 @synthesize remoteHostStatus; 13 // 更新网络状态 14 - (void)updateStatus { 15 self.remoteHostStatus = [[Reachability sharedReachability] remoteHostStatus]; 16 } 17 // 通知网络状态 18 - (void)reachabilityChanged:(NSNotification *)note { 19 [self updateStatus]; 20 if (self.remoteHostStatus == NotReachable) { 21 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"AppName", nil) 22 message:NSLocalizedString (@"NotReachable", nil) 23 delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; 24 [alert show]; 25 [alert release]; 26 } 27 } 28 // 程序启动器,启动网络监视 29 - (void)applicationDidFinishLaunching:(UIApplication *)application { 30 // 设置网络检测的站点 31 [[Reachability sharedReachability] setHostName:@"www.apple.com"]; 32 [[Reachability sharedReachability] setNetworkStatusNotificationsEnabled:YES]; 33 // 设置网络状态变化时的通知函数 34 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) 35 name:@"kNetworkReachabilityChangedNotification" object:nil]; 36 [self updateStatus]; 37 } 38 - (void)dealloc { 39 // 删除通知对象 40 [[NSNotificationCenter defaultCenter] removeObserver:self]; 41 [window release]; 42 [super dealloc]; 43 } 44 45 Reachability 2.0版本 46 // MyAppDelegate.h 47 @class Reachability; 48 49 @interface MyAppDelegate : NSObject <UIApplicationDelegate> { 50 Reachability *hostReach; 51 } 52 53 @end 54 55 // MyAppDelegate.m 56 - (void)reachabilityChanged:(NSNotification *)note { 57 Reachability* curReach = [note object]; 58 NSParameterAssert([curReach isKindOfClass: [Reachability class]]); 59 NetworkStatus status = [curReach currentReachabilityStatus]; 60 61 if (status == NotReachable) { 62 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"AppName"" 63 message:@"NotReachable" 64 delegate:nil 65 cancelButtonTitle:@"YES" otherButtonTitles:nil]; 66 [alert show]; 67 [alert release]; 68 } 69 } 70 71 - (void)applicationDidFinishLaunching:(UIApplication *)application { 72 // ... 73 74 // 监测网络情况 75 [[NSNotificationCenter defaultCenter] addObserver:self 76 selector:@selector(reachabilityChanged:) 77 name: kReachabilityChangedNotification 78 object: nil]; 79 hostReach = [[Reachability reachabilityWithHostName:@"www.google.com"] retain]; 80 hostReach startNotifer]; 81 // ... 82 }
二:使用NSConnection下载数据
1 1.创建NSConnection对象,设置委托对象 2 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[self urlString]]]; 3 [NSURLConnection connectionWithRequest:request delegate:self]; 4 2. NSURLConnection delegate委托方法 5 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response; 6 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error; 7 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data; 8 - (void)connectionDidFinishLoading:(NSURLConnection *)connection; 9 10 3. 实现委托方法 11 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 12 [self.receivedData setLength:0]; //通常在这里先清空接受数据的缓存 13 } 14 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 15 [self.receivedData appendData:data]; //可能多次收到数据,把新的数据添加在现有数据最后 16 } 17 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 18 // 错误处理 19 } 20 - (void)connectionDidFinishLoading:(NSURLConnection *)connection { 21 // disconnect 22 [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 23 NSString *returnString = [[NSString alloc] initWithData:self.receivedData encoding:NSUTF8StringEncoding]; 24 NSLog(returnString); 25 [self urlLoaded:[self urlString] data:self.receivedData]; 26 firstTimeDownloaded = YES; 27 }
三:使用NSXMLParser解析xml文件
1 1. 设置委托对象,开始解析 2 NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; //或者也可以使用initWithContentsOfURL直接下载文件,但是有一个原因不这么做: 3 // It's also possible to have NSXMLParser download the data, by passing it a URL, but this is not desirable 4 // because it gives less control over the network, particularly in responding to connection errors. 5 [parser setDelegate:self]; 6 [parser parse]; 7 8 2. 常用的委托方法 9 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName 10 namespaceURI:(NSString *)namespaceURI 11 qualifiedName:(NSString *)qName 12 attributes:(NSDictionary *)attributeDict; 13 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 14 namespaceURI:(NSString *)namespaceURI 15 qualifiedName:(NSString *)qName; 16 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string; 17 - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError; 18 19 static NSString *feedURLString = @"http://www.yifeiyang.net/test/test.xml"; 20 21 3. 应用举例 22 - (void)parseXMLFileAtURL:(NSURL *)URL parseError:(NSError **)error 23 { 24 NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:URL]; 25 [parser setDelegate:self]; 26 [parser setShouldProcessNamespaces:NO]; 27 [parser setShouldReportNamespacePrefixes:NO]; 28 [parser setShouldResolveExternalEntities:NO]; 29 [parser parse]; 30 NSError *parseError = [parser parserError]; 31 if (parseError && error) { 32 *error = parseError; 33 } 34 [parser release]; 35 } 36 37 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI 38 qualifiedName:(NSString*)qName attributes:(NSDictionary *)attributeDict{ 39 // 元素开始句柄 40 if (qName) { 41 elementName = qName; 42 } 43 if ([elementName isEqualToString:@"user"]) { 44 // 输出属性值 45 NSLog(@"Name is %@ , Age is %@", [attributeDict objectForKey:@"name"], [attributeDict objectForKey:@"age"]); 46 } 47 } 48 49 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI 50 qualifiedName:(NSString *)qName 51 { 52 // 元素终了句柄 53 if (qName) { 54 elementName = qName; 55 } 56 } 57 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 58 { 59 // 取得元素的text 60 } 61 NSError *parseError = nil; 62 [self parseXMLFileAtURL:[NSURL URLWithString:feedURLString] parseError:&parseError];
本来后面还有使用NSOperation和NSOperationQueue启动多线程的章节,不过先吸收这些,后面再作介绍。