2012-08-11 15 views
23

Việc sử dụng thông số ngữ cảnh trong phương pháp sau được sử dụng để đăng ký thông báo giá trị khóa là gì. Các tài liệu chỉ biểu thị nó như là một tập dữ liệu tùy ý.tầm quan trọng của tham số ngữ cảnh trong Giá trị khóa quan sát

addObserver:self forKeyPath:@"selectedIndex" options:NSKeyValueObservingOptionNew context:nil 

Ai đó có thể làm sáng tỏ mục đích đằng sau nó là những gì ...

Cảm ơn

+0

thể trùng lặp của [Các thông số từ observeValueForKeyPath: ofObject: thay đổi: bối cảnh:] (http://stackoverflow.com/questions/1625575/parameters-from-observevalueforkeypathofobjectchangecontext) –

Trả lời

73

Tôi hy vọng lời giải thích này không phải là quá trừu tượng để hiểu.

Giả sử bạn tạo một lớp MyViewController, là lớp con của UIViewController. Bạn không có mã nguồn của UIViewController.

Bây giờ bạn quyết định thực hiện MyViewController sử dụng KVO để quan sát các thay đổi đối với thuộc tính center của self.view. Vì vậy, bạn hợp lệ thêm mình là một người quan sát:

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 
    [self.view addObserver:self forKeyPath:@"center" options:0 context:NULL]; 
} 

- (void)viewDidDisappear:(BOOL)animated { 
    [self.view removeObserver:self forKeyPath:@"center"]; 
    [super viewDidDisappear:animated]; 
} 

Vấn đề ở đây là bạn không biết nếu UIViewController cũng đăng ký chính nó như là một quan sát viên của self.view 's center. Nếu có, bạn có thể có hai vấn đề:

  1. Bạn có thể được gọi hai lần khi trung tâm của chế độ xem thay đổi.
  2. Khi bạn tự xóa mình với tư cách người quan sát, bạn cũng có thể xóa đăng ký KVO UIViewController.

Bạn cần một cách để đăng ký chính mình với tư cách là người quan sát có thể phân biệt với đăng ký KVO của UIViewController. Đó là nơi mà đối số context xuất hiện. Bạn cần phải chuyển một giá trị cho context mà bạn hoàn toàn chắc chắn UIViewControllerkhông phải là sử dụng làm đối số context. Khi bạn hủy đăng ký, bạn lại sử dụng cùng một số context để bạn chỉ xóa đăng ký của mình, chứ không phải đăng ký của UIViewController. Và trong phương thức observeValueForKeyPath:ofObject:change:context: của bạn, bạn cần phải kiểm tra số context để xem thư đó là dành cho bạn hay cho siêu lớp của bạn.

Một cách để đảm bảo bạn sử dụng số context mà không có gì khác sử dụng là tạo biến số static trong MyViewController.m. Sử dụng nó khi bạn đăng ký và hủy đăng ký, như thế này:

static int kCenterContext; 

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 
    [self.view addObserver:self forKeyPath:@"center" options:0 context:&kCenterContext]; 
} 

- (void)viewDidDisappear:(BOOL)animated { 
    [self.view removeObserver:self forKeyPath:@"center" context:&kCenterContext]; 
    [super viewDidDisappear:animated]; 
} 

Sau đó, trong phương pháp observeValueForKeyPath:... của bạn, kiểm tra xem nó như thế này:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
    change:(NSDictionary *)change context:(void *)context 
{ 
    if (context == &kCenterContext) { 
     // This message is for me. Handle it. 
     [self viewCenterDidChange]; 
     // Do not pass it on to super! 
    } else { 
     // This message is not for me; pass it on to super. 
     [super observeValueForKeyPath:keyPath ofObject:object 
      change:change context:context]; 
    } 
} 

Bây giờ bạn sẽ được bảo đảm không ảnh hưởng đến việc KVO của lớp cha của bạn, nếu nó làm bất kỳ. Và nếu ai đó làm cho một lớp con của MyViewController cũng sử dụng KVO, nó sẽ không can thiệp vào KVO của bạn.

Cũng lưu ý rằng bạn có thể sử dụng ngữ cảnh khác nhau cho mỗi đường dẫn chính mà bạn quan sát. Sau đó, khi hệ thống thông báo cho bạn về một thay đổi, bạn có thể kiểm tra ngữ cảnh thay vì kiểm tra đường dẫn chính. Kiểm tra tính bình đẳng của con trỏ nhanh hơn một chút so với việc kiểm tra tính bình đẳng của chuỗi.Ví dụ:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
    change:(NSDictionary *)change context:(void *)context 
{ 
    if (context == &kCenterContext) { 
     [self viewCenterDidChange]; 
     // Do not pass it on to super! 
    } else if (context == &kBackgroundColorContext) { 
     [self viewBackgroundDidChange]; 
     // Do not pass it on to super! 
    } else if (context == &kAlphaContext) { 
     [self viewAlphaDidChange]; 
     // Do not pass it on to super! 
    } else { 
     // This message is not for me; pass it on to super. 
     [super observeValueForKeyPath:keyPath ofObject:object 
      change:change context:context]; 
    } 
} 
+0

Cảm ơn rất nhiều cho lời giải thích chi tiết của bạn .Thực sự đánh giá cao nó. Nó đã được khó hiểu với tôi một thời gian tại sao tham số này là quan trọng và trả lời của bạn làm rõ nó. :) – rustylepord

+0

Xin chào tôi có thể sử dụng ngữ cảnh để đặt một số đối tượng và sau đó khi thông báo đến lấy nó o thực hiện một số tác vụ cụ thể dựa trên giá trị được lưu trữ trong ngữ cảnh. – Sandeep

+9

+1 Giải thích rõ ràng. (Một báo trước duy nhất: thuộc tính 'UIView' không tuân thủ KVO. Bạn không thể quan sát' view.center'.) –