sub*_*272 2 iphone delegates ios objective-c-blocks
我想编写一个自定义委托方法,以从另一个视图控制器接收我的一个视图控制器中的事件.我应该在这里使用块而不是代表.哪个是首选?
@protocol MyClassDelegate
-(void)doSomethingInDelegate;
@end
@interface MyClass : NSObject
@property id<MyClassDelegate> delegate;
-(void)doSomething
@end
@implementation MyClass
-(void)doSomething
{
[self.delegate doSomethingInDelegate];
}
@end
@interface MyOtherClass<MyClassDelegate> : NSObject
...
@end
@implementation MyOtherClass
-(void)doSomethingInDelegate
{
NSLog(@"Doing something in delegate");
}
@end
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,如果您有非常少量的委托方法(理想情况下只有1),那么块可能是一个很好的替代方法.如果你有几个委托方法,那么块可能会变得很尴尬.
UITableView
在UITableViewDelegate
和之间有几十个委托方法UITableViewDataSource
.使用块配置它会很笨拙并且使代码重用非常困难.如果"作为委托"的特定方式可能是高度可重用的(如in UITableViewController
),那么委托是一种更强大的模式.
另一方面,如果你的代表最终只有一个"thisActionFinished:"方法,那么一个委托可能有点过分,最好只传递一个块.有很多情况这是真的,我们曾经有过需要创建大量的单方法委托协议,这有点痛苦.块使常见模式更容易.
但它并不是委托的通用替代品,而且块有许多与回调无关的其他目的.因此学习这两种技术很重要.
看你的具体例子,有几个错误.我们在委托和块表单中都这样做.
// Since the protocol needs to know about the class, you need to warn the
// compiler that this class exists.
@class MyClass;
// Declare the delegate protocol. Delegate method names should follow this
// pattern with "did", "should", or "will" in their names. Delegate methods
// should always pass the delegating object as the first parameter. A given
// delegate may be delegating for several instances.
@protocol MyClassDelegate
-(void)myClass:(MyClass *)class didSomething:(id)something;
@end
// Declare the class that has a delegate. Notice that `delegate` should be `weak`
// here. In your example, it's `strong`, and that will almost always lead to a
// retain loop. With rare exceptions, delegates are not retained.
@interface MyClass : NSObject
@property (nonatomic, readwrite, weak) id<MyClassDelegate> delegate;
-(void)doSomething;
@end
// Do the thing
@implementation MyClass
-(void)doSomething {
[self.delegate myClass:self didSomething:@"SOMETHING"];
}
@end
// The delegate object almost always has a strong pointer to the thing it delegates
// for. That's why you want the `delegate` property to be weak.
// Note that your syntax was wrong. "MyOtherClass <MyClassDelegate>". That's
// the new generic syntax, not the protocol syntax. Protocols go at the end.
@interface MyOtherClass : NSObject <MyClassDelegate>
@property (nonatomic, readwrite, strong) MyClass *c;
@end
// And the obvious impl
@implementation MyOtherClass
- (instancetype)init {
self = [super init];
if (self) {
self.c = [MyClass new];
self.c.delegate = self;
}
return self;
}
-(void)myClass:(MyClass *)class didSomething:(id)something {
NSLog(@"Doing something in delegate");
}
@end
Run Code Online (Sandbox Code Playgroud)
如果这是一个基于块的API,让我们做同样的事情.
// If your callback takes no arguments and returns nothing, then you can
// use dispatch_block_t here. But often you need parameters or return
// something, and for that you should usually make a typealias. Welcome to the
// spiral world of block syntax.
typedef void(^MyClassCallback)(id something);
// Instead of a delegate, we have a callback. We might have several. We might
// have a block that returns the row height. But if you're doing a lot of
// that, just use a delegate. Note that blocks should always be `copy`.
@interface MyClass : NSObject
@property (nonatomic, readwrite, copy) MyClassCallback callback;
-(void)doSomething;
@end
// And here's how you use the block. It's just like a function.
@implementation MyClass
-(void)doSomething {
if (self.callback != nil) {
self.callback(@"SOMETHING");
}
}
@end
// And the delegate.
@interface MyOtherClass : NSObject
@property (nonatomic, readwrite, strong) MyClass *c;
@end
@implementation MyOtherClass
- (instancetype)init {
self = [super init];
if (self) {
self.c = [MyClass new];
// And here's the syntax for creating the block.
self.c.callback = ^(id something) {
NSLog(@"Doing something in delegate");
};
}
return self;
}
@end
Run Code Online (Sandbox Code Playgroud)
请注意,我们在委托中不需要额外的方法来保存一行代码,我们不需要定义协议.这是转向轻量级授权块的重要原因.它使相关代码保持紧密.但是当代码变得复杂时,"在一起"变得疯狂,并且块不再是一个好的解决方案.回到代表们,这样做非常好.
归档时间: |
|
查看次数: |
1790 次 |
最近记录: |