Mac开发基础09-NSViewController(一)

NSViewController 简介

NSViewController 是 macOS 应用程序中的核心类,用于管理单个视图层次结构。它提供了对视图生命周期、布局管理和内容更新的控制,并与模型数据和其他控制器进行交互,提供了高效的视图控制和管理机制。

基础知识点

NSViewController 继承自 NSResponder,它主要用于以下几方面:

  1. 视图层次结构管理:管理视图及其子视图。
  2. 视图生命周期管理:管理视图的加载、显示、隐藏和销毁生命周期。
  3. 与数据模型交互:通过关联的模型数据来更新视图内容。
  4. 事件响应:处理用户交互事件。

常见 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 的生命周期方法对正确处理视图的呈现和销毁非常重要。

  1. init(nibName:bundle:):初始化视图控制器。通常用于从 NIB/XIB 文件中加载视图。
  2. loadView:视图控制器的主视图在第一次访问时会调用该方法。这是设置视图层次结构的好时机。
  3. viewDidLoad:视图层次结构已载入到内存时调用。适用于额外的初始化工作,比如设置控件的初始状态。
  4. viewWillAppear:视图即将加入视图层级时调用。适用于每次视图显示前需要进行的操作,比如更新数据。
  5. viewDidAppear:视图已经加入视图层级时调用。适用于视图已经显示后的操作,比如启动动画。
  6. viewWillDisappear:视图即将从视图层级移除时调用。适用于移除前需要进行的操作,例如停止动画或者解除绑定。
  7. 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 应用的视图层次结构,更好地实现复杂和模块化的用户界面。

posted @ 2024-08-06 14:57  Mr.陳  阅读(26)  评论(0编辑  收藏  举报