2013-08-07 15 views
8

Sto comunicando tra due classi con NSNotificationCenter. Il mio problema è che sebbene tocchi un pulsante una sola volta (e che il pulsante si spenga solo una volta), produco involontariamente un numero crescente di notifiche da una sola chiamata a NSNotificationCenter.NSNotifica inviata una volta, ma viene ricevuta più volte

Ecco una migliore spiegazione del problema, con il codice:


mie due classi sono il MainView classe e la Menu classe.

Quando una vista in MainView classe è sfruttato, si lancia una vista creata e governata dal Menu classe. Questo codice viene chiamato quando l'MainView viene inizializzato:

menu=[[MyMenu alloc] init]; 
UITapGestureRecognizer * tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapped:)]; 
[tap setNumberOfTapsRequired:1]; 
[container addGestureRecognizer:tap]; 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onChangeItem:) name:@"ItemChange" object:nil]; 

questo gesto incendi Recognizer fuori questo metodo, anche nel MainView classe:

- (void) onTapped: (UIGestureRecognizer*) recognizer { 
    NSLog(@"tap"); 
    [menu displayMenu]; 
} 

Questo è come il Menu classe inizializza:

- (MyMenu*) init { 
    self=[super init]; 
    UICollectionViewFlowLayout * layout=[[UICollectionViewFlowLayout alloc] init]; 
    menuView=[[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, 200, 200) collectionViewLayout:layout]; 
    [menuView setDataSource:self]; 
    [menuView setDelegate:self]; 
    [menuView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"]; 
    [menuView setAutoresizesSubviews:YES]; 
    [menuView setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth]; 
    [menuView setBackgroundColor:[UIColor clearColor]]; 
    [menuView setIndicatorStyle:UIScrollViewIndicatorStyleWhite]; 
    return self; 
} 

E questo è il metodo displayMenu all'interno Menu classe:

- (void) displayMenu { 
    [viewForMenu addSubview:menuView]; 
} 

La classe Menu ha anche un metodo clearMenu:

- (void) clearMenu { 
    [menuView removeFromSuperview]; 
} 

Questo è il codice per ogni cella della UICollectionView, contenuto all'interno my Menu classe:

- (UICollectionViewCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 
    UICollectionViewCell * cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath]; 
    [cell setTag:indexPath.row]; 
    UITapGestureRecognizer * tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onButtonTapped:)]; 
    [tap setNumberOfTapsRequired:1]; 
    [cell addGestureRecognizer:tap]; 
    NSLog(@"button tapped : %d",indexPath.row); 
    return cell; 
} 

Questo chiama il metodo onButtonTapped:, anche nel mio Menu classe:

- (void) onButtonTapped:(UIGestureRecognizer*) recognizer { 
    NSInteger buttonTapped=[[recognizer view] tag]; 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ItemChange" object:nil userInfo:@{@"selected":@(buttonTapped)}]; 
[self clearMenu]; 
} 

Questa notifica viene prelevato dal mio MainView classe con questo codice:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onChangeItem:) name:@"ItemChange" object:nil]; 

Questo chiama il metodo onChangeItem: , all'interno del mio mainView classe:

- (void) onChangeItem: (NSNotification*) notification { 
    NSLog(@"change item to %d",[[[notification userInfo] objectForKey:@"clock"] intValue]); 
} 

Quindi questo è il codice.


OK, ecco il problema: la prima volta che viene visualizzato il menu ottengo questo nel mio ceppo:

...[43023:11f03] tap 
...[43023:11f03] button tapped : 1 
...[43023:11f03] change item to 1 

E questo va bene, questo è quello che mi aspetto.Tuttavia seconda volta ottengo questo:

...[43023:11f03] tap 
...[43023:11f03] button tapped : 1 
...[43023:11f03] change item to 1 
...[43023:11f03] change item to 1 

terza volta ho ottenere questo:

...[43023:11f03] tap 
...[43023:11f03] button tapped : 1 
...[43023:11f03] change item to 1 
...[43023:11f03] change item to 1 
...[43023:11f03] change item to 1 
...[43023:11f03] change item to 1 

E così via. Ogni tocco successivo su una voce di menu raddoppia la quantità di chiamate di notifica.


Per cominciare pensavo di aggiungere più viste e, di conseguenza, ho ottenuto più pulsanti, quindi chiamate di notifiche multiple.

Tuttavia, come si può vedere dal mio log, questo non è il caso. I pulsanti ricevono solo un evento di tocco: si attiva solo una notifica, ma alla classe ricevente vengono inviate più notifiche.

Qualcuno può spiegarmi questo?

Ci scusiamo per il lungo post!

+0

Dove nel codice si chiama '[[NSNotificationCenter defaultCenter] addObserver: self-selector: @selector (onChangeItem :) nome: @ oggetto" ItemChange ": nil];' e lo rimuove? Nel tuo metodo 'onChangeItem:' stampa l'indirizzo di memoria di 'self' che sta osservando la notifica' NSLog (@ "% p", self); 'e mostraci cosa vedi nella console. – 0x8badf00d

+0

Questo viene chiamato quando il ** mainView ** viene inizializzato. Quindi è chiamato solo una volta. – Jimmery

+0

si può aggiungere 'NSLog (@ "% p", auto),' 'nella tua onChangeItem:' metodo e ci mostrano quello che si vede in consolle – 0x8badf00d

risposta

28

Bene, suppongo che [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onChangeItem:) name:@"ItemChange" object:nil]; vengano aggiunti più di una volta.

mi piace per eliminare qualsiasi potenziale osservatore prima di aggiungere un osservatore, in questo modo:

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"ItemChange" object:nil]; 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onChangeItem:) name:@"ItemChange" object:nil]; 

In questo modo ci sarà mai una sola richiamata osservatore.

+0

Questo non ha funzionato, ottengo lo stesso identico risultato. – Jimmery

+0

@Jimmery Se si esegue una ricerca globale per "addObserver:" c'è un "removeObserver:" sopra ciascuno? – CodeReaper

+0

Oh. Ok. Sono un idiota, ho messo il tuo codice nel posto sbagliato. Ora che è nel posto giusto, risolve il mio bug! Grazie mille :) Vorrei poterti offrire più di semplici punti internet falsi! – Jimmery

Problemi correlati