2010-02-01 11 views
17

voglio aggiungere un selettore in un dizionario (lo scopo principale è per identificare il metodo di callback e delegato dopo l'arrivo a fare qualcosa)Aggiungere selettore del metodo in un dizionario

ma trovo che io non posso farlo, la il programma riceverà un errore "EXC_BAD_ACCESS". C'è qualche altro modo per me di aggiungere il selettore di metodo a un dizionario? Grazie per il vostro aiuto.

risposta

22

Aggiunta di una nuova voce a un dizionario fa due cose (oltre ad aggiungere al dizionario, ovviamente):

  1. ci vuole una copia del valore della chiave. Ciò significa che l'oggetto chiave deve implementare il valore del protocollo NSCopying
  2. retain s. Questo significa che ha bisogno di implementare il protocollo NSObject

E 'probabilmente il secondo che sta causando il vostro EXC_BAD_ACCESS.

Ci sono almeno due modi per aggirare questo problema.

In primo luogo, anziché aggiungere il selettore è possibile aggiungere l'istanza della classe che implementa il selettore al dizionario. Di solito la tua classe erediterà da NSObject e funzionerà correttamente. Nota che manterrà comunque la classe, forse non quello che vuoi.

In secondo luogo, è possibile convertire un selettore in una stringa (e viceversa) utilizzando NSSelectorFromString e NSStringFromSelector (docs are here).

+0

Non implementare un metodo non causa un EXC_BAD_ACCESS. Si ottiene un errore "non riconosce il selettore". Piuttosto, il problema è il fatto che i selettori non sono affatto oggetti. – user102008

+0

@ user102008 Sì, si blocca perché non sono oggetti. Ma ancora non funzionerebbe correttamente se gli oggetti non implementassero 'retain' e' release'. –

1

L'idioma comune in Obj-C è di avere nomi specifici per i callback per eventi specifici. (Tale parserDidBeginDocument: da NSXMLParserDelegate). Se è necessario che sia in grado di specificare i nomi, è probabile che l'unica soluzione sia aggiungere i nomi dei selettori come @"mySelector:withArgument:context:" o somesuch.

+3

È possibile convertire tra SEL e NSString utilizzando NSSelectorFromString e NSStringFromSel ettore –

+0

Uso un oggetto singleton per l'accesso a Internet. e ho un nome di metodo: "getFooWithDelegate: callbackSelector:" e voglio aggiungere il delegato e il callback a un dizionario di richieste usando un UUID di richiesta come chiave. Puoi spiegare di più sull'aggiunta del "nome del selettore" che hai menzionato? – KONG

+0

@athanhcong: di nuovo; sembra davvero come se dovessi avere un singolo nome specifico per il selettore in questione, ad es. 'internetConnection: receivedFoo: withUUID:', dal momento che dovrai comunque scrivere il metodo di ricezione per ricevere l'oggetto in modo abbastanza specifico. Se quello per qualsiasi motivo non è un'opzione; useresti 'NSSelectorFromString()' e 'NSStringFromSelector()' come descritto nel post di Stephen Darlingtons. –

2

ricevo la mia risposta sulla base del commento di Zydeco:

È possibile convertire tra SEL e NSString utilizzando NSSelectorFromString e NSStringFromSelector

36

So che questa domanda è stato risposto molto tempo fa , ma nel caso in cui qualcuno si imbatta in esso come ho fatto ...

La combinazione di NSStringFromSelector e NSSelectorFromString come ans cercato sopra è probabilmente il modo migliore per andare. Ma se lo vuoi davvero, puoi utilizzare un selettore come valore o chiave in un NSDictionary.

Un selettore (tipo SEL) è implementato come puntatore a una struttura nei runtime Objective-C di Apple. Un puntatore non può essere utilizzato direttamente in un dizionario, ma un puntatore può essere avvolto in un oggetto NSValue che può essere utilizzato.

Usando questo metodo è possibile memorizzare un selettore come un valore in un dizionario usando codice come questo:

 
dictionary = 
    [NSDictionary dictionaryWithObject:[NSValue valueWithPointer:selector] 
           forKey:key]; 

Un selettore può essere recuperato utilizzando il codice come questo:

 
SEL selector = [[dictionary objectForKey:key] pointerValue]; 

Allo stesso modo per l'utilizzo un selettore come chiave:

 
dictionary = 
    [NSDictionary dictionaryWithObject:value 
           forKey:[NSValue valueWithPointer:selector]]; 

value = [dictionary objectForKey:[NSValue valueWithPointer:selector]]; 
+3

+1 utilizzando questo metodo per memorizzare la chiave è più efficiente della conversione in una stringa perché il confronto tra puntatori è O (1) mentre il confronto tra stringhe è O (n) – user102008

Problemi correlati