6

次のコードがあります:

@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

viewDidLoadそこで、メソッドの先頭にブレークポイントを配置しましたviewDidDisappear。最初に に移動するアプリを起動するとviewDidload、ダウンロード後に に移動しviewDidDisappearます。

しかし、私のアプリでは、データを再度ダウンロードして投稿しnotification: NSDownloadCompleteます。そして、この VC では動作しますが、後で以下を使用して削除しました:

[[NSNotificationCenter defaultCenter] removeObserver:self]

この VCviewDidLoadは最初に 1 回使用され、再度 addObserver を使用することはできません。

なにが問題ですか?

編集 addObserver メソッドをviewWillAppearまたはに配置しようとしましたviewWillDisappear-結果はありません。NSLog(@"addObserver");前に追加します

 [[NSNotificationCenter defaultCenter] addObserverForName...

ビューでDidLoad

そして書く

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

ログに次のように表示されます。

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

どうしたの?

EDIT 2 オブザーバーを削除する必要があることがわかりますが、 addObserver メソッドで再びブロックを実行します

ここに画像の説明を入力

4

3 に答える 3

5

e1985 が明らかにしようとしているのは、あなたのaddObserverremoveObserver呼び出しが適切にバランスされていないということです。viewDidLoadVC の初期化後に一度だけ呼び出さviewDidDisappearれますが、View Controller が画面外に移動するたびに呼び出されます。

addObserverこの問題を解決するには、とのremoveObserver呼び出しのバランスを取る必要があります。それらを で作成しviewDidLoad、もう一方を で作成するかdealloc、e1985 が提案したようにviewDidAppear:とで作成しviewDidDisappear:ます。

編集:わかりました。問題は、オブザーバーとしてaddObserverForName:object:queue:usingBlock:登録しないものを使用しているという事実から生じます(最初の引数として渡す場合と同様)。selfaddObserver:selector:name:object:self

したがって、あなたの場合、オブザーバーでは[[NSNotificationCenter defaultCenter] removeObserver:self];ないため、何もしません。ドキュメントに示されているように、代わりに の戻り値をself呼び出す必要があります。removeObserver:addObserverForName:object:queue:usingBlock:

戻り値

オブザーバーとして機能する不透明なオブジェクト。

したがって、コードは次のようになります。

// 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
于 2013-06-10T11:41:14.407 に答える
3

使用しているパターンが正しくありません。でオブザーバーを追加し、viewDidAppear:で削除する必要がありviewDidDisappear:ます。

于 2013-06-10T11:25:01.220 に答える