2010-09-22 16 views
16

Desidero impostare il delegato di un oggetto all'interno di un metodo di classe in Objective-C. Pseudo-codice:Objective-C equivalente alle classi anonime di Java nei metodi di classe

+ (ClassWithDelegate*) myStaticMethod { 
    if (myObject == nil) { 
     myObject = [[ClassWithDelegate alloc] init]; 
     // myObject.delegate = ? 
    } 
    return myObject; 
} 

In Java vorrei semplicemente creare una classe anonima che implementava il protocollo delegato. Come posso fare qualcosa di simile in Objective-C?

Fondamentalmente vorrei evitare di creare una classe separata (e file) per implementare un semplice protocollo delegato.

+0

possibile duplicato di [? Implementazione delegato anonimo in Objective-C] (http://stackoverflow.com/questions/766475/anonymous-delegate-implementation-in- obiettivo-c) –

+0

@Dave DeLong Chiarito titolo per differenziare da quella domanda. In questo caso il contesto è un metodo statico. – hpique

+0

il contesto non ha importanza. Devi fornire un oggetto ('id') come delegato, e l'altra domanda risponde chiaramente che non esiste una classe anonima in Objective-C (ancora), quindi dovrai usare un oggetto normale. –

risposta

13

Attualmente non ci sono classi anonime in Objective-C.

Spesso è possibile utilizzare un oggetto già esistente. Ad esempio, per un NSTableViewDataSource, è possibile implementare i metodi nel documento o visualizzare il controller e passarlo come delegato.

Oppure è possibile avere l'oggetto stesso implementare il protocollo e renderlo il proprio delegato nel caso predefinito.

Oppure i metodi che inviano i messaggi delegati possono controllare un delegato nullo e fare qualcosa di sensato in quella situazione.

Oppure è possibile dichiarare e definire una classe all'interno del file di implementazione che si sta creando l'oggetto che necessita di un delegato.

+0

Grazie JeremyP! Quindi fondamentalmente in questo caso potrei definire una classe ad-hoc nel file di implementazione, creare un'istanza nel messaggio di classe e assegnarla come delegato. Sarebbe corretto? – hpique

+0

Questo è probabilmente il modo giusto per farlo in questa situazione. – JeremyP

16

Come jeremyp ha giustamente detto, Non ci sono classi anonime in Objective C che ci sono in Java.

Ma in Java, le classi anonime vengono utilizzate principalmente per implementare l'interfaccia a metodo singolo o quella che chiamiamo anche un'interfaccia funzionale .

noi, per evitano il implementare l'interfaccia in una classe solo per un'implementazione del metodo che è più comunemente utilizzato per ascoltatori, osservatori e gestori di eventi.

questo è in gran parte fatto a causa della mancanza di funzioni prima classe anonima in Java (precedenti alla versione 8 e progetto lambda).

Objective C ha qualcosa chiamato come blocchi, dove è possibile passare direttamente un blocco che contiene l'implementazione di tale metodo unico anziché una classe vuota avvolgendolo.

Esempio:

Un uso di Anonymous classe in Java

//Functional interface 
interface SomethingHandler 
{ 
    void handle(Object argument); 
} 

//a method that accepts the handler in some other class 
class SomeOtherClass 
{ 
    void doSomethingWithCompletionHandler(SomethingHandler h){ 
     // do the work that may consume some time in a separate thread may be. 
     // when work is done call the handler with the result which could be any object 
     h.handler(result); 
    }; 
} 

// Somewhere else in some other class, in some other code 
// passing the handler after instantiating someObj as an object of SomeOtherClass which can use the handler as needed 
SomeOtherClass someObj = new SomeOtherClass(); 
someObj.doSomethingWithCompletionHandler(new SomethingHandler() 
         { 
           void handle(Object argument) 
           { 
           // handle the event using the argument 
           } 
         }); 

In Objective C

// declare the handler block 
typedef void (^SomethingHandler)(id argument){} 

// this interface is different than Java interface which are similar to Protocols 
@interface SomeOtherClass 
-(void)doSomethingWithCompletionHandler:(SomethingHandler)h; 
@end 

@implementation SomeOtherClass 
-(void)doSomethingWithCompletionHandler:(SomethingHandler)h 
{ 
      // do the work that may consume some time in a separate thread may be. 
      // when work is done call the handler with the result which could be any object 
      h(result); 
} 

@end 

    // passing the handler after instantiating someObj as an object of SomeOtherClass which can use the handler as needed 

SomeOtherClass* someObj = [[SomeOtherClass alloc] init]; // ARC :) 

[someObj doSomethingWithCompletionHandler:^(id argument) 
              { 
               // handle the event using the argument 
              }]; 
1

classi anonimi possono essere attuate con biblioteca.Diversi mesi fa ho lavorato sulla forcella MMMutableMethods per migliorare la vecchia implementazione (discutendo con l'autore) e aggiungere il mio meccanismo senza alcuna manipolazione del runtime obj-c.

https://github.com/k06a/MMMutableMethods

A. primo meccanismo funziona su obj-c runtime creazione classe:

MM_CREATE(MM_REUSE,^(Class class){ 
    [class addMethod:@selector(onResultWithId:) 
     fromProtocol:@protocol(AMCommandCallback) 
      blockImp:^(id this,id res){ 
       NSLog(@"onResultWithId: %@",res); 
      }]; 
    [class addMethod:@selector(onErrorWithJavaLangException:) 
     fromProtocol:@protocol(AMCommandCallback) 
      blockImp:^(id this,JavaLangException *e){ 
       NSLog(@"onErrorWithJavaLangException: %@",e); 
      }]; 
}) 

B. Secondo meccanismo funziona sul semplice messaggio implementazione in avanti:

MM_ANON(^(MMAnonymousClass *anon){ 
    [anon addMethod:@selector(onResultWithId:) 
     fromProtocol:@protocol(AMCommandCallback) 
      blockImp:^(id this,id res){ 
       NSLog(@"onResultWithId: %@",res); 
      }]; 
    [anon addMethod:@selector(onErrorWithJavaLangException:) 
     fromProtocol:@protocol(AMCommandCallback) 
      blockImp:^(id this,JavaLangException *e){ 
       NSLog(@"onErrorWithJavaLangException: %@",e); 
      }]; 
}) 

Prima si crea nuove classi obc-j in runtime, consente di creare classi MM_CREATE_CLASS(MM_REUSE, *) e istanze direttamente con MM_CREATE(MM_REUSE, *). Le classi verranno create solo alla prima esecuzione e riutilizzate per impostazione predefinita, ma è possibile evitare il riutilizzo chiamando MM_CREATE_CLASS_ALWAYS(*) e MM_CREATE_ALWAYS(*).

Il secondo meccanismo non crea alcuna istanza di runtime, basta ricordare i blocchi per i selettori e le chiamate al metodo di inoltro.

Preferisco il secondo modo di non creare molte classi in runtime. IMHO è molto più sicuro e abbastanza potente.

Per utilizzare questa libreria solo:

pod 'MMMutableMethods', :git => 'https://github.com/k06a/MMMutableMethods' 
Problemi correlati