Mac开发基础10-NSViewController(二)

1. View-Based UI Updates

NSViewController 提供了很多优化 UI 更新的方法。利用这些方法,你可以更有效地管理复杂视图的改变。

viewWillLayout

该方法在控制器的视图层次结构布局之前调用,可以在此方法中修改子视图的布局。

Objective-C
- (void)viewWillLayout {
    [super viewWillLayout];
    // 执行布局前需要的操作
    NSLog(@"View will layout");
}
Swift
override func viewWillLayout() {
    super.viewWillLayout()
    // 执行布局前需要的操作
    print("View will layout")
}

updateViewConstraints

通过重写这个方法可以动态更新约束。

Objective-C
- (void)updateViewConstraints {
    [super updateViewConstraints];
    // 更新视图的约束
    NSLog(@"Updating view constraints");
}
Swift
override func updateViewConstraints() {
    super.updateViewConstraints()
    // 更新视图的约束
    print("Updating view constraints")
}

2. 错误状态显示

NSViewController 可以利用自己的状态显示错误信息,比如网络请求错误或数据解析错误。

使用 presentError

Objective-C
- (void)someMethodThatMayFail {
    NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain code:101 userInfo:@{NSLocalizedDescriptionKey: @"Something went wrong"}];
    [self presentError:error];
}
Swift
func someMethodThatMayFail() {
    let error = NSError(domain: NSCocoaErrorDomain, code: 101, userInfo: [NSLocalizedDescriptionKey: "Something went wrong"])
    self.presentError(error)
}

3. 自定义 storyboardIdentifier

在 Storyboard 中为视图控制器定义唯一标识符,然后在代码中动态加载。

设置和使用 storyboardIdentifier

Objective-C
NSViewController *vc = [self.storyboard instantiateControllerWithIdentifier:@"MyViewController"];
Swift
let vc = self.storyboard?.instantiateController(withIdentifier: "MyViewController") as! NSViewController

4. 深入理解 prepare(for:sender:) 方法

NSViewController 中,prepare(for:sender:) 方法一般用来在界面转场之前传递数据或者设定状态。

Objective-C

- (void)prepareForSegue:(NSStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"mySegue"]) {
        MyDestinationViewController *destinationVC = segue.destinationController;
        destinationVC.data = self.dataToSend;
    }
}

Swift

override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
    if segue.identifier == "mySegue" {
        let destinationVC = segue.destinationController as! MyDestinationViewController
        destinationVC.data = self.dataToSend
    }
}

5. Restoration 恢复视图控制器状态

NSViewController 支持状态恢复机制,使得应用退出后再启动时可以恢复到之前的状态。

启用状态恢复

Objective-C
- (void)viewDidLoad {
    [super viewDidLoad];
    self.restorationIdentifier = NSStringFromClass([self class]);
}

- (void)encodeRestorableStateWithCoder:(NSCoder *)coder {
    [super encodeRestorableStateWithCoder:coder];
    // 保存需要恢复的状态
    [coder encodeObject:self.someState forKey:@"someState"];
}

- (void)restoreStateWithCoder:(NSCoder *)coder {
    [super restoreStateWithCoder:coder];
    // 恢复之前保存的状态
    self.someState = [coder decodeObjectForKey:@"someState"];
}
Swift
override func viewDidLoad() {
    super.viewDidLoad()
    self.restorationIdentifier = String(describing: type(of: self))
}

override func encodeRestorableState(with coder: NSCoder) {
    super.encodeRestorableState(with: coder)
    // 保存需要恢复的状态
    coder.encode(self.someState, forKey: "someState")
}

override func restoreState(with coder: NSCoder) {
    super.restoreState(with: coder)
    // 恢复之前保存的状态
    self.someState = coder.decodeObject(forKey: "someState") as? SomeType
}

6. 自定义转场动画

通过 NSViewControllerTransitionOptions,可以在切换视图时自定义动画效果。

自定义动画

Objective-C
- (void)switchToViewController:(NSViewController *)toViewController {
    NSViewController *fromViewController = self.childViewControllers.firstObject;
    [self addChildViewController:toViewController];
    [self transitionFromViewController:fromViewController toViewController:toViewController options:NSViewControllerTransitionSlideLeft completionHandler:^{
        [fromViewController removeFromParentViewController];
    }];
}
Swift
func switchToViewController(_ toViewController: NSViewController) {
    let fromViewController = self.children.first!
    self.addChild(toViewController)
    self.transition(from: fromViewController, to: toViewController, options: .slideLeft, completionHandler: {
        fromViewController.removeFromParent()
    })
}

7. 视图层级捕捉和截图

需要时可以捕捉视图内容并保存为图片,用于调试或临时保存视图状态。

捕捉视图

Objective-C
- (NSImage *)captureView:(NSView *)view {
    NSRect rect = view.bounds;
    NSBitmapImageRep *rep = [view bitmapImageRepForCachingDisplayInRect:rect];
    [view cacheDisplayInRect:rect toBitmapImageRep:rep];
    return [[NSImage alloc] initWithCGImage:[rep CGImage] size:rect.size];
}
Swift
func captureView(_ view: NSView) -> NSImage {
    let rect = view.bounds
    let rep = view.bitmapImageRepForCachingDisplay(in: rect)!
    view.cacheDisplay(in: rect, to: rep)
    return NSImage(cgImage: rep.cgImage!, size: rect.size)
}

8. 处理视图的层级和顺序

使用 subviews 属性可以操作视图的层级和顺序。

Objective-C
- (void)bringSubviewToFront:(NSView *)view {
    [view.superview addSubview:view positioned:NSWindowAbove relativeTo:nil];
}
Swift
func bringSubviewToFront(_ view: NSView) {
    view.superview?.addSubview(view, positioned: .above, relativeTo: nil)
}

posted @ 2024-08-06 15:04  Mr.陳  阅读(10)  评论(0编辑  收藏  举报