02-數(shù)據(jù)解析

一、數(shù)據(jù)解析

在網絡開發(fā)中,從服務器獲取的二進制數(shù)據(jù)包括以下幾種
? Html ? 圖片
? 視頻
? 音頻
? zip
除了以上文件格式之外,最常見的數(shù)據(jù)莫過于JSON,偶爾也會有XML。無論JSON還是XML都是一種特殊格式的字符串,按照特定的規(guī)則描述數(shù)據(jù)結構旷偿。

1痴脾、準備工作--安裝Apache服務器

安裝Apache

  • 一发乔、目的

    1. 能夠有一個測試的服務器垄惧,不是所有的特殊網絡服務都能找到免費的遏片!
  • 二薯嗤、為什么是 "Apache"

    1. 使用最廣的 Web 服務器
    2. Mac自帶顽爹,不需要額外的安裝,只需要修改幾個配置就可以骆姐,簡單镜粤,快捷
    3. 有些特殊的服務器功能,Apache都能很好的支持
      例如:HTTP PUT/DELETE 操作玻褪,知識補充涉及的 HTTPS 服務
  • 三肉渴、 準備工作

    1>設置用戶密碼

  • 四、 配置服務器

    1. 配置服務器的工作
      1> 在Finder中創(chuàng)建一個"Sites"的文件夾带射,直接創(chuàng)建在/Users/apple(當前用戶名)目錄下
      2> 修"同规,指向剛剛創(chuàng)建的文件夾
      3> 拷貝一個文件

    2. 配置服務器注意事項
      1> 關閉中文輸入法
      2> 命令和參數(shù)之間需要有"空格"
      3> 修改系統(tǒng)文件一定記住"sudo",否則會沒有權限
      4> 目錄要在/Users/apple(當前用戶名)

    3. 配置服務器
      提示:$開頭的窟社,可以拷貝券勺,但是不要拷貝$
      // 切換工作目錄
      $cd /etc/apache2

      // *** 備份文件,以防不測灿里,只需要執(zhí)行一次就可以了
      $sudo cp httpd.conf httpd.conf.bak

      // 提示:如果后續(xù)操作出現(xiàn)錯誤关炼!可以使用以下命令,恢復備份過的httpd.conf 文件
      $ sudo cp httpd.conf.bak httpd.conf

      // vim里面只能用鍵盤匣吊,不能用鼠標
      // 用vim編輯httpd.conf
      $sudo vim httpd.conf

      // 查找DocumentRoot
      */DocumentRoot

      "將光標移動到首行"
      // 進入編輯模式
      *i
      "修改引號中的路徑"

      // 進入命令模式

      *Mac 10.10 的 Apache 配置略微有一些不一樣儒拂!
      在 httpd.conf 中找到
      Options FollowSymLinks Multiviews
      加一個單詞 Indexes,修改后的結果如下:
      Options Indexes FollowSymLinks Multiviews
      /Users/flilili/Sites

      *ESC:q

      // 查找php
      */php

      "將光標移動到行首" c
      // 刪除行首注釋#
      *x

      // 保存并退出
      *:wq

      // 不保存退出!!!!!!!!!
      *:q!

      // 切換工作目錄
      $cd /etc

      // 拷貝php.ini文件
      $sudo cp php.ini.default php.ini

      // 重新啟動apache服務器
      $sudo apachectl -k restart

      如果提示以下錯誤是正常的:
      httpd: Could not reliably determine the server's fully qualified domain name, using teacher.local for ServerName
      httpd not running, trying to start

  常見問題:

  1. 如果點擊info.php文件色鸳,出現(xiàn)下載社痛,或者只是顯示一小段文字

  解決辦法:

  在終端中輸入以下兩個命令:
  // 關閉 apache 服務器
  $sudo apachectl -k stop

  // 重新再次啟動 apache
  $sudo apachectl -k start

  #如果上面命令無效,可執(zhí)行下面命令試試
  // 啟動 apache 服務器
  $ sudo /usr/sbin/apachectl start
  // 關閉 apache 服務器
  $ sudo /usr/sbin/apachectl stop
  1. 在 MAC10.9之后缕碎,為了安全考慮褥影,每次啟動計算機哑芹,Apache服務器默認是不會自動啟動的蹬挤!

可以啟動計算機之后,打開終端,輸入以下命令:
// 啟動 apache
$sudo apachectl -k start

  1. 最常見的問題
    交換文件已經存在运吓,直接按字母 d,可以刪除交換文件肤晓!


  2. 執(zhí)行腳本的時候耀盗,顯示不了,拒絕訪問房匆!原因大家用 NTFS 格式的 U 盤拷貝網絡素材耸成!會把文件本身的權限過濾掉!

以下是在終端中修改文件權限的指令浴鸿!
$ chmod 644 info.php(要修改權限的文件名)
$ chmod 644 .

問題解惑
1> 為什么要設置用戶密碼井氢?
答:apache是一個web服務器,一旦啟動了服務器岳链,從互聯(lián)網上的任何一個人都有可能訪問到我們的電腦花竞,不設置密碼意味著我們的電腦在互聯(lián)網上是裸奔的,非常不安全掸哑。

2> 為什么Sites文件夾要創(chuàng)建在/Users/apple(當前用戶名)目錄下约急?在 Desktop 或 Document文件下創(chuàng)建可以不?
答:不可以苗分。因為Desktop 或 Document文件是用戶私人的文件夾目錄厌蔽。而我們配置的服務器是需要讓所有網絡用戶以匿名的身份能夠有權限訪問這個目錄,因此文件夾必須放在根目錄里面摔癣。

3> 為什么修改系統(tǒng)文件一定用sudo奴饮?
答:因為修改系統(tǒng)文件只有系統(tǒng)管理員才能修改,所以要以系統(tǒng)管理員的身份去修改供填,使用 sudo 就代表是系統(tǒng)管理員的權限拐云。

4> 為什么下面命令只需要執(zhí)行一次就可以了?
$sudo cp httpd.conf httpd.conf.bak
答:如果 httpd.conf 文件在修改壞了之后再執(zhí)行一次該命令,那么副本也是壞的了近她,所以只需要在修改之前執(zhí)行一次就行了叉瘩。

知識補充:

> /etc文件夾下的文件都是跟 mac 配置相關的文件。相當 window 下 system32 文件夾粘捎。

二薇缅、JSON

1、JSON 介紹

JSON本質上,就是一個“特殊格式”的字符串攒磨。

  • ? JSON是網絡上用來傳輸數(shù)據(jù)使用最廣泛的數(shù)據(jù)格式,沒有之一
  • ?JSON出生草根,是Javascrpit的子集& Java沒有任何關系!

參考網站:http://www.w3cschool.cc泳桦。w3c 是國際互聯(lián)網組織的縮寫。

www.runoob.com

2娩缰、JSON的語法規(guī)則

  • ? 數(shù)據(jù)以 key/value 鍵值對表示灸撰。
  • ? 數(shù)據(jù)由逗號分割。
  • ? 花括號保存對象,對應OC的NSDictionary。
  • ? 方括號保存數(shù)組,對應OC的NSArray浮毯。

JSON格式化工具

3完疫、JSON值

  • ? 數(shù)字(整數(shù)或浮點數(shù))。
  • ?字符串(在雙引號中)债蓝。
  • ?邏輯值(true或false)壳鹤。
  • ? 數(shù)組(在方括號中)。
  • ?null

4饰迹、JSON解析--天氣預報

一芳誓、解析天氣預報

- (void)loadData1{
    // 創(chuàng)建 url
    NSURL *url = [NSURL URLWithString:@"http://www.weather.com.cn/adat/sk/101010100.html"];
    // 創(chuàng)建請求對象
    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:10.0];
    // 發(fā)送異步請求
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        
        NSLog(@"data = %@",data);
        NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
        /*
         NSJSONReadingMutableContainers = (1UL << 0), 容器可變
         NSJSONReadingMutableLeaves = (1UL << 1), 葉子可變
         NSJSONReadingAllowFragments(碎片) = (1UL << 2) 頂級節(jié)點可以既不是數(shù)組也不是字典
         */
        
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
        
        NSLog(@"%@市 溫度 %@ 風向 %@ 風力 %@ ",dict[@"weatherinfo"][@"city"],dict[@"weatherinfo"][@"temp"],dict[@"weatherinfo"][@"WD"],dict[@"weatherinfo"][@"WS"]);
    }];
}

專業(yè)名詞解析
* 序列化
    向服務器發(fā)送數(shù)據(jù)之前,將 NSArray/NSDcitionary 轉成二進制的過程。
* 反序列化
    從服務器接收到數(shù)據(jù)之后,將二進制數(shù)據(jù)轉換成 NSArray/NSDcitionary的過程啊鸭。

5锹淌、JSON解析--第三方框架

  • 1、常見的JSON解析第三方框架
    ? JSONKit(最快)
    ?SBJson
    ? TouchJSON
    .# 以上三個框架的性能依次降低莉掂。

  • 2葛圃、蘋果原生(自帶):NSJSONSerialization(性能最好)

  • 3、介紹JSONKit第三方框架的目的

    • ?JSON的解析并不是表面上這么簡單憎妙。
    • ? 官方說JSONKit比蘋果原生的JSON解析速度要快。
      ? JSONKit在很多老的項目中仍然在使用,知道'JSONKit'說明我們是資深的iOS程序員曲楚。
    • ? JSONKit已經在2012年停止更新,適用于iOS5.0之前的版本開發(fā)使用厘唾。(蘋果原生的NSJSONSerialization是iOS5.0之后出現(xiàn))。
    • ? 了解 ARC & MRC 混編的方法
  • 4龙誊、JSONKit解析

    • ?下載框架:http://github.com/johnezang/JSONKit抚垃。

    • ?導入框架文件:JSONKit.h & JSONKit.m。

    • ?設置MRC標記

      • 選擇"項目"-"Build Phases"-"Compile Sources"趟大。
      • 找到JSONKit.m并且在Compiler Flags中添加-fno-objc-arc鹤树。 # -fno-objc-arc告訴編譯器,編譯JSONKit.m時不使用ARC。
      • 修改錯誤,利用自動修復功能,修改兩處isa的錯誤逊朽。
    • ?反序列化id result = [[JSONDecoder decoder] objectWithData:data];

  • 5罕伯、JSONKit性能測試
    ?測試代碼如下

intlargeNumber =100*1000;
- (void)loadData{
    
    //創(chuàng)建url
    NSURL *url = [NSURL URLWithString:@"http://localhost/demo.json"];
    //創(chuàng)建請求對象
    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0timeoutInterval:10.0];
    //發(fā)送異步請求
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        //絕對時間是自參考日期的時間間隔
        CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
        for(intindex =0; index < largeNumber; index ++) {
            // NSMutableDictionary *result = [[JSONDecoder decoder] objectWithData:data];
            NSMutableDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
        }
        NSLog(@"-----endTime = %f",CFAbsoluteTimeGetCurrent() - start);
        
        NSLog(@"-----endTime = %f",CFAbsoluteTimeGetCurrent() - start);
        //JKDictionary 其實就是 NSMutableDictionary 的 子類 //NSLog(@"------%@,%@",result,result[@"message"]);
        
    }];
}

通過測試驗證結果如下:
JSONKit:4.907761秒
官方:0.299994秒

由此可得出結論:蘋果原生的JSON解析速度遠遠比JSONKit快。
  如果工作中遇到使用第三方框架解析 JSON 的舊項目,建議替換為蘋果原生的叽讳。
  替換的原則:看項目是否要支持iOS5.0之前的版本追他。如果不需要果斷替換。
  替換步驟
      備份(給自己一個后悔的機會)
      刪除JSONKit.h & .m文件
      哪里出錯改哪里

三岛蚤、PList解析

  • 1邑狸、PList主要在蘋果開發(fā)中常用,很多后臺并不會返回Plist的格式數(shù)據(jù)。有關PList的反序列化知道即可涤妒。
  • 2单雾、PList解析代碼如下
- (void)loadData{
    // 創(chuàng)建 url
    NSURL *url = [NSURL URLWithString:@"http://localhost/videos.plist"];
    // 創(chuàng)建請求對象
    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:10.0];
    // 發(fā)送異步請求
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        id result = [NSPropertyListSerialization propertyListWithData:data options:0 format:NULL error:nil];
        NSLog(@"%@   %@",result,[result class]);
    }];
}

NSPropertyListSerialization 參數(shù):
-data:要反序列化的二進制數(shù)據(jù)
-options:選項,位移枚舉類型
NSPropertyListImmutable = 0 不可變,
NSPropertyListMutableContainers= 1  容器可變,
NSPropertyListMutableContainersAndLeaves= 2  容器和葉子可變
- format:如果不希望知道格式,傳人 NULL 即可
-error:錯誤信息

四、XML 解析

0.XML語法

  • 一個元素可以擁有多個屬性

1、XML介紹

一硅堆、介紹

  • 1蜂奸、XML的英文全稱(eXtensible Markup Language) 中文名稱可擴展標 記語言。

  • 2硬萍、XML的特點:

    • 語法規(guī)則很簡單,且很有邏輯扩所。
    • 出身名門,w3c制定,微軟和 IBM 曾經共同大力推薦過的數(shù)據(jù)格式。
    • 專門設計用來傳輸和存儲數(shù)據(jù)
  • 3朴乖、與HTML的區(qū)別:

    • HTML的標記不是所有都需要成對出現(xiàn)祖屏。
    • XML要求所有的標記必須成對出現(xiàn)。
    • HTML標記不區(qū)分大小寫,XML則大小敏感,即區(qū)分大小寫买羞。

二袁勺、XML解析的方式

  • 蘋果原生
    NSXMLParser:SAX方式解析,使用簡單

    • 是只讀的方式,從上向下的方式解析
    • 是蘋果提供的解析方式
    • 使用 NSXMLParser 通過 代理 實現(xiàn)解析。
  • DOM解析

    • 是在MAC使用的解析方式畜普。
    • 內存消耗極大,不適用于手機期丰。因此蘋果沒有提供手機上DOM解析。
    • iPhone無法直接使用DOM方式解析XML吃挑。
  • 第三方框架

    • libxml2:純C語言,默認包含在iOS SDK中,同時支持DOM和SAX方式解析
    • GDataXML:DOM方式解析,由Google開發(fā),基于libxml2
  • XML解析方式的選擇建議

    • 大文件:NSXMLParser钝荡、libxml2
    • 小文件:GDataXML

2、SAX解析

2.0舶衬、NSLog確認解析思路

一埠通、SAX解析步驟

  • 開始文檔--準備工作
  • 開始"節(jié)點"
  • 發(fā)現(xiàn)節(jié)點內部的內容,每一個節(jié)點,可能需要多次才能找完
  • 結束"節(jié)點"
  • 結束文檔--解析結束
  • 以上步驟2,3逛犹,4會不斷循環(huán),一直到所有解析完成端辱。

二、代碼演示XML的解析

/**
 *  加載 xml 數(shù)據(jù)
 */
- (void)loadData{
    // 創(chuàng)建 url
    NSURL *url = [NSURL URLWithString:@"http://localhost/videos.xml"];
    // 創(chuàng)建請求對象
    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:10.0];
    // 發(fā)送異步請求(由于解析 xml 是一個耗時的過程虽画,所以新開啟隊列)
    [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        // 1.創(chuàng)建 xml 解析器
        NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
        // 2.設置代理來解析
        parser.delegate = self;
        // 3.解析器開始
        //解析 -- 一旦開始解析,后續(xù)的解析工作全部交給代理完成
        [parser parse];
    }];
}

5.iOS對NSURLRequest提供了7種緩存策略:(實際上能用的只有4種)
NSURLRequestUseProtocolCachePolicy // 默認的緩存策略(取決于協(xié)議)
NSURLRequestReloadIgnoringLocalCacheData // 忽略緩存舞蔽,重新請求
NSURLRequestReloadIgnoringLocalAndRemoteCacheData // 未實現(xiàn)
NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData // 忽略緩存,重新請求
NSURLRequestReturnCacheDataElseLoad// 有緩存就用緩存码撰,沒有緩存就重新請求
NSURLRequestReturnCacheDataDontLoad// 有緩存就用緩存渗柿,沒有緩存就不發(fā)請求,當做請求出錯處理(用于離線模式)
NSURLRequestReloadRevalidatingCacheData // 未實現(xiàn)

三灸拍、通過NSLog打印,確認XML解析思路

#pragma mark  - NSXMLParserDelegate 代理方法
/**
 *  開始解析
 */
- (void)parserDidStartDocument:(NSXMLParser *)parser {
    NSLog(@"1做祝、開始解析");
}
/**
 *  解析到一個開始節(jié)點調用
 */
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    NSLog(@"2、開始節(jié)點 %@ %@",elementName,attributeDict);
}

/**
 *  解析到節(jié)點文字調用  一個節(jié)點的內容可以會調用多次該方法
 */
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    NSLog(@"3鸡岗、發(fā)現(xiàn)節(jié)點內容======> %@",string);
}

/**
 *  解析到結束節(jié)點調用  elementName 沒有反斜線 /
 */
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    NSLog(@"4混槐、結束節(jié)點------%@",elementName);
}

/**
 *  解析結束調用
 */
- (void)parserDidEndDocument:(NSXMLParser *)parser{
    NSLog(@"5、結束文檔");
}
2.1轩性、畫XML解析思維導圖
  1. 懶加載 創(chuàng)建數(shù)組
  2. 開始節(jié)點 如果節(jié)點是vedio節(jié)點創(chuàng)建新對象 設置ID 將設置好的丟進數(shù)組 下一次重新賦值
  3. 發(fā)現(xiàn)節(jié)點內容 拼接字符串
  4. 結束節(jié)點 下一次開始節(jié)點要把上一次清空
  5. 結束解析(打印)
2.2声登、XML解析代碼實現(xiàn)
#pragma mark  - NSXMLParserDelegate 代理方法
/**
 *  開始解析
 */
- (void)parserDidStartDocument:(NSXMLParser *)parser {
    // 清空數(shù)組
    [self.videos removeAllObjects];
}
/**
 *  解析到一個開始節(jié)點調用
 */
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    if ([elementName isEqualToString:@"video"]) {
        // 創(chuàng)建 video 模型
        self.currentVideo = [[Video alloc] init];
        // 設置 id
        self.currentVideo.videoId = @([attributeDict[@"videoId"] integerValue]);
    }
    // 清空當前正在拼接的字符內容
    [self.elementString setString:@""];
    // 錯誤寫法
    //self.elementString = @"";
}

/**
 *  解析到節(jié)點文字調用  一個節(jié)點的內容可以會調用多次該方法
 */
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    [self.elementString appendString:string];
}

/**
 *  解析到結束節(jié)點調用  elementName 沒有反斜線 /
 */
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    // 如果 elementName 是 video,則添加到數(shù)組中
    /* 最笨方法
     if ([elementName isEqualToString:@"video"]){
     [self.videos addObject:self.currentVideo];
     } else if ([elementName isEqualToString:@"name"]){
     self.currentVideo.name = self.elementString;
     } else if ([elementName isEqualToString:@"length"]){
     self.currentVideo.length = @(self.elementString.integerValue);
     } else if ([elementName isEqualToString:@"desc"]){
     self.currentVideo.desc = self.elementString;
     } else if ([elementName isEqualToString:@"imageURL"]) {
     self.currentVideo.imageURL = self.elementString;
     } else if ([elementName isEqualToString:@"videoURL"]){
     self.currentVideo.videoURL = self.elementString;
     } else if ([elementName isEqualToString:@"teacher"]){
     self.currentVideo.teacher = self.elementString;
     }
     */
    // 如果是 name,length,desc....則設置屬性
    
    // 簡便方法
    if ([elementName isEqualToString:@"video"]){
        [self.videos addObject:self.currentVideo];
    } else if(![elementName isEqualToString:@"videos"]){
        //使用 KVC 設置屬性, KVC是一種以字符串形式間接設置數(shù)據(jù)的方式
        [self.currentVideo setValue:self.elementString forKey:elementName];
    }
}

/**
 *  解析結束調用
 */
- (void)parserDidEndDocument:(NSXMLParser *)parser{
    NSLog(@"%@",self.videos);
}

3、SAX解析重構

1、新建一個模型類HMSAXVideo悯嗓,專門做解析工作件舵。
2、提供類方法:+(void)saxParser:(NSData *)data finished:(void (^)(NSArray *))finished脯厨。
/**
 *  視頻數(shù)組
 */
@property(nonatomic,strong) NSMutableArray *videos;
/**
 *  當前正在解析的視頻
 */
@property(nonatomic,strong) HMVideo *currentVideo;
/**
 *  當前正在拼接的字符串
 */
@property(nonatomic,strong) NSMutableString *elementString;
/**
 *  解析完回調block
 */
@property(nonatomic,copy) void (^finishedBlock)(NSArray *);
// 如果回調的 block 在當前方法不執(zhí)行,需要用一個屬性記錄
+(void)saxParser:(NSData *)data finished:(void (^)(NSArray *))finished{
    // 使用斷言確保外界傳人的回調不為空,如果為空,則崩潰提示
    NSAssert(finished != nil, @"必須傳人回調");
    // 0.創(chuàng)建解析模型
    HMSAXVideo *sax = [[HMSAXVideo alloc] init];
    // 記錄回調 block
    sax.finishedBlock = finished;
    // 1.創(chuàng)建 xml 解析器
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
    // 2.設置代理來解析
    parser.delegate = sax;
    // 3.解析器開始解析
    // parse:是同步方法铅祸,會等所用代理方法執(zhí)行完畢后,才會執(zhí)行后面的代碼
    [parser parse];
#warning 不能在parse方法調用后設置回調
    // 記錄回調 block
    // sax.finishedBlock = finished;
}

#pragma mark - 懶加載
- (NSMutableArray *)videos {
    if(_videos == nil){
        _videos = [NSMutableArray array];
    }
    return _videos;
}

- (NSMutableString *)elementString {
    if (_elementString == nil) {
        _elementString = [NSMutableString string];
    }
    return _elementString;
}

#pragma mark  - NSXMLParserDelegate 代理方法
/**
 *  開始解析
 */
- (void)parserDidStartDocument:(NSXMLParser *)parser {
    // 清空數(shù)組
    [self.videos removeAllObjects];
}
/**
 *  解析到一個開始節(jié)點調用
 */
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    if ([elementName isEqualToString:@"video"]) {
        // 創(chuàng)建 video 模型
        self.currentVideo = [[HMVideo alloc] init];
        // 設置 id
        self.currentVideo.videoId = @([attributeDict[@"videoId"] integerValue]);
    }
    // 清空當前正在拼接的字符內容
    [self.elementString setString:@""];
}

/**
 *  解析到節(jié)點文字調用  一個節(jié)點的內容可以會調用多次該方法
 */
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    [self.elementString appendString:string];
}

/**
 *  解析到結束節(jié)點調用  elementName 沒有反斜線 /
 */
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
   // 使用 KVC 設置屬性
    if ([elementName isEqualToString:@"video"]){
        [self.videos addObject:self.currentVideo];
    } else if(![elementName isEqualToString:@"videos"]){
        [self.currentVideo setValue:self.elementString forKey:elementName];
    }
}

/**
 *  解析結束調用
 */
- (void)parserDidEndDocument:(NSXMLParser *)parser{
    dispatch_async(dispatch_get_main_queue(), ^{
        self.finishedBlock(self.videos.copy);
    });
}

五合武、UITableView展示數(shù)據(jù)

5.1临梗、Stroyboard自定義cell

5.2、設置Cell數(shù)據(jù)

1稼跳、HMVideo模型中提供屬性
//視頻時長
@property (nonatomic, strong,readonly) NSString *time;
計算時間方式有兩種
方式一:重寫time屬性getter方法
- (NSString *)time {
         int len = self.length.intValue;
         return [NSString stringWithFormat:@"%02d:%02d:%02d", len/3600,(len % 3600)/ 60,               (len % 60)];
}
方式二:
- (void)setLength:(NSNumber *)length {
    _length = length;
    int len = self.length.intValue;
    _time = [NSString stringWithFormat:@"%02d:%02d:%02d", len/3600, (len % 3600)/60, (len % 60)];
}

SDWebImage下載頭像
UIImage *placeholder = [UIImage imageNamed:@"user_default"];
[self.iconView sd_setImageWithURL:video.fullImageUrl placeholderImage:placeholder options:SDWebImageRetryFailed | SDWebImageLowPriority];

參數(shù)
SDWebImageLowPriority:會在表格滾動的時候盟庞,暫停圖像下載,性能會好很多
SDWebImageRetryFailed:圖片下載失敗后重試

5.3汤善、集成下列刷新控件

  • 1什猖、通過代碼和storyboard
/**
 *  集成下拉刷新控件(通過代碼)
 */
- (void)setRefreshControl{
    // 集成下拉控件(不需要設置frame)
    self.refreshControl = [[UIRefreshControl alloc] init];
    // 監(jiān)聽下拉事件
    [self.refreshControl addTarget:self action:@selector(loadData) forControlEvents:UIControlEventValueChanged];
    // 設置提示文字,顏色
    NSMutableAttributedString *attributedTitle = [[NSMutableAttributedString alloc] initWithString:@"努力加載中……" attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15],NSForegroundColorAttributeName:[UIColor redColor]}];
    self.refreshControl.attributedTitle = attributedTitle;
    // 設置菊花顏色
    self.refreshControl.tintColor = [UIColor grayColor];
}
  • 2红淡、UIRefreshControl使用說明
    • 目前只對UITableviewController有用
    • 只能下拉刷新不狮,不能上拉刷新
    • init或者viewdidload中創(chuàng)建UIRefreshControl,設置文字锉屈,顏色等信息
    • 系統(tǒng)自動管理UIRefreshControl荤傲,自動添加到tableview視圖中;
    • 給UIRefreshControl添加監(jiān)聽方法颈渊,當值改變的時候調用方法用于數(shù)據(jù)請求
    • 該方法中請求數(shù)據(jù)確認完成之后,調用endRefreshing方法终佛,關閉刷新

六俊嗽、GDataXML解析xml

6.1、GDataXML介紹

在計算機領域铃彰,針對 XML 解析绍豁,還有 DOM 解析方式,在PC端和服務器被廣泛使用

  • 背景

    • 主要用在 PC 端或服務器端牙捉。
    • 蘋果提供了 NSXML 類支持 DOM 方式的解析
    • 不過 NSXML 類只能用在 MAC 開發(fā)竹揍,在iOS中無法直接使用。
  • DOM 特點(可讀可寫)

    • DOM 方式不僅能解析 XML文檔邪铲,還能夠修改:增加節(jié)點/刪除節(jié)點芬位、
    • 一次性將 XML 文檔以樹形結構讀入內存。
    • 橫向的節(jié)點越多带到,內存消耗越大昧碉。
    • 使用 DOM 解析適合于小的 XML 解析,并且能夠動態(tài)維護。
    • 有些第三方框架提供了 DOM 方式的解析被饿,GData/KissXML(XMPP)
    • 在 iOS開發(fā)中四康,如果要使用 DOM 方式解析,最好只是處理小的 XML

6.2狭握、代碼實現(xiàn)

需要配置:
command+b后會出現(xiàn)報錯
在Build Settings里面“Header Search Paths ”"Other Linker Flags"
// libxml includes require that the target Header Search Paths contain
//
//   /usr/include/libxml2
//
// and Other Linker Flags contain
//
//   -lxml2

- (void)loadData {
    // 創(chuàng)建 url對象
    NSURL *url = [NSURL URLWithString:@"http://192.168.1.105/videos.xml"];
    // 創(chuàng)建請求對象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    // 發(fā)送請求
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        // 創(chuàng)建視頻數(shù)組
        NSMutableArray *videos = [NSMutableArray array];
        // 建立 xml 文檔
        GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data error:NULL];
        
        // 獲得根節(jié)點對象
        GDataXMLElement *rootElement = doc.rootElement;
        
        // 遍歷子節(jié)點
        for (GDataXMLElement *childElement in rootElement.children) {
//            NSLog(@"child = %@",childElement);

            // 每遍歷一次就創(chuàng)建一個視頻對象
            HMVideo *video = [[HMVideo alloc] init];
 
          // 將模型對象添加到數(shù)組中
            [videos addObject:video];
            
            // 繼續(xù)變量childElement的子節(jié)點
            for (GDataXMLElement *node  in childElement.children) {
                // 使用 KVC 賦值
//                NSLog(@"name = %@,value = %@",node.name,node.stringValue);
                [video setValue:node.stringValue forKey:node.name];

            }
            // 遍歷屬性字典數(shù)組
            for (GDataXMLNode *attr in childElement.attributes) {
                // 使用 KVC 賦值
//                NSLog(@"attr = %@,attrValue = %@",attr.name,attr.stringValue);
                [video setValue:attr.stringValue forKey:attr.name];
            }
        }
        NSLog(@"videos = %@",videos);
    }];
}

七闪金、Copy,NSNumber,id

思考?為什么模型HMVideo中的屬性都使用copy? 改為strong運行看看效果论颅。

  • strong 和 copy 的區(qū)別

    • strong :在設置數(shù)值的時候哎垦,僅僅是引用計算+1
    • copy :在設置數(shù)值的時候,如果屬性是可變的嗅辣,會copy一個不可變的副本撼泛。copy動作是在setter方法中執(zhí)行的。
  • 畫圖解析使用strong導致的效果澡谭。

  • 如果模型屬性要使用strong

#下面的代碼
[self.currentVideo setValue:self.elementString forKey:elementName];

#修改為
[self.currentVideo setValue:self.elementString.copy forKey:elementName];
  • 重寫了屬性的setter方法愿题,就是接管了原有系統(tǒng)提供的setter方法。
# 如果重寫了copy屬性的 setter 方法,一定要copy,否則外面的copy屬性就是strong屬性蛙奖。
比如重寫了模型的name屬性的 setter方法:
- (void)setName:(NSString *)name {
    _name = [name copy];
//    _name = name; 屬性就相當于 strong 了  
}
  • NSNumber,id屬性
    代碼演示實際開發(fā)中不用NSNumber帶來的問題潘酗。 Strong 基本數(shù)據(jù)類型
    代碼演示服務器返回數(shù)據(jù)中有id鍵值對的問題。 id NSNumber ID

問題
1.kvc的利用
2.申明屬性時strong&copy的使用雁仲,copy的實現(xiàn)在系統(tǒng)默認setter方法下實現(xiàn)仔夺。
3.獲得了對象的第一個/最后一個值,怎么取全部值

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末攒砖,一起剝皮案震驚了整個濱河市缸兔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吹艇,老刑警劉巖惰蜜,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異受神,居然都是意外死亡抛猖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門鼻听,熙熙樓的掌柜王于貴愁眉苦臉地迎上來财著,“玉大人,你說我怎么就攤上這事撑碴〕沤蹋” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵灰羽,是天一觀的道長驮履。 經常有香客問我鱼辙,道長,這世上最難降的妖魔是什么玫镐? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任倒戏,我火速辦了婚禮,結果婚禮上恐似,老公的妹妹穿的比我還像新娘杜跷。我一直安慰自己,他們只是感情好矫夷,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布葛闷。 她就那樣靜靜地躺著,像睡著了一般双藕。 火紅的嫁衣襯著肌膚如雪淑趾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天忧陪,我揣著相機與錄音扣泊,去河邊找鬼。 笑死嘶摊,一個胖子當著我的面吹牛延蟹,可吹牛的內容都是我干的。 我是一名探鬼主播叶堆,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼阱飘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了虱颗?” 一聲冷哼從身側響起沥匈,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎忘渔,沒想到半個月后咐熙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡辨萍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了返弹。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锈玉。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖义起,靈堂內的尸體忽然破棺而出拉背,到底是詐尸還是另有隱情,我是刑警寧澤默终,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布椅棺,位于F島的核電站犁罩,受9級特大地震影響,放射性物質發(fā)生泄漏两疚。R本人自食惡果不足惜床估,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望诱渤。 院中可真熱鬧丐巫,春花似錦、人聲如沸勺美。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽赡茸。三九已至缎脾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間占卧,已是汗流浹背遗菠。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留屉栓,地道東北人舷蒲。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像友多,于是被迫代替她去往敵國和親牲平。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內容