Delegate
Delegate
也是iOS
和Mac OSX
开发中最长使用的一种设计模式,其主要作用是将一个对象方法的实现,交给另外一个对象去实现。
Objective-C
定义一个protocol
// 定义一个协议
@protocol CYViewDelegate <NSObject>
- (void)changeContent:(NSString * _Nullable)content;
@end
// 类CYView持有这个delegate
@interface CYView : NSObject
@property (nonatomic, weak) id<CYViewDelegate> delegate;
@end
调用协议的地方
// 调用CYViewDelegate的方法
- (void)mouseDown:(NSEvent *)event {
NSString *content = @"Hello DUDU!";
// 注意这里的判断逻辑
if (self.delegate && [self.delegate respondsToSelector:@selector(changeContent:)]) {
[self.delegate changeContent:content];
}
}
实际执行该delegate方法的类
@interface AppDelegate () <CYViewDelegate>
@property (weak) IBOutlet NSWindow *window;
@property (weak) IBOutlet CYView *customView;
@property (weak) IBOutlet NSTextField *contentLabel;
@end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
self.customView.delegate = self;
}
// 实际执行delegate的地方
- (void)changeContent:(NSString *)content {
self.contentLabel.stringValue = content;
}
@end
Swift
这次主要来学习如何使用Swift中的delegate。
定义一个delegate
protocol CYViewDelegate: class {
func changeContent(_ content: String)
}
class CYView: NSView {
weak var delegate: CYViewDelegate?
override func mouseDown(with event: NSEvent) {
print("鼠标左键按下")
let content = "Hello, Kamal!"
delegate?.changeContent(content)
}
}
注意:
- 这里我们定义协议的时候,在
CYViewDelegate
后面加了class
的。这里是为了保证protocol
只能在类中使用(Swift
中struct
和enum
都可以)。也可以如下:// 1. @objc是表明当前代码是针对NSObject对象,也就是class对象,就可以正常使用weak了 // 2. 仅@objc标记的protocol可以使用@optional。 @objc protocol CYViewDelegate { @objc optional func changeContent(_ content: String) }
- 只有
delegate
是class
的时候,才需要加weak
修饰- 并且
weak
的引用是optional
的,所以必须使用var
修饰,并且可以为nil
delegate
是optional
的,那么不需要Objective-C
中的respondsToSelector
判断了
实现这个delegate
这里就和Objective-C中的写法差不多了。
class AppDelegate: NSObject, NSApplicationDelegate, CYViewDelegate {
@IBOutlet weak var postButton: NSButton!
@IBOutlet weak var customView: CYView!
@IBOutlet weak var contentLabel: NSTextField!
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
self.customView.delegate = self
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
// 实际执行delegate方法的地方
func changeContent(_ content: String) {
self.contentLabel.stringValue = content
}
}
总结
-
使用关键词
weak
是为了避免强引用导致的闭环。 -
当
delegate
是一个类时,使用weak
关键词。Swift
中的struct
和enums
是值对象类型,不是引用类型,所以它们不会引起强引用闭环
网友评论