摘要:
使用Cocoa的内置用户界面保存机制保存/恢复NSSearchField
我的状态的正确方法是什么NSViewController
?
细节:
我正在开发我的第一个macOS应用程序,我的用户界面状态恢复有点麻烦.到目前为止,我已经将它工作到了我的子类中调用encodeRestorableState(with:)
和restoreState(with:)
方法的地步NSViewController
.
我有一个NSSearchField
在我的视图控制器中,我想保存/恢复搜索字段的状态,包括其文本,任何选择,光标位置,以及它当前是否处于焦点.
如果我使用以下代码,则正确保存和恢复文本:
override func encodeRestorableState(with coder: NSCoder) {
super.encodeRestorableState(with: coder)
coder.encode(searchField.stringValue, forKey: "searchText")
}
override func restoreState(with coder: NSCoder) {
super.restoreState(with: coder)
if let searchText = coder.decodeObject(forKey: "searchText") as? String {
searchField.stringValue = searchText
}
}
Run Code Online (Sandbox Code Playgroud)
显然我可以添加更多代码来保存/恢复搜索字段的选择和光标位置等.
我真正的问题是,是否有更好,更正确,更自动的方式来保存和恢复搜索字段的状态?或者我是否需要为我希望保存的搜索字段的每个属性编写自己的代码?
我试过用:
searchField.encodeRestorableState(with: coder)
Run Code Online (Sandbox Code Playgroud)
和:
searchField.restoreState(with: coder)
Run Code Online (Sandbox Code Playgroud)
在上述两种方法中,但在我的应用重新启动时,搜索字段中没有出现任何内容.
我还实施了:
override class func restorableStateKeyPaths() -> [String] {
var keys = super.restorableStateKeyPaths()
keys.append("searchField.stringValue")
return keys
}
Run Code Online (Sandbox Code Playgroud)
这里"searchField"
是名 …
我正在尝试将iOS 6 State Restoration添加到我刚刚完成的应用程序中.这是一个应用程序,其中的模型主要来自CoreData.
按照建议,我使用"传递接力棒"方法在视图控制器之间移动托管对象上下文 - 我在我的App Delegate中创建MOC,将其传递给第一个View Controller,后者将其传递给prepareForSegue:中的第二个,它将它传递给prepareForSegue:中的第三个,等等.
这似乎与国家恢复没有太大关系.我唯一能想到的就是直接在我的App Delegate中从viewControllerWithRestorationIdentifierPath:coder:的实现中检索MOC.实际上,看起来Apple开发人员在观看WWDC会话时做了类似的事情.
这是最好/唯一的方式吗?状态恢复是否有效地打破了Pass-The-Baton,至少对于恢复的视图控制器?
我一直在四处寻找状态恢复.在下面的代码中,UITableViewController的滚动位置被恢复,但是,如果我要进入详细视图(将MyViewController的实例推入导航堆栈),当应用程序重新启动时,它总是返回到第一个视图导航堆栈中的控制器(即MyTableViewController).有人能帮我恢复到正确的视图控制器(即MyOtherViewController)吗?
AppDelegate.m
- (BOOL)launchWithOptions:(NSDictionary *)launchOptions
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
MyTableViewController *table = [[MyTableViewController alloc] initWithStyle:UITableViewStylePlain];
table.depth = 0;
UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:table];
navCon.restorationIdentifier = @"navigationController";
self.window.rootViewController = navCon;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
});
return YES;
}
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return [self launchWithOptions:launchOptions];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return [self launchWithOptions:launchOptions];
}
Run Code Online (Sandbox Code Playgroud)
MyTableViewController.m
- (id)initWithStyle:(UITableViewStyle)style …
Run Code Online (Sandbox Code Playgroud) 我正在存储我的应用程序屏幕,以便在应用程序打开时它将显示已存储的屏幕.该应用程序是基于导航的.
我已将Restoration Ids分配给主故事板中的两个视图控制器.第一个控制器是导航控制器的根视图控制器.我还为导航控制器分配了Restoration Id.现在问题是当我运行应用程序时,我收到以下警告:
无法创建正在进行的恢复标记文件.
不确定还需要做什么.
我在iOS项目中收到此警告:(iOS7,XCode 5 GM)
警告:无法创建正在进行的恢复标记文件
我正在研究一个viewcontroller,当我在启动时收到此警告时,它会变为全黑.删除应用程序并重新启动XCode有时似乎有所帮助.我两个都没有回来
-(BOOL)application:(UIApplication *)application shouldRestoreApplicationState:
-(BOOL)application:(UIApplication *)application shouldSaveApplicationState:
Run Code Online (Sandbox Code Playgroud)
Update1:我在iPhone4s上测试过.结果相同.我的视图控制器上的警告和黑屏.
Update2:回答了我自己的黑屏问题.该警告在最新的iOS 7.0.x版本中消失了.
即使它没有运行,我也试图让核心蓝牙唤醒应用程序.
正如Apple所说,"因为状态保存和恢复是内置于Core Bluetooth,您的应用程序可以选择使用此功能来要求系统保留应用程序的中央和外围管理器的状态,并继续执行某些与蓝牙相关的任务.代表他们,即使你的应用程序不再运行.当其中一个任务完成后,系统会将你的应用程序重新启动到后台,并让你的应用程序有机会恢复其状态并适当地处理事件."
我添加了以下代码以选择加入此功能:
myCentralManager =
[[CBCentralManager alloc] initWithDelegate:self queue:nil
options:@{ CBCentralManagerOptionRestoreIdentifierKey:
@"myCentralManagerIdentifier" }];
Run Code Online (Sandbox Code Playgroud)
但应用程序醒来时的回调从未被触发.
-(BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
}
-(void)centralManager:(CBCentralManager *)central
willRestoreState:(NSDictionary *)state {
}
Run Code Online (Sandbox Code Playgroud)
这两个从未被称为.
我正在测试这个唤醒功能的方式:
我在info.plist中的后台模式中添加了"bluetooth central",因此BLE在后台运行.
在我的iphone No.1中启动centralManager.开始扫描.
按下主页然后退出,玩一些内存沉重的游戏,在调试日志中我会看到:"因内存压力而终止.进程已完成退出代码0".这是为了模拟ios系统如何因内存压力而终止后台应用程序.
与另一部iphone No.2开始一个灯塔并开始广播.
结果:那些重新启动的回调永远不会被调用.
任何想法为什么这不起作用?如果这是一个API问题,当你的手机接近BLE信标时,还有其他方法可以将你的应用重新启动到BLE的后台吗?我已经尝试使用ibeacon唤醒应用程序,但核心蓝牙中央管理器将不允许您在后台连接到ibeacon.
谢谢!
ios core-bluetooth bluetooth-lowenergy cbcentralmanager state-restoration
这有点长,但并不琐碎,需要花很多时间来证明这个问题。
我试图弄清楚如何将一个小示例应用程序从iOS 12更新到iOS13。该示例应用程序不使用任何故事板(除了启动屏幕)。这是一个简单的应用程序,显示了一个带有由计时器更新的标签的视图控制器。它使用状态恢复,因此计数器从中断处开始。我希望能够支持iOS 12和iOS13。在iOS 13中,我想更新到新的场景架构。
在iOS 12下,该应用程序可以正常运行。在全新安装中,计数器从0开始并上升。将应用程序置于后台,然后重新启动应用程序,然后计数器从停止处继续计数。状态恢复全部正常。
现在,我正在尝试使用场景在iOS 13下运行该功能。我遇到的问题是找出初始化场景窗口并将导航控制器和主视图控制器还原到场景的正确方法。
我已经阅读了尽可能多的Apple文档,这些文档与状态恢复和场景有关。我看过与窗口和场景相关的WWDC视频(212-在iPad上引入多个Windows,258-为多个Windows架构应用)。但我似乎缺少将所有内容组合在一起的作品。
当我在iOS 13下运行该应用程序时,所有预期的委托方法(AppDelegate和SceneDelegate)都被调用。状态恢复正在恢复导航控制器和主视图控制器,但rootViewController
由于所有UI状态恢复都在AppDelegate中,因此我不知道如何设置场景窗口的状态。
似乎也有一些与NSUserTask
应该使用的相关的东西,但我无法说明问题。
缺少的部分似乎是在willConnectTo
方法中SceneDelegate
。我敢肯定,我还需要一些变化stateRestorationActivity
的SceneDelegate
。中可能还需要进行更改AppDelegate
。我怀疑其中的任何内容都ViewController
需要更改。
要复制我的工作,请使用Single View App模板使用Xcode 11(当前为Beta 4)创建一个新的iOS项目。将部署目标设置为iOS 11或12。
删除主故事板。在Info.plist中删除对Main的两个引用(一个位于顶层,另一个位于Application Scene Manifest的深处。按如下所示更新3个swift文件。
AppDelegate.swift:
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
print("AppDelegate willFinishLaunchingWithOptions")
// This probably shouldn't be run under iOS 13? …
Run Code Online (Sandbox Code Playgroud) 我正在努力在我的应用程序中实现状态恢复,但是我遇到了一个问题.我最近在桌面视图中添加了3D Touch支持,并且每次都完美地工作,除非我已经添加了状态恢复.当应用程序恢复表格视图时,向单元格施加压力不会产生任何效果,就好像表格视图尚未注册进行预览一样.
我有这个代码viewDidLoad
:
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 9.0, *) {
if traitCollection.forceTouchCapability == UIForceTouchCapability.Available {
registerForPreviewingWithDelegate(self, sourceView: view)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我试着将它移动viewDidAppear
到看它是否会有所帮助,但它并没有什么不同.
有任何想法吗?
我已经在iOS应用程序中集成了MMDrawerController库,现在我需要恢复应用程序状态,即使应用程序在后台被杀死(仅当应用程序从前台输入到后台时),它在正常的导航应用程序中工作正常但是当我在我的应用程序中使用" setCenterViewController "选项更改导航,恢复无法按预期工作,并且我已按照此链接中提供的所有说明操作:" https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/PreservingandRestoringState.html "
我已经使用了setCenterViewController选项(推荐来自MMDrawer)导航到特定的屏幕,然后在后台删除应用程序,当我们重新打开它时会启动默认的初始屏幕,但我们期望它应该在进入背景之前重新打开屏幕.
这是代码片段:
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
appDelegate.homeController.navigationController.navigationBarHidden = YES;
HomeViewController *homeVC = [[HomeViewController alloc] initWithNibName:@"HomeViewController" bundle:nil];
UINavigationController *_navg = [[UINavigationController alloc]initWithRootViewController:homeVC];
_navg.restorationIdentifier = @"homeNavigationController";
homeVC.title = [self.dataSource objectAtIndex:indexPath.row]; homeVC.restorationIdentifier = @"HomeViewController";
[appDelegate.drawerController setCenterViewController:_navg withCloseAnimation:YES completion:nil];
self.currentViewController = _navg;
self.currentViewController.restorationIdentifier = @"homeNavigationController";
Run Code Online (Sandbox Code Playgroud)
帮我解决这个问题.
我想在我的应用程序中进行状态恢复,不使用故事板.我看到我的主要应用程序ViewController在状态恢复期间实例化了两次 - 你如何确保它只创建一次?
就我了解的流动,application:willFinishLaunchingWithOptions
并且pplication:didFinishLaunchingWithOptions
将使用commonInit
这将设置应用程序的UIWindow方法及其RootViewController的.在我的例子中,rootViewController是一个UINavigationController,其中一个名为"MyMainViewController"的类充当UINavigation的rootViewController.
除此之外,我也分别处理willEncodeRestorableStateWithCoder
和处理didDecodeRestorableStateWithCoder
.但似乎到了我的时候didDecodeRestorableStateWithCoder
,我看到MyMainViewController创建了两个独立的实例.
确保在恢复期间只创建一个UIViewController的方法是什么?
恢复期间的呼叫顺序:
这是我在AppDelegate中所做的事情:
NSString * const kRootViewControllerKey = @"RootViewControllerKey";
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self commonInitWithOptions:launchOptions];
return YES;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self commonInitWithOptions:launchOptions];
return YES;
}
- (void)commonInitWithOptions:(NSDictionary *)launchOptions {
static dispatch_once_t predicate;
dispatch_once(&predicate, ^ {
// While this will be called only once during the lifetype of the app, when the process is killed …
Run Code Online (Sandbox Code Playgroud) ios ×9
ios6 ×2
swift ×2
3dtouch ×1
core-data ×1
ios13 ×1
ios7 ×1
iphone ×1
macos ×1
nstextfield ×1
objective-c ×1
uiscene ×1
uitableview ×1
xcode ×1