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)
}
将来的你会感谢今天如此努力的你!
版权声明:本文为博主原创文章,未经博主允许不得转载。