2013-06-10 35 views
5

tôi có mã tiếp theo:removeObserver không làm việc

@implementation SplashViewVC 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    self.splashView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"Default.png"]]; 
    self.activityIndicator.originY = 355.f; 
    [[NSNotificationCenter defaultCenter] addObserverForName:NCDownloadComplete object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *n){ 
     NSInteger errorCode = [n.userInfo[@"errorCode"] integerValue];   
     [self.activityIndicator stopAnimating]; 
     if (errorCode == ERROR_CODE_NO_CONNECTION) { 
      UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Some problem with server" delegate:self cancelButtonTitle:@"try again" otherButtonTitles:nil]; 
      [alertView show]; 
     } else if (errorCode == 0) { 
      [self dismissViewControllerAnimated:YES completion:nil]; 
     } 
    }]; 
    [self downloadData]; 
} 

- (void)downloadData 
{ 
    [self.activityIndicator startAnimating]; 
    [[Server sharedServer] getMovieData]; 
} 

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 
{ 
    [self downloadData]; 
} 

- (void)viewDidDisappear:(BOOL)animated 
{ 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
    [super viewDidDisappear:animated]; 
} 

@end 

Vì vậy, tôi đặt breakpoint tại bắt đầu của viewDidLoad phương pháp, trong viewDidDisappear. Khi tôi khởi chạy ứng dụng, trước tiên hãy truy cập viewDidload, sau khi tải xuống, hãy truy cập viewDidDisappear.

Nhưng trong ứng dụng của tôi, tôi lại tải xuống dữ liệu và đăng notification: NSDownloadComplete. Và trong VC này nó là công việc, nhưng tôi sau gỡ bỏ sử dụng:

[[NSNotificationCenter defaultCenter] removeObserver:self] 

VC này sử dụng viewDidLoad một lần vào đầu & không thể một lần nữa addObserver.

Điều gì là sai?

EDIT tôi cố gắng đưa addObserver phương pháp để viewWillAppear hoặc viewWillDisappear - không có kết quả. tôi thêm NSLog(@"addObserver"); trước

[[NSNotificationCenter defaultCenter] addObserverForName... 

trong viewDidLoad

và viết

- (void)viewDidDisappear:(BOOL)animated 
{ 
    NSLog(@"removeObserver"); 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
    [super viewDidDisappear:animated]; 
} 

Trong log tôi thấy:

2013-06-10 14:32:05.646 myApp[9390:c07] addObserver 
2013-06-10 14:32:06.780 myApp[9390:c07] removeObserver 

gì sai?

EDIT 2 bạn có thể thấy rằng người quan sát phải được loại bỏ nhưng nó lại chạy khối trong phương pháp addObserver

enter image description here

+3

đó là mã bản sao & dán? Tôi chỉ tự hỏi vì 'viewDidLoad' của bạn chỉ là 3 dòng và sau đó có các câu lệnh không có trong bất kỳ phương thức nào. Đó không phải là hợp lệ;) – HAS

+0

@HAS tất cả công việc tốt, ngoại trừ câu hỏi của tôi =) – user2213271

+0

Xin lỗi, nhưng đó không phải là;) Dấu ngoặc nhọn sau 'self.activityIndicator.originY = 355.f;' là sai. Xóa và bạn sẽ có mã hợp lệ;) – HAS

Trả lời

24

Ngoài thêm/gỡ bỏ quan sát gọi không đúng là cân bằng, ít lưu ý trong câu trả lời khác, có một vấn đề khác.

Mã của bạn để xóa người quan sát sai. Đối với người quan sát dựa trên khối, giá trị trả lại của addObserver phải được tính làm đối số cho removeObserver. Vì vậy, bạn nên thêm thuộc tính

@property(nonatomic, strong) id observer; 

vào lớp học. Sau đó, bạn thêm các quan sát viên với

self.observer = [[NSNotificationCenter defaultCenter] addObserverForName:NCDownloadComplete object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *n){ 
    // ... 
}]; 

và loại bỏ nó với

[[NSNotificationCenter defaultCenter] removeObserver:self.observer]; 
+0

Vâng, điều này giải quyết được vấn đề của tôi Cảm ơn bạn =) – user2213271

+0

cảm ơn bạn rất nhiều Martin, giải pháp của bạn hoạt động rất tốt. – Wilson

3

Các mô hình bạn đang sử dụng là không đúng. Bạn nên thêm người quan sát vào viewDidAppear: và xóa nó trong viewDidDisappear:.

+1

hoặc thêm người quan sát trong 'viewWillAppear:' –

+1

@ e1985 không được trợ giúp. Và viewWillAppear: không giúp đỡ quá – user2213271

5

Điều e1985 đang cố gắng vạch trần là các cuộc gọi addObserverremoveObserver của bạn không được cân bằng hợp lý. viewDidLoad chỉ được gọi một lần sau khi khởi tạo VC, nhưng viewDidDisappear được gọi mỗi khi bộ điều khiển chế độ xem được di chuyển khỏi màn hình.

Để giải quyết vấn đề của bạn, bạn phải cân bằng addObserverremoveObserver các cuộc gọi, hoặc bằng cách làm cho chúng trong viewDidLoad và một ở dealloc, hoặc - như e1985 gợi ý - trong viewDidAppear:viewDidDisappear:.

EDIT: Ok, vì vậy vấn đề của bạn xuất phát từ thực tế là bạn đang sử dụng addObserverForName:object:queue:usingBlock: mà không đăng ký self như quan sát (như addObserver:selector:name:object: sẽ làm gì nếu bạn vượt qua self như là đối số đầu tiên).

Vì vậy, trong trường hợp của bạn, [[NSNotificationCenter defaultCenter] removeObserver:self]; không có gì vì self không phải là người quan sát.thay vào đó bạn nên gọi removeObserver: trên giá trị trở lại của addObserverForName:object:queue:usingBlock:, như in the doc:

Return Value

Một đối tượng đục để hoạt động như người quan sát.

Vì vậy, mã của bạn nên trông giống như sau:

// header file .h 
@interface SplashViewVC : UIViewController 

@property (strong, nonatomic) id downloadCompleteObserver; 

@end 

// implementation file .m 
@implementation SplashViewVC 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    // [...] snip 

    self.downloadCompleteObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NCDownloadComplete object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *n){ 
     NSInteger errorCode = [n.userInfo[@"errorCode"] integerValue];   
     [self.activityIndicator stopAnimating]; 
     if (errorCode == ERROR_CODE_NO_CONNECTION) { 
      UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Some problem with server" delegate:self cancelButtonTitle:@"try again" otherButtonTitles:nil]; 
      [alertView show]; 
     } else if (errorCode == 0) { 
      [self dismissViewControllerAnimated:YES completion:nil]; 
     } 
    }]; 
    [self downloadData]; 
} 

// [...] snip 

- (void)dealloc 
{ 
    [[NSNotificationCenter defaultCenter] removeObserver:self.downloadCompleteObserver]; 
    [super dealloc]; 
} 

@end 
+0

Tôi di chuyển trong viewDidAppear: và không có kết quả = ( – user2213271

+0

Vui lòng giải thích vấn đề rõ ràng hơn sau đó. "Không hoạt động"? –

+0

i thêm màn hình nơi bạn có thể thấy khối đó được gọi sau phương thức removeObserver. – user2213271