จะเรียกใช้ฟังก์ชันเรียกกลับใน 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
ไฟล์ Implementation (.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 responseToSelector: @selector (myClassWillDoSomething :)) {" ในตัวอย่างของฉันผู้ร่วมประชุมจำเป็นต้องใช้ทั้งสองวิธี
แทนที่จะใช้โปรโตคอลแบบไม่เป็นทางการคุณยังสามารถใช้โปรโตคอลที่เป็นทางการที่กำหนดด้วย @protocol หากคุณทำเช่นนั้นคุณจะเปลี่ยนประเภทของตัวตั้งค่าผู้รับมอบสิทธิ์และตัวแปรอินสแตนซ์เป็น " id <MyClassDelegate>
" แทนที่จะเป็นเพียง " id
"
นอกจากนี้คุณจะสังเกตเห็นว่าไม่มีการเก็บผู้ร่วมประชุมไว้ โดยทั่วไปแล้วจะเกิดขึ้นเนื่องจากวัตถุที่ "เป็นเจ้าของ" อินสแตนซ์ของ "MyClass" มักจะเป็นผู้รับมอบสิทธิ์ด้วย หาก MyClass ยังคงรักษาผู้รับมอบสิทธิ์ไว้ก็จะมีรอบการเก็บรักษา เป็นความคิดที่ดีในเมธอด dealloc ของคลาสที่มีอินสแตนซ์ MyClass และเป็นผู้รับมอบสิทธิ์ในการล้างข้อมูลอ้างอิงของผู้ร่วมประชุมเนื่องจากเป็นตัวชี้หลังที่อ่อนแอ มิฉะนั้นหากมีบางอย่างทำให้อินสแตนซ์ 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:] จะเป็นแบบอะซิงโครนัสซึ่งจะทำให้การโทรกลับมีประโยชน์มากกว่าที่อยู่ที่นี่
เพื่อให้คำถามนี้เป็นปัจจุบันการเปิดตัวARCของ iOS 5.0 หมายความว่าสามารถทำได้โดยใช้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);
}];
มีF **** ng Block Syntaxอยู่เสมอหากคุณลืมไวยากรณ์ Block ของ Objective-C
+ (void)sayHi:(void(^)(NSString *reply))callback;
ไม่ได้+ (void)sayHi:(void(^)(NSString *))callback;
- (void)someMethodThatTakesABlock:(returnType (^nullability)(parameterTypes))blockName;
(Note parameterTypes
not parameters
)
CallBack: มีการโทรกลับ 4 ประเภทใน Objective C
ประเภทตัวเลือก : คุณสามารถดู NSTimer, UIPangesture เป็นตัวอย่างของ Selector callback ใช้สำหรับการเรียกใช้โค้ดที่ จำกัด มาก
ประเภทผู้รับมอบสิทธิ์ : ทั่วไปและใช้มากที่สุดในกรอบงานของ Apple UITableViewDelegate, NSNURLConnectionDelegate โดยปกติจะใช้เพื่อแสดงการดาวน์โหลดรูปภาพจำนวนมากจากเซิร์ฟเวอร์แบบอะซิงโครนัสเป็นต้น
โปรดแจ้งให้เราทราบหากมีคำตอบอื่น ๆ ฉันจะขอบคุณมัน