Objective-C에서 콜백 기능을 수행하는 방법은 무엇입니까?
완성 된 몇 가지 예제를보고 싶습니다. 이해해야합니다.
Objective-C에서 콜백 기능을 수행하는 방법은 무엇입니까?
완성 된 몇 가지 예제를보고 싶습니다. 이해해야합니다.
답변:
일반적으로 목표 C의 콜백은 델리게이트로 수행됩니다. 다음은 사용자 지정 대리자 구현의 예입니다.
헤더 파일 :
@interface MyClass : NSObject {
id delegate;
}
- (void)setDelegate:(id)delegate;
- (void)doSomething;
@end
@interface NSObject(MyDelegateMethods)
- (void)myClassWillDoSomething:(MyClass *)myClass;
- (void)myClassDidDoSomething:(MyClass *)myClass;
@end
구현 (.m) 파일
@implementation MyClass
- (void)setDelegate:(id)aDelegate {
delegate = aDelegate; /// Not retained
}
- (void)doSomething {
[delegate myClassWillDoSomething:self];
/* DO SOMETHING */
[delegate myClassDidDoSomething:self];
}
@end
이것은 일반적인 접근 방식을 보여줍니다. 콜백 메서드의 이름을 선언하는 NSObject에 범주를 만듭니다. NSObject는 실제로 이러한 메서드를 구현하지 않습니다. 이러한 유형의 범주를 비공식 프로토콜이라고합니다. 많은 개체가 이러한 메서드를 구현할 수 있다는 의미입니다. 선택 자의 형식 서명을 전달하는 방법입니다.
다음으로 일부 개체는 "MyClass"의 대리자가되고 MyClass는 대리자의 대리자 메서드를 적절하게 호출합니다. 델리게이트 콜백이 선택 사항 인 경우 일반적으로 "if ([delegate respondsToSelector : @selector (myClassWillDoSomething :)) {"과 같이 디스패치 사이트에서이를 보호합니다. 내 예에서 대리자는 두 메서드를 모두 구현해야합니다.
비공식 프로토콜 대신 @protocol로 정의 된 공식 프로토콜을 사용할 수도 있습니다. 그렇게하면 델리게이트 setter의 유형을 변경하고 인스턴스 변수를 " id <MyClassDelegate>
"대신 " id
"로 변경합니다.
또한 대리인이 유지되지 않음을 알 수 있습니다. 이는 일반적으로 "MyClass"인스턴스를 "소유"하는 개체가 일반적으로 대리자이기 때문에 수행됩니다. MyClass가 델리게이트를 유지했다면 유지주기가있을 것입니다. MyClass 인스턴스가 있고 약한 백 포인터이기 때문에 대리자 참조를 지우는 대리자 인 클래스의 dealloc 메서드에서 좋은 생각입니다. 그렇지 않으면 MyClass 인스턴스를 유지하는 것이 있으면 매달린 포인터가 생깁니다.
완전성을 위해 StackOverflow RSS가 무작위로 질문을 부활 시켰으므로 다른 (최신) 옵션은 블록을 사용하는 것입니다.
@interface MyClass: NSObject
{
void (^_completionHandler)(int someParameter);
}
- (void) doSomethingWithCompletionHandler:(void(^)(int))handler;
@end
@implementation MyClass
- (void) doSomethingWithCompletionHandler:(void(^)(int))handler
{
// NOTE: copying is very important if you'll call the callback asynchronously,
// even with garbage collection!
_completionHandler = [handler copy];
// Do stuff, possibly asynchronously...
int result = 5 + 3;
// Call completion handler.
_completionHandler(result);
// Clean up.
[_completionHandler release];
_completionHandler = nil;
}
@end
...
MyClass *foo = [[MyClass alloc] init];
int x = 2;
[foo doSomethingWithCompletionHandler:^(int result){
// Prints 10
NSLog(@"%i", x + result);
}];
다음은 델리게이트의 개념을 배제하고 원시 콜백을 수행하는 예입니다.
@interface Foo : NSObject {
}
- (void)doSomethingAndNotifyObject:(id)object withSelector:(SEL)selector;
@end
@interface Bar : NSObject {
}
@end
@implementation Foo
- (void)doSomethingAndNotifyObject:(id)object withSelector:(SEL)selector {
/* do lots of stuff */
[object performSelector:selector withObject:self];
}
@end
@implementation Bar
- (void)aMethod {
Foo *foo = [[[Foo alloc] init] autorelease];
[foo doSomethingAndNotifyObject:self withSelector:@selector(fooIsDone:)];
}
- (void)fooIsDone:(id)sender {
NSLog(@"Foo Is Done!");
}
@end
일반적으로-[Foo doSomethingAndNotifyObject : withSelector :] 메서드는 비동기식이므로 여기보다 콜백이 더 유용합니다.
이 질문을 최신 상태로 유지하기 위해 iOS 5.0의 ARC 도입은 Blocks를 사용하여 더욱 간결하게 수행 할 수 있음을 의미합니다 .
@interface Robot: NSObject
+ (void)sayHi:(void(^)(NSString *))callback;
@end
@implementation Robot
+ (void)sayHi:(void(^)(NSString *))callback {
// Return a message to the callback
callback(@"Hello to you too!");
}
@end
[Robot sayHi:^(NSString *reply){
NSLog(@"%@", reply);
}];
Objective-C의 블록 구문을 잊어 버린 경우 항상 F **** ng 블록 구문 이 있습니다.
+ (void)sayHi:(void(^)(NSString *reply))callback;
하지+ (void)sayHi:(void(^)(NSString *))callback;
- (void)someMethodThatTakesABlock:(returnType (^nullability)(parameterTypes))blockName;
(참고 parameterTypes
하지 않음 parameters
)
콜백 : Objective C에는 4 가지 유형의 콜백이 있습니다.
선택기 유형 : NSTimer, UIPangesture가 Selector 콜백의 예입니다. 매우 제한된 코드 실행에 사용됩니다.
위임 유형 : 일반적이며 Apple 프레임 워크에서 가장 많이 사용됩니다. UITableViewDelegate, NSNURLConnectionDelegate. 일반적으로 서버에서 비동기식으로 많은 이미지 다운로드를 표시하는 데 사용됩니다.
다른 답변이 있으면 알려주십시오. 감사하겠습니다.