亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

KVO 的使用和舉例

系統 1756 0

? ? KVO(key-value Observer),通過命名可以聯想到,一個監視著監視著鍵值配對,讓一個對象A來監視另一個對象B中的鍵值,一旦B中的受監視鍵所對應的值發生了變化,對象A會進入一個回調函數,有機會對于B中的受監視鍵值的改變立刻進行處理和應對。

? ? 注:雖然對象A中的回調函數有點像代理方法,但是回調函數的調用和鍵值發生變化處在同一個線程中,并非像某些代理方法會在另一個線程中進行回調。也就是說,如果對鍵key進行了監視,一旦鍵key對應的值發生了變化,就會去調用監視著的回調函數,直到回調函數跑完后鍵key對應值發生變化的流程才能繼續。

? ? 好處就是減少膠水代碼。

? ? 比如比賽比分發生了變化,如果我們不用KVO機制,我們需要告訴大屏幕控制人員,告訴網絡媒體,告訴廣播電臺播音員,甚至告訴其他賽場的工作人員。

??

一個簡單的KVO機制的程序

導航欄有三個元素,左邊的編輯按鈕,用來刪除表的記錄,右邊的“+”按鈕,用來新增表的記錄,而當中的標題,用來顯示最近的一次動作。開發思路大致為這樣:

? ?表視圖有一個數據源dataSource,我們需要利用kVO機制去監視這個數據源,當按下“+”按鈕時往數據源中添加一條數據,觸發KVO,隨后在KVO的回調函數中,我們將界面更新成和數據源同步。

? ?當刪除一條數據時,數據源減少一條數據,同樣觸發KVO并在隨后KVO的回調函數中,將界面更新同步。

總體來說,無論對數據源做任何操作,我們都會在KVO的回調函數中,進行程序界面和數據源的同步工作,代碼如下:

      @interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>

{

    IBOutlet UITableView *_tbv;

}



//遵循KVC的編碼規范

@property (nonatomic,retain) NSMutableArray *dataSrc;

@property (nonatomic,retain) NSString *titleMsg;



//提供KVC中對于容器鍵屬性(dataSrc)的接口

-(NSUInteger)countOfDataSrc;

-(void)insertObject:(id)object inDataSrcAtIndex:(NSUInteger)index;

-(id)objectInDataSrcAtIndex:(NSUInteger)index;

-(void)removeObjectFromDataSrcAtIndex:(NSUInteger)index;

@end


    

?上述代碼中一共聲明了兩個屬性變量:dataSrc作為數據源,titleMsg作為標題

由于數據源dataSrc是屬于容器類型的數據,根據KVC協議需要申明并實現數組形式的幾個方法

協議的時間內容中直接使用可變數組提供的功能,對上述四個接口進行實現,代碼如下:

      //集合屬性的個數

-(NSUInteger)countOfDataSrc

{

    return [self.dataSrc count];

}



//集合屬性的新增動作

-(void)insertObject:(id)object inDataSrcAtIndex:(NSUInteger)index

{

    [self.dataSrc insertObject:object atIndex:index];

}



//集合屬性的取值動作

-(id)objectInDataSrcAtIndex:(NSUInteger)index

{

    return [self.dataSrc objectAtIndex:index];

}



//集合屬性的刪除動作

-(void)removeObjectFromDataSrcAtIndex:(NSUInteger)index

{

    [self.dataSrc removeObjectAtIndex:index];

}


    

?至此KVC的準備工作都做完了,繼續實現KVO機制,對于界面的初始化進口位置,作如下初始化的設置

      - (void)viewDidLoad

{

    [super viewDidLoad];

	// Do any additional setup after loading the view, typically from a nib.

    //初始化表視圖(UITableView)的數據

    self.dataSrc = [[NSMutableArray alloc]initWithCapacity:0];

    self.titleMsg = @"沒有動作";

    _tbv=[[UITableView alloc]init];

    //

    //對表視圖的數據進行監視

    //

    //誰來監視,KVO的監視回調函數就調用誰

    [self addObserver:self

     //監視的鍵的路徑,我們這里的屬性由于只有一層,所以直接寫dataSrc

           forKeyPath:@"dataSrc"

     //需要知道表數據改動時的新舊數據,方便我們研究,如果不需要,可以置為0

              options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld

     //KVO 觸發時,我們收到的額外信息,如果不需要可以置為nil

              context:@"testContent"];

    

    [self addObserver:self forKeyPath:@"titleMsg" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:@"testContent"];

    

    //右邊的按鈕,我們放增加

    UIBarButtonItem *addButton=[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(add)];

    self.navigationItem.rightBarButtonItem=addButton;

    

    //左邊的按鈕,我們放編輯,主要提供刪除功能

    //初始化沒有數據,所以我們disable掉“編輯”按鈕

    self.navigationItem.leftBarButtonItem=self.editButtonItem;

    self.navigationItem.leftBarButtonItem.enabled=NO;

    self.editButtonItem.title=@"編輯";

    

    //標題

    self.navigationItem.title=self.titleMsg;

    

    _tbv.delegate=self;

    [self.view addSubview:_tbv];

}


    

?然后寫上必須釋放的方法

      -(void)dealloc

{

    [self removeObserver:self forKeyPath:@"dataSrc"];

    [self removeObserver:self forKeyPath:@"titleMsg"];

}


    

?隨后當用戶點擊“+”按鈕時,新增的處理函數如下:

      
        //
      
      
        導航欄上增加按鈕的調用方法
      
      

-(
      
        void
      
      
        )add

{

    
      
      
        //
      
      
        我們打算設置一個靜態的整形記錄當前的排序值
      
      
        static
      
      
        int
      
       myIndex=
      
        0
      
      
        ;

    

    
      
      
        //
      
      
        每次進來,我們就把當前的排序值作為新增的對象

    
      
      
        //
      
      
        所以調用KVO提供的新增接口,插入新元素的位置始終位于最后
      
      

    [self insertObject:[NSString stringWithFormat:
      
        @"
      
      
        %d
      
      
        "
      
      
        ,myIndex] inDataSrcAtIndex:[self countOfDataSrc]];

    

    myIndex
      
      ++
      
        ;

    

    self.titleMsg
      
      =[NSString stringWithFormat:
      
        @"
      
      
        新增:%d
      
      
        "
      
      
        ,myIndex];

}
      
    

當用戶點擊“編輯”按鈕時,被調用的系統默認的方法進行重寫

      
        //
      
      
        當用戶單擊“編輯”按鈕時,對被調用的系統默認方法進行重寫
      
      

-(
      
        void
      
      
        )setEditing:(BOOL)editing animated:(BOOL)animated

{

    
      
      
        //
      
      
        UIViewController 提供的editButtonItem 默認會調用此方法

    
      
      
        //
      
      
        所以我們重寫此方法,第一步就是讓表視圖變成編輯狀態,供我們刪除內容用
      
      
            

    [_tbv setEditing:editing animated:animated];

    

    
      
      
        //
      
      
        第二步讓super繼續操作

    
      
      
        //
      
      
        目的是不改變UIViewController對于editButtonItem原有的動作

    
      
      
        //
      
      
        如果不加,那就是等于我們將這個方法截獲了

    
      
      
        //
      
      
        效果不同體現在:editButtonItem不會在Edit狀態和Done狀態之間切換
      
      
            [super setEditing:editing animated:animated];

    

    
      
      
        if
      
      
        (editing)

    {

        self.editButtonItem.title
      
      =
      
        @"
      
      
        完成
      
      
        "
      
      
        ;

    }

    
      
      
        else
      
      
        

    {

        self.editButtonItem.title
      
      =
      
        @"
      
      
        編輯
      
      
        "
      
      
        ;

    }

}
      
    

當用戶按下“Delete”后,作為表視圖的代理,“tableView:commitEditingStyle:forRowAtIndexPath:”,這個代理方法將會被調用,所以需要實現如下代碼:

      -(
      
        void
      
      )tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *
      
        )indexPath

{

    
      
      
        if
      
      (editingStyle==
      
        UITableViewCellEditingStyleDelete)

    {

        self.titleMsg
      
      =[NSString stringWithFormat:
      
        @"
      
      
        刪除:[%d]
      
      
        "
      
      
        ,indexPath.row];

        [self removeObjectFromDataSrcAtIndex:indexPath.row];

    }

}
      
    

KVO所觸發的回調函數的實現方式

      
        //
      
      
        KVO監視某個屬性時,當屬性發生變化會受到此回調
      
      

-(
      
        void
      
      )observeValueForKeyPath:(NSString *)keyPath ofObject:(
      
        id
      
      )
      
        object
      
       change:(NSDictionary *)change context:(
      
        void
      
       *
      
        )context

{

    
      
      
        if
      
      ([keyPath isEqualToString:
      
        @"
      
      
        titleMsg
      
      
        "
      
      
        ])

    {

        [self handleTitleChangeofObject:
      
      
        object
      
      
        

                                 change:change

                                context:context];

        
      
      
        return
      
      
        ;

    }

    

    NSInteger changeRow
      
      =
      
        0
      
      
        ;

    
      
      
        //
      
      
        NSKeyValueChangeIndexesKey鍵中記錄了集合屬性改變位置等重要信息
      
      

    NSIndexSet *indices=
      
        [change objectForKey:NSKeyValueChangeIndexesKey];

    

    
      
      
        if
      
      
        (indices)

    {

        
      
      
        //
      
      
        我們每次只改集合中的一處地方,所以我們可以用firstIndex來簡單的取出改變的地方

        
      
      
        //
      
      
        如果時多處地方遭到修改,需要使用NSindexSet類提供的getIndexes方法
      
      

        changeRow=
      
        indices.firstIndex;

    }

    

    
      
      
        //
      
      
        制作NSIndexPath,為了提供給表視圖進行UI更新
      
      

    NSIndexPath *changeIndexPath=[NSIndexPath indexPathForRow:changeRow inSection:
      
        0
      
      
        ];

    

    
      
      
        //
      
      
        NSKeyValueChangeKindKey信息中記錄了監視屬性的值變化類型
      
      

    NSNumber *kind=
      
        [change objectForKey:NSKeyValueChangeKindKey];

    
      
      
        switch
      
      
         ([kind intValue]) {

        
      
      
        case
      
      
         NSKeyValueChangeInsertion:

            
      
      
        //
      
      
        此新增方法后,表視圖重繪
      
      
                    [_tbv insertRowsAtIndexPaths:[NSArray arrayWithObjects:changeIndexPath] withRowAnimation:UITableViewRowAnimationFade];

            
      
      
        break
      
      
        ;

         
      
      
        case
      
      
         NSKeyValueChangeRemoval:

            
      
      
        //
      
      
        次刪除方法后,表視圖會重繪
      
      
                    [_tbv deleteRowsAtIndexPaths:[NSArray arrayWithObjects:changeIndexPath] withRowAnimation:UITableViewRowAnimationFade];

            
      
      
        break
      
      
        ;

        
      
      
        default
      
      
        :

            
      
      
        break
      
      
        ;

    }

    

    
      
      
        //
      
      
        控制編輯按鈕

    
      
      
        //
      
      
        如果表數據有記錄
      
      
        if
      
      ([self countOfDataSrc]>
      
        0
      
      
        )

    {

        
      
      
        //
      
      
        讓編輯按鈕可用
      
      

        self.navigationItem.leftBarButtonItem.enabled=
      
        YES;

    }

    
      
      
        else
      
      
        

    {

        
      
      
        //
      
      
        讓編輯按鈕不可用,并且遵循UIVievController對于不可用時的UI處理(比如變成edit)
      
      
                [self setEditing:NO animated:YES];

        self.navigationItem.leftBarButtonItem.enabled
      
      =
      
        NO;

    }

    

}
      
    

下列代碼則是對于界面標題的更新代碼

      -(
      
        void
      
      )handleTitleChangeofObject:(
      
        id
      
      )
      
        object
      
      
        

                          change:(NSDictionary 
      
      *
      
        )change

                         context:(
      
      
        void
      
       *
      
        )context

{

    self.navigationItem.title
      
      =
      
        self.titleMsg;

}
      
    

剩下的表視圖的實現方法就不貼了

KVO 的使用和舉例


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 26uuu欧美视频在线观看 | 狠狠狠狠狠狠干 | 午夜剧场毛片 | 国产精品视频久久久久久 | 92在线视频 | 噜噜嘿在线视频免费观看 | 国产精品二区页在线播放 | 青青青青久久精品国产h | 一区二区中文字幕 | 久久高清一级毛片 | 亚洲伦理中文字幕一区 | 久久99久久99精品免费看动漫 | 九九热国产在线 | 久久亚洲国产精品一区二区 | 国产日本欧美在线观看 | 欧美亚洲另类久久综合 | 亚洲最大在线观看 | 色婷婷免费视频 | 亚洲国产天堂久久九九九 | 丁香色婷婷 | 午夜欧美福利视频 | 在线观看 一区 | 欧美13一14周岁a在线播放 | 免费看操片 | 久久久www免费看片 久久久不卡 | 99国产精品视频免费观看 | 久热网| 香蕉eeww99国产在线观看 | 一二三区免费视频 | 久久经典免费视频 | 亚洲日本中文字幕 | 国产一区二区三区四 | 91嫩草国产线免费观看 | 欧美综合色区 | 最新日本一级中文字幕 | 日日摸夜夜摸狠狠摸97 | 欧美日韩免费播放一区二区 | 黄片毛片在线看 | 久草在线观看资源 | 99热久久这里只有精品99 | 日日干日日操 |