• ios 网络编程总结


    转载自:http://www.cocoachina.com/bbs/read.php?tid=31300&uid=29631

    一:确认网络环境3G/WIFI 
     
        1. 添加源文件和framework 
         
        开发Web等网络应用程序的时候,需要确认网络环境,连接情况等信息。如果没有处理它们,是不会通过Apple的审查的。 
        Apple 的 例程 Reachability 中介绍了取得/检测网络状态的方法。要在应用程序程序中使用Reachability,首先要完成如下两部: 
         
        1.1. 添加源文件: 
        在你的程序中使用 Reachability 只须将该例程中的 Reachability.h 和 Reachability.m 拷贝到你的工程中。如下图: 
     
         
         
        1.2.添加framework: 
        将SystemConfiguration.framework 添加进工程。如下图: 
         
         
        2. 网络状态 
         
        Reachability.h中定义了三种网络状态: 
        typedef enum { 
            NotReachable = 0,            //无连接 
            ReachableViaWiFi,            //使用3G/GPRS网络 
            ReachableViaWWAN            //使用WiFi网络 
        } NetworkStatus; 
         
        因此可以这样检查网络状态: 
     
        Reachability *r = [Reachability reachabilityWithHostName:@“www.apple.com”]; 
        switch ([r currentReachabilityStatus]) { 
                case NotReachable: 
                        // 没有网络连接 
                        break; 
                case ReachableViaWWAN: 
                        // 使用3G网络 
                        break; 
                case ReachableViaWiFi: 
                        // 使用WiFi网络 
                        break; 
        } 
         
        3.检查当前网络环境 
        程序启动时,如果想检测可用的网络环境,可以像这样 
        // 是否wifi 
        + (BOOL) IsEnableWIFI { 
            return ([[Reachability reachabilityForLocalWiFi] currentReachabilityStatus] != NotReachable); 
        } 
     
        // 是否3G 
        + (BOOL) IsEnable3G { 
            return ([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] != NotReachable); 
        } 
        例子: 
        - (void)viewWillAppear:(BOOL)animated {     
        if (([Reachability reachabilityForInternetConnection].currentReachabilityStatus == NotReachable) &&  
                ([Reachability reachabilityForLocalWiFi].currentReachabilityStatus == NotReachable)) { 
                self.navigationItem.hidesBackButton = YES; 
                [self.navigationItem setLeftBarButtonItem:nil animated:NO]; 
            } 
        } 
     
        4. 链接状态的实时通知 
        网络连接状态的实时检查,通知在网络应用中也是十分必要的。接续状态发生变化时,需要及时地通知用户: 
         
        Reachability 1.5版本 
        // My.AppDelegate.h 
        #import "Reachability.h" 
     
        @interface MyAppDelegate : NSObject <UIApplicationDelegate> { 
            NetworkStatus remoteHostStatus; 
        } 
     
        @property NetworkStatus remoteHostStatus; 
     
        @end 
     
        // My.AppDelegate.m 
        #import "MyAppDelegate.h" 
     
        @implementation MyAppDelegate 
        @synthesize remoteHostStatus; 
     
        // 更新网络状态 
        - (void)updateStatus { 
            self.remoteHostStatus = [[Reachability sharedReachability] remoteHostStatus]; 
        } 
     
        // 通知网络状态 
        - (void)reachabilityChanged:(NSNotification *)note { 
            [self updateStatus]; 
            if (self.remoteHostStatus == NotReachable) { 
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"AppName", nil) 
                             message:NSLocalizedString (@"NotReachable", nil) 
                            delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; 
                [alert show]; 
                [alert release]; 
            } 
        } 
     
        // 程序启动器,启动网络监视 
        - (void)applicationDidFinishLaunching:(UIApplication *)application { 
         
            // 设置网络检测的站点 
            [[Reachability sharedReachability] setHostName:@"www.apple.com"]; 
            [[Reachability sharedReachability] setNetworkStatusNotificationsEnabled:YES]; 
            // 设置网络状态变化时的通知函数 
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) 
                                                     name:@"kNetworkReachabilityChangedNotification" object:nil]; 
            [self updateStatus]; 
        } 
     
        - (void)dealloc { 
            // 删除通知对象 
            [[NSNotificationCenter defaultCenter] removeObserver:self]; 
            [window release]; 
            [super dealloc]; 
        }  
         
        Reachability 2.0版本 
         
     
        // MyAppDelegate.h 
        @class Reachability; 
     
            @interface MyAppDelegate : NSObject <UIApplicationDelegate> { 
                Reachability  *hostReach; 
            } 
     
        @end 
     
        // MyAppDelegate.m 
        - (void)reachabilityChanged:(NSNotification *)note { 
            Reachability* curReach = [note object]; 
            NSParameterAssert([curReach isKindOfClass: [Reachability class]]); 
            NetworkStatus status = [curReach currentReachabilityStatus]; 
         
            if (status == NotReachable) { 
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"AppName"" 
                                  message:@"NotReachable" 
                                  delegate:nil 
                                  cancelButtonTitle:@"YES" otherButtonTitles:nil]; 
                                  [alert show]; 
                                  [alert release]; 
            } 
        } 
                                   
        - (void)applicationDidFinishLaunching:(UIApplication *)application { 
            // ... 
                       
            // 监测网络情况 
            [[NSNotificationCenter defaultCenter] addObserver:self 
                                  selector:@selector(reachabilityChanged:) 
                                  name: kReachabilityChangedNotification 
                                  object: nil]; 
            hostReach = [[Reachability reachabilityWithHostName:@"www.google.com"] retain]; 
            hostReach startNotifer]; 
            // ... 
        } 
     
     
    二:使用NSConnection下载数据 
         
        1.创建NSConnection对象,设置委托对象 
         
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[self urlString]]]; 
        [NSURLConnection connectionWithRequest:request delegate:self]; 
         
        2. NSURLConnection delegate委托方法 
            - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;   
            - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;   
            - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;   
            - (void)connectionDidFinishLoading:(NSURLConnection *)connection;   
     
        3. 实现委托方法 
        - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 
            // store data 
            [self.receivedData setLength:0];            //通常在这里先清空接受数据的缓存 
        } 
         
        - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
               /* appends the new data to the received data */ 
            [self.receivedData appendData:data];        //可能多次收到数据,把新的数据添加在现有数据最后 
        } 
     
        - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
            // 错误处理 
        } 
     
        - (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
            // disconnect 
            [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;    
            NSString *returnString = [[NSString alloc] initWithData:self.receivedData encoding:NSUTF8StringEncoding]; 
            NSLog(returnString); 
            [self urlLoaded:[self urlString] data:self.receivedData]; 
            firstTimeDownloaded = YES; 
        } 
     
    三:使用NSXMLParser解析xml文件 
     
        1. 设置委托对象,开始解析 
        NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];   //或者也可以使用initWithContentsOfURL直接下载文件,但是有一个原因不这么做: 
        // It's also possible to have NSXMLParser download the data, by passing it a URL, but this is not desirable 
        // because it gives less control over the network, particularly in responding to connection errors. 
        [parser setDelegate:self]; 
        [parser parse]; 
     
        2. 常用的委托方法 
        - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName  
                                    namespaceURI:(NSString *)namespaceURI 
                                    qualifiedName:(NSString *)qName  
                                    attributes:(NSDictionary *)attributeDict; 
        - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName  
                                    namespaceURI:(NSString *)namespaceURI  
                                    qualifiedName:(NSString *)qName; 
        - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string; 
        - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError; 
     
        static NSString *feedURLString = @"http://www.yifeiyang.net/test/test.xml"; 
     
        3.  应用举例 
        - (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]; 

    使用NSOperation和NSOperationQueue启动多线程
    在app store中的很多应用程序非常的笨重,他们有好的界面,但操作性很差,比如说当程序从网上或本地载入数据的时候,界面被冻结了,用户只能等程序完全载入数据之后才能进行操作。 
    当打开一个应用程序时,iphone会产生一个包含main方法的线程,所用程序中的界面都是运行在这个线程之中的(table views, tab bars, alerts…),有时候我们会用数据填充这些view,现在问        题是如何有效的载入数据,并且用户还能自如的操作程序。方法是启动新的线程,专门用于数据的下载,而主线程不会因为下载数据被阻塞。 
    不管使用任何编程语言,在实现多线程时都是一件很麻烦的事情。更糟糕的是,一旦出错,这种错误通常相当糟糕。然而,幸运的是apple从os x10.5在这方面做了很多的改进,NSThread的引入,使得开发多线程应用程序容易多了。除此之外,它们还引入了两个全新的类,NSOperation和NSOperationQueue。 
    接下来我们通过一个实例来剖析如何使用这两个类实现多线程。这里指示展示这两个类的基本用法,当然这不是使用他们的唯一办法。 
    如果你熟悉java或者它的别的变种语言的话 ,你会发现NSOperation对象很像java.lang.Runnable接口,就像java.lang.Runnable接口那样,NSOperation类也被设计为可扩展的,而且只有一个需要重写的方法。它就是-(void)main。使用NSOperation的最简单的方式就是把一个NSOperation对象加入到NSOperationQueue队列中,一旦这个对象被加入到队列,队列就开始处理这个对象,直到这个对象的所有操作完成。然后它被队列释放。 
    下面的例子中,使用一个获取网页,并对其解析程NSXMLDocument,最后将解析得到的NSXMLDocument返回给主线程。 
         
    PageLoadOperation.h@interface PageLoadOperation : NSOperation { 
        NSURL *targetURL;} 
    @property(retain) NSURL *targetURL; 
    - (id)initWithURL:(NSURL*)url;@end 
     
    PageLoadOperation.m 
    #import "PageLoadOperation.h"#import "AppDelegate.h"@implementation PageLoadOperation@synthesize targetURL;- (id)initWithURL:(NSURL*)url;{ 
        if (![super init]) return nil; 
        [self setTargetURL:url]; 
        return self;}- (void)dealloc { 
        [targetURL release], targetURL = nil; 
        [super dealloc]; 

    - (void)main  

        NSString *webpageString = [[[NSString alloc] 
        initWithContentsOfURL:[self targetURL]] autorelease]; 
        NSError *error = nil; 
        NSXMLDocument *document = [[NSXMLDocument alloc] 
        initWithXMLString:webpageString  
        options:NSXMLDocumentTidyHTML error:&error]; 
        if (!document) { 
            NSLog(@"%s Error loading document (%@): %@",  
            _cmd, [[self targetURL] absoluteString], error); 
             return; 
        } 
        [[AppDelegate shared] 
        performSelectorOnMainThread:@selector(pageLoaded:) 
             withObject:document waitUntilDone:YES]; 
        [document release]; 

    @end 
        正如我们所看到的那样,这个类相当的简单,在它的init方法中接受一个url并保存起来,当main函数被调用的时候,它使用这个保存的url创建一个字符串,并将这个字符串传递给NSXMLDocumentinit方法。如果加载的xml数据没有出错,数据会被传递给AppDelegate,它处于主线程中。到此,这个线程的任务就完成了。在主线程中注销操作队列的时候,会将这个NSOperation对象释放。 
    AppDelegate.h 
    @interface AppDelegate : NSObject { 
        NSOperationQueue *queue; 
    }+ (id)shared;- (void)pageLoaded:(NSXMLDocument*)document;@endAppDelegate.m        #import "AppDelegate.h"#import "PageLoadOperation.h"@implementation AppDelegate 
    static AppDelegate *shared; 
    static NSArray *urlArray; 
    - (id)init 

        if (shared) 
        { 
            [self autorelease]; 
            return shared; 
        } 
        if (![super init]) return nil;    NSMutableArray *array = [[NSMutableArray alloc] init];[array addObject:@"http://www.google.com"];[array addObject:@"http://www.apple.com"];[array addObject:@"http://www.yahoo.com"];[array addObject:@"http://www.zarrastudios.com"];[array addObject:@"http://www.macosxhints.com"];urlArray = array;    queue = [[NSOperationQueue alloc] init];shared = self;return self; 
        } 
        •    (void)applicationDidFinishLaunching: 
        (NSNotification *)aNotification 

            for (NSString *urlString in urlArray)  
            { 
            NSURL *url =  
            [NSURL URLWithString:urlString];        PageLoadOperation *plo =  
            [[PageLoadOperation alloc] initWithURL:url]; 
            [queue addOperation:plo]; 
            [plo release]; 
            } 

    - (void)dealloc 

            [queue release], queue = nil; 
            [super dealloc]; 

    + (id)shared; 

            if (!shared) { 
                [[AppDelegate alloc] init]; 
            } 
            return shared; 

    - (void)pageLoaded:(NSXMLDocument*)document; 

            NSLog(@"%s Do something with the XMLDocument: %@", 
                 _cmd, document); 

    @end 
     
    NSOperationQueue的并行控制(NSOperationQueue Concurrency) 
            在上面这个简单的例子中,我们很难看出这些操作是并行运行的,然而,如果你你的操作花费的时间远远比这里的要长,你将会发现,队列是同时执行这些操作的。幸运的是,如果你想要为队列限制同时只能运行几个操作,你可以使用NSOperationQueue的setMaxConcurrentOperationCount:方法。例如,[queue setMaxConcurrentOperationCount:2]; 

  • 相关阅读:
    SGU 176.Flow construction (有上下界的最大流)
    POJ 2391.Ombrophobic Bovines (最大流)
    poj 1087.A Plug for UNIX (最大流)
    poj 1273.PIG (最大流)
    POJ 2112.Optimal Milking (最大流)
    SGU 196.Matrix Multiplication
    SGU 195. New Year Bonus Grant
    关于multicycle path
    ppt做gif动图
    codeforces 598A Tricky Sum
  • 原文地址:https://www.cnblogs.com/java20130723/p/3212094.html
Copyright © 2020-2023  润新知