Mac開發基礎09-NSViewController(一)
NSViewController 簡介
NSViewController 是 macOS 應用程序中的核心類,用于管理單個視圖層次結構。它提供了對視圖生命周期、布局管理和內容更新的控制,并與模型數據和其他控制器進行交互,提供了高效的視圖控制和管理機制。
基礎知識點
NSViewController 繼承自 NSResponder,它主要用于以下幾方面:
- 視圖層次結構管理:管理視圖及其子視圖。
- 視圖生命周期管理:管理視圖的加載、顯示、隱藏和銷毀生命周期。
- 與數據模型交互:通過關聯的模型數據來更新視圖內容。
- 事件響應:處理用戶交互事件。
常見 API 和方法
初始化與視圖管理
初始化視圖控制器
Objective-C
- (instancetype)initWithNibName:(NSNibName)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
Swift
init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?)
加載視圖
會在視圖第一次訪問時調用,通常在這里執行一些視圖初始化工作。
Objective-C
- (void)loadView {
self.view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 200, 200)];
}
Swift
override func loadView() {
self.view = NSView(frame: NSRect(x: 0, y: 0, width: 200, height: 200))
}
視圖生命周期
視圖即將出現
Objective-C
- (void)viewWillAppear;
Swift
override func viewWillAppear() {
super.viewWillAppear()
}
視圖已經出現
Objective-C
- (void)viewDidAppear;
Swift
override func viewDidAppear() {
super.viewDidAppear()
}
視圖即將消失
Objective-C
- (void)viewWillDisappear;
Swift
override func viewWillDisappear() {
super.viewWillDisappear()
}
視圖已經消失
Objective-C
- (void)viewDidDisappear;
Swift
override func viewDidDisappear() {
super.viewDidDisappear()
}
子視圖管理
添加子視圖控制器
Objective-C
- (void)addChildViewController:(NSViewController *)childViewController;
Swift
func addChild(_ childViewController: NSViewController)
移除子視圖控制器
Objective-C
- (void)removeFromParentViewController;
Swift
func removeFromParent()
切換子視圖控制器
Objective-C
- (void)transitionFromViewController:(NSViewController *)fromViewController
toViewController:(NSViewController *)toViewController
options:(NSViewControllerTransitionOptions)options
completionHandler:(void (^)(void))completion;
Swift
func transition(from fromViewController: NSViewController, to toViewController: NSViewController, options: NSViewController.TransitionOptions = [], completionHandler completion: (() -> Void)? = nil)
數據綁定和更新
綁定模型數據
可以使用 @IBOutlet 和 @IBAction 將視圖控件連接到代碼中。
Objective-C
@interface MyViewController : NSViewController
@property (weak) IBOutlet NSTextField *textField;
@end
@implementation MyViewController
- (IBAction)buttonClicked:(id)sender {
self.textField.stringValue = @"Button clicked!";
}
@end
Swift
class MyViewController: NSViewController {
@IBOutlet weak var textField: NSTextField!
@IBAction func buttonClicked(_ sender: Any) {
textField.stringValue = "Button clicked!"
}
}
自定義布局和自動布局
手動布局視圖
Objective-C
- (void)viewDidLayout {
[super viewDidLayout];
self.view.subviews[0].frame = NSMakeRect(10, 10, 100, 100);
}
Swift
override func viewDidLayout() {
super.viewDidLayout()
self.view.subviews[0].frame = NSMakeRect(10, 10, 100, 100)
}
使用自動布局
Objective-C
- (void)viewDidLoad {
[super viewDidLoad];
NSView *subview = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
[subview setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:subview];
[self.view addConstraints:@[
[subview.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:10],
[subview.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-10],
[subview.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:10],
[subview.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor constant:-10]
]];
}
Swift
override func viewDidLoad() {
super.viewDidLoad()
let subview = NSView(frame: NSRect(x: 0, y: 0, width: 100, height: 100))
subview.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(subview)
NSLayoutConstraint.activate([
subview.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 10),
subview.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -10),
subview.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 10),
subview.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -10)
])
}
視圖交互和事件響應
響應用戶事件
可以為視圖添加手勢識別器或繼承 NSView 的事件方法。
Objective-C
- (void)viewDidLoad {
[super viewDidLoad];
NSClickGestureRecognizer *clickRecognizer = [[NSClickGestureRecognizer alloc] initWithTarget:self action:@selector(handleClick:)];
[self.view addGestureRecognizer:clickRecognizer];
}
- (void)handleClick:(NSGestureRecognizer *)gestureRecognizer {
NSLog(@"View clicked!");
}
Swift
override func viewDidLoad() {
super.viewDidLoad()
let clickRecognizer = NSClickGestureRecognizer(target: self, action: #selector(handleClick(_:)))
self.view.addGestureRecognizer(clickRecognizer)
}
@objc func handleClick(_ gestureRecognizer: NSGestureRecognizer) {
print("View clicked!")
}
深入探討
視圖控制器生命周期
理解 NSViewController 的生命周期方法對正確處理視圖的呈現和銷毀非常重要。
init(nibName:bundle:):初始化視圖控制器。通常用于從 NIB/XIB 文件中加載視圖。loadView:視圖控制器的主視圖在第一次訪問時會調用該方法。這是設置視圖層次結構的好時機。viewDidLoad:視圖層次結構已載入到內存時調用。適用于額外的初始化工作,比如設置控件的初始狀態。viewWillAppear:視圖即將加入視圖層級時調用。適用于每次視圖顯示前需要進行的操作,比如更新數據。viewDidAppear:視圖已經加入視圖層級時調用。適用于視圖已經顯示后的操作,比如啟動動畫。viewWillDisappear:視圖即將從視圖層級移除時調用。適用于移除前需要進行的操作,例如停止動畫或者解除綁定。viewDidDisappear:視圖已經從視圖層級移除時調用。適用于視圖已經消失后的操作,比如保存數據。
動態加載和卸載視圖
在內存有限或者視圖控件復雜的情況下,可以考慮動態加載和卸載部分視圖。
Objective-C
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
if (self.isViewLoaded && !self.view.window) {
self.view = nil;
}
}
Swift
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
if self.isViewLoaded && self.view.window == nil {
self.view = nil
}
}
模塊化開發和復用性
NSViewController 可以用于構建模塊化的 UI 組件,使得各個部分可以獨立開發和測試,然后再組合成完整的界面。
Objective-C
@interface CustomViewController : NSViewController
@end
@implementation CustomViewController
- (instancetype)init {
if (self = [super initWithNibName:nil bundle:nil]) {
}
return self;
}
- (void)loadView {
// 模塊化視圖初始化
self.view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 200, 200)];
// 添加更多子視圖或控件
}
@end
Swift
class CustomViewController: NSViewController {
override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
// 初始化代碼
}
required init?(coder: NSCoder) {
super.init(coder: coder)
// 初始化代碼
}
override func loadView() {
// 模塊化視圖初始化
self.view = NSView(frame: NSRect(x: 0, y: 0, width: 200, height: 200))
// 添加更多子視圖或控件
}
}
通過掌握 NSViewController 的這些常見 API 和基礎技巧,了解其視圖生命周期和使用場景,能夠靈活高效地管理 macOS 應用的視圖層次結構,更好地實現復雜和模塊化的用戶界面。
將來的你會感謝今天如此努力的你!
版權聲明:本文為博主原創文章,未經博主允許不得轉載。

浙公網安備 33010602011771號