2010-09-22 2 views
16

Я хочу установить делегат объекта внутри метода класса в Objective-C. Псевдокод:Objective-C, эквивалентный анонимным классам Java в методах класса

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

В Java я бы просто создал анонимный класс, который реализовал протокол делегата. Как я могу сделать что-то подобное в Objective-C?

В основном я хотел бы избежать создания отдельного класса (и файлов) для реализации простого протокола делегатов.

+0

возможно дубликат [? Реализации делегата Anonymous в Objective-C] (http://stackoverflow.com/questions/766475/anonymous-delegate-implementation-in- цель-с) –

+0

@Dave DeLong Уточненный заголовок, чтобы отличать этот вопрос. В этом случае контекст является статическим методом. – hpique

+0

контекст не имеет значения. Вы должны предоставить объект ('id') в качестве делегата, а в другом вопросе вполне понятно, что в Objective-C нет пока еще анонимного класса, поэтому вам придется использовать нормальный объект. –

ответ

13

В настоящее время анонимных классов в Objective-C нет.

Часто вы можете использовать уже существующий объект. Например, для NSTableViewDataSource вы можете реализовать методы в контроллере документа или представления и передать это как делегат.

Или вы можете реализовать сам объект протокола и сделать его своим делегатом в случае по умолчанию.

Или методы, которые отправляют сообщения делегата, могут проверять делегата нулевого уровня и делать что-то разумное в этой ситуации.

Или вы можете объявить и определить класс внутри файла реализации, который вы создаете для объекта, которому нужен делегат.

+0

Спасибо JeremyP! Поэтому в основном в этом случае я мог бы определить класс ad-hoc в файле реализации, создать экземпляр в сообщении класса и назначить его как делегат. Правильно ли это? – hpique

+0

Это, вероятно, правильный способ сделать это в этой ситуации. – JeremyP

16

Как верно сказал JeremyP, В Objective C нет анонимных классов, как в Java.

Но в Java, анонимные классы в основном используются для реализации интерфейса одного метода или того, что мы также называем функциональным интерфейсом .

Мы делаем это, чтобы избежать необходимости реализовывать интерфейс в классе только для одной реализации метода, который наиболее часто используется для радиослушателей, наблюдателей и обработчиков событий.

В основном это делается из-за отсутствия анонимных функций первого класса в Java (до версии 8 и проекта лямбда).

Objective C есть то, что называется, как блоков, где вы можете непосредственно передать блок, который содержит реализацию этого единственного метода, а не пустой класс оберточной его.

Пример:

Применение анонимных класса в 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 
           } 
         }); 

В 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

анонимные классы могут быть реализованы с помощью библиотеки.Несколько месяцев назад я работал над вилкой MMMutableMethods, чтобы улучшить старую реализацию (обсуждение с автором) и добавить собственный механизм без каких-либо манипуляций во время выполнения.

https://github.com/k06a/MMMutableMethods

A. Первый механизм работает на Obj-C во время выполнения создания класса:

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. Второй механизм работает на простых сообщений вперед реализации:

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); 
      }]; 
}) 

Первый один создает новые классы obc-j во время выполнения, он позволяет создавать классы MM_CREATE_CLASS(MM_REUSE, *) и непосредственно экземпляры с MM_CREATE(MM_REUSE, *). Классы будут создаваться только при первом выполнении и повторно использоваться по умолчанию, но вы можете избежать повторного использования, вызывая MM_CREATE_CLASS_ALWAYS(*) и MM_CREATE_ALWAYS(*).

Второй механизм не создает экземпляры времени выполнения, просто запоминает блоки для селекторов и пересылает им вызовы методов.

Я предпочитаю второй способ не создавать много классов во время выполнения. ИМХО намного безопаснее и достаточно мощно.

Чтобы использовать эту библиотеку только:

pod 'MMMutableMethods', :git => 'https://github.com/k06a/MMMutableMethods' 
Смежные вопросы