标签: uikit-state-preservation

iOS状态保存和容器视图

我在故事板中有一个使用容器视图的视图控制器.两者都具有恢复标识符集.父母正在被保存并恢复正常.然而,孩子不是.在子视图控制器上都没有-encodeRestorableStateWithCoder:-decodeRestorableStateWithCoder:正在被调用.

保存使用视图容器创建的子视图控制器的正确方法是什么?我可以将子视图控制器保存在父节点中-encodeRestorableStateWithCoder:,这将导致它被保存,但我没有办法在恢复期间使用它.

iphone ios uikit-state-preservation

19
推荐指数
2
解决办法
4873
查看次数

iOS 6 - 状态保存和恢复

我已经实现了用于状态保存的iOS 6 API,它可以工作 - 在我退出应用程序并重新启动几毫秒后,恢复的视图控制器会进入,但随后它被我在启动时显示的主视图控制器所取代.

每次应用程序启动主窗口的根视图时我都会设置,所以这一定是问题所在.

这是我的代码:

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [self commonInitializationLaunching:launchOptions];
    return YES;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [self commonInitializationLaunching:launchOptions];
    return YES;
}

- (void)commonInitializationLaunching:(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.
        static NSString *const kKeychainItemName = @"OAuthGoogleReader";
        self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
        self.navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];

        GTMOAuth2Authentication *auth;
        auth = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName
                                                                     clientID:kClientID
                                                                 clientSecret:kClientSecret];

        self.window.rootViewController = …
Run Code Online (Sandbox Code Playgroud)

iphone xcode cocoa-touch ios6 uikit-state-preservation

11
推荐指数
2
解决办法
7641
查看次数

viewControllerWithRestorationIdentifierPath:coder:如何查找现有实例?

文档viewControllerWithRestorationIdentifierPath:coder:说:

您对此方法的实现应创建(或查找)相应的视图控制器对象并将其返回...并不总是需要在此方法的实现中创建新的视图控制器对象.您还可以返回由其他方法创建的现有视图控制器对象.例如,如果已从故事板文件加载视图控制器,则将返回该对象而不是创建新对象.[我的斜体.]

这对我来说似乎完全是胡说八道.这是一种类方法!我们目前没有任何访问任何实例的权限 - 除非我们创建一个实例.如果有人可以向我解释一个类方法如何找到或知道"已经从故事板文件中加载的视图控制器",我将不胜感激.

编辑:为了获得赏金,您必须向我展示一个实际案例,从您自己的应用程序中,viewControllerWithRestorationIdentifierPath:coder:用于"返回通过其他方式创建的现有视图控制器对象" 的类方法.

ios uikit-state-preservation

10
推荐指数
1
解决办法
1567
查看次数

我们在WWDC 2012 Session 208中如何找到"Restrospector"工具?

WWDC 2012会议208是关于UIKit状态保存和恢复.最后,提到了调试工具"Restrospector".它应该可视化磁盘上的持久状态.

状态本身持久保存到"已保存的应用程序状态"目录中的"data.data"文件.当你打开它时,它是一个XML文件,但它的一部分不是人类可读的.

我确实在Apple开发者论坛和开发者网站上搜索过,但也只有人要求使用这个工具,但是没有人有答案.也许Stack Overflow可以提供帮助吗?

objective-c ios uikit-state-preservation

9
推荐指数
1
解决办法
607
查看次数

UIKit状态保存不恢复滚动偏移

我有一个在iOS 6中使用UIKit状态保存的应用程序.我能够保存/恢复视图控制器的状态,即选择了哪个选项卡和导航控制器层次结构,但是我无法获取我的表视图来恢复它的偏移量.我的故事板中有一个用于视图的恢复标识符,以及视图控制器和视图控制器(表的数据源)实现UIDataSourceModelAssociation如下:

- (NSString *)modelIdentifierForElementAtIndexPath:(NSIndexPath *)indexPath inView:(UIView *)view
{
    TSStatus *status = [self._fetchedResultsController objectAtIndexPath:indexPath];

    return status.objectID.URIRepresentation.absoluteString;
}

- (NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view
{
    NSURL *statusURL = [NSURL URLWithString:identifier];
    NSManagedObjectID *statusID = [[TSDataController sharedController].persistentStoreCoordinator managedObjectIDForURIRepresentation:statusURL];
    TSStatus *status = (TSStatus *)[[TSDataController sharedController].mainContext objectWithID:statusID];

    return [__fetchedResultsController indexPathForObject:status];
}
Run Code Online (Sandbox Code Playgroud)

modelIdentifierForElementAtIndexPath:inView:应用程序进入后台时modelIdentifierForElementAtIndexPath:inView:会被调用,但永远不会被调用.

iphone uikit ios ios6 uikit-state-preservation

8
推荐指数
1
解决办法
1771
查看次数

标签栏和导航控制器应用程序中的状态恢复

目标:我正在尝试在基于选项卡控制器的应用程序上恢复状态(每个选项卡上都有导航控制器).

问题:重新启动时,所选选项卡似乎按预期还原,但所选选项卡内的导航层次结构不是.

发展:

  1. 我首先开始使用项目模板"基于标签的app".
  2. 接下来,我将恢复ID添加到子视图控制器和标签栏控制器.
  3. 在app委托中,我实现了application(_:shouldSaveApplicationState:)application(_:shouldRestoreApplicationState:).

然后我运行应用程序,切换到第二个(右)选项卡,点击主页,终止.重新启动,显示右侧选项卡(如预期).到现在为止还挺好.

  1. 接下来,我转到故事板并将两个子视图控制器嵌入相应的导航控制器中,并为这些控制器分配恢复ID.

我运行应用程序,恢复仍然有效.还好.

  1. 接下来,我添加一个"细节"视图控制器; 它的类是UIViewController故事板的自定义子类,具有配置调试标签内容及其视图背景颜色的属性.

  2. 我在每个选项卡的顶视图控制器上放置了一个"显示详细信息..."按钮,并从每个选项卡创建一个segue到(共享)详细视图控制器中.所以现在我的故事板看起来像一个六边形(同样,两个segues都有在Interface Builder中设置的标识符).因此,左右顶视图控制器共享相同类型的"细节"视图控制器.在展示中,它被配置为区别于它被推动的位置(参见下一点).

  3. 在每个顶视图控制器的prepareForSegue(_:sender:)方法中,我以不同的方式配置推送的细节视图控制器:不同的文本和背景颜色(分别为"左"和"蓝","右"和红色).

  4. 我将代码添加到详细视图控制器以保存和恢复文本和背景颜色属性的状态:encodeRestorableStateWithCoder(_:)decodeRestorableStateWithCoder(_:).此外,我实现了viewDidLoad()以便在视图中反映这些属性的值.每当它被实例化并通过segue推入导航时,首先设置属性然后用于配置视图viewDidLoad().无论何时在恢复期间实例化,都会设置属性decodeRestorableStateWithCoder(_:)并类似地使用viewDidLoad().

...但是当我运行此代码时,最后选择的选项卡将被恢复,但仅限于顶视图控制器 - 左侧或右侧 - 而不是详细信息.有趣的是,最后设置为细节视图控制器的背景颜色瞬间闪烁.

我放置断点中encodeRestorableStateWithCoder(_:)decodeRestorableStateWithCoder(_:),但只有其中第被执行(编码).

  1. 想知道可能会遗漏什么,我继续实施了app委托application(_:viewControllerWithRestorationIdentifierPath:coder:)(总是返回nil,但是记录了传递的路径组件).

关于是否需要这种方法的文档不是很清楚,并且在任何情况下,除了细节之外的所有视图控制器似乎都可以完美地恢复,即使没有它.我添加了代码,根据最后一个路径组件(即该控制器的恢复ID)实例化每个视图控制器并返回它.

现在,它decodeRestorableStateWithCoder(_:) 调用,但导航仍然会在瞬间返回到选项卡的顶视图控制器.

那么发生了什么?在Tab栏+导航控制器应用程序中实现状态保存和恢复我缺少什么?

ios uistoryboard uikit-state-preservation ios9

8
推荐指数
1
解决办法
914
查看次数

iOS 6状态保存和恢复的自动化测试

我正在更新一个应用程序,以便在iOS 6中使用新的状态保存和恢复功能.据我所知,在应用程序中测试此功能的最佳指导包括手动执行(例如http://www.absoluteripple.com/1 /post/2012/09/ios-6-state-preservation-and-restoration.html).

有没有办法自动测试保存和恢复状态?

testing ios uikit-state-preservation

7
推荐指数
1
解决办法
467
查看次数

为什么我不能在NSKeyedArchiver中编码NSValue?

我试图对一个MKMapView中心进行编码并跨越一个NSKeyedArchiver状态保存.我找到了几个方便的新MapKit NSValue添加,valueWithMKCoordinate:valueWithMKCoordinate:.尝试将这些编码到密钥存档器中失败:

- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
    NSValue *mapCenterValue = [NSValue valueWithMKCoordinate:mapView.centerCoordinate];
    NSValue *mapSpanValue = [NSValue valueWithMKCoordinateSpan:mapView.region.span];
    [coder encodeObject:mapCenterValue forKey:kMapCenter];
    [coder encodeObject:mapSpanValue forKey:kMapSpan];
}
Run Code Online (Sandbox Code Playgroud)

由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:' - [NSKeyedArchiver encodeValueOfObjCType:at:]:此归档程序无法对结构进行编码

我知道这个问题的解决方案是将单个双打编码为四个单独的密钥.

我的问题是为什么会发生这种情况.一个NSValue是一个对象,为什么它告诉我"这个归档器不能编码结构"

cocoa objective-c mapkit nsvalue uikit-state-preservation

7
推荐指数
1
解决办法
2674
查看次数

UICollectionView状态恢复:自定义滚动位置

我试图找到处理UICollectionView状态恢复的最佳方法,其元素可能会移动.我的目标是确保在重新启动应用程序时,集合视图中最后查看的项目仍然可见,即使项目已移动.例如,当应用程序被杀死时,项目A位于索引3的单元格中,当应用程序重新启动时,如果模型说项目A应该显示在索引4处,我希望集合视图初始化到索引4处的单元格的偏移量.

我认为UIDataSourceModelAssociation在我的UICollectionViewDataSource课程中实现协议会为我解决这个问题,因为文档说明:

[UITableView和UICollectionView]类使用此协议的方法来确保将相同的数据对象(而不仅仅是相同的行索引)滚动到视图中并进行选择.

但是,我观察到的是,实现此协议确实会在恢复期间正确影响所选单元格的indexPath (这对我的应用程序并不重要),但它不会影响滚动位置.滚动位置(集合视图的contentOffset)始终恢复到应用程序被杀死时的位置,并且不受UICollectionViewDataSource的影响.

我有一个看起来像这样的解决方法.它与模型关联协议的模式基本相同,但我必须手动完成:

override func encodeRestorableStateWithCoder(coder: NSCoder) {
    let identifier = determineIdOfCurrentlyVisibleCell()
    coder.encodeObject(identifier, forKey: "visibleCellIdentifier")
}

override func decodeRestorableStateWithCoder(coder: NSCoder) {
    if let identifier = coder.decodeObjectForKey("visibleCellIdentifier") as? String {
        if let indexPath = model.indexPathForIdentifier(identifier) {
            collectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: .CenteredVertically, animated: false)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我是否误解了UIDataSourceModelAssociation的用法?有bug吗?是否有一种更优雅或正确的方式让它发挥作用?

ios uicollectionview uikit-state-preservation state-restoration swift

6
推荐指数
1
解决办法
1450
查看次数

为什么我的 iOS 应用程序在返回前台模式后从第一个屏幕重新启动?

当在详细信息屏幕中的我的 iOS 应用程序中时,我按下主页按钮,这将导致它进入后台模式。在大约 7 分钟不活动后,我重新启动它,它不会从我离开它的地方开始。它从第一个屏幕开始。

我上网,开始了解国家保护和恢复。我在一个屏幕中实现,但它似乎不起作用。这就是我在 appDelegate.m 中所做的

    //appDelegate.m

    -(BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder
    {
        return YES;
    }

    -(BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder
    {
        return YES;
    }
Run Code Online (Sandbox Code Playgroud)

以下代码位于 appDelegate.m 中的 willFinishLaunchingWithOptions 方法中。我没有使用故事板,因为这个应用程序很旧。它有 XIB。所以这个应用程序总是需要转到登录屏幕,在那里检查是否存储了 accessToken,它将从登录屏幕转到主屏幕。如果未存储,它将保留在登录屏幕中。所以这是必须执行的。因此,只有一种方法可以像下面这样编码。

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
   ...
   ...
   loginViewController = [[LoginViewController alloc] initWithNibName:@"LoginViewController" bundle:nil];

   self.navigationController = [[UINavigationController alloc]initWithRootViewController:loginViewController];
   self.navigationController.restorationIdentifier = @"NavigationController";
   [loginViewController.view setBackgroundColor:[UIColor whiteColor]];
   self.window.rootViewController = self.navigationController;
   ...
   ...
}
Run Code Online (Sandbox Code Playgroud)

我已经在 viewDidLoad() 中为所有视图控制器提供了恢复 ID,如下所示。例如这是我在 PetDetailViewController.m 中所做的

    - (void)viewDidLoad
    {
        [super viewDidLoad];

        self.restorationIdentifier = @"MatchedPetIdentification";
        self.restorationClass = [self class]; …
Run Code Online (Sandbox Code Playgroud)

application-restart ios uikit-state-preservation state-restoration ios-background-mode

6
推荐指数
1
解决办法
1989
查看次数

具有自定义代理或数据源的视图控制器的状态保留

我试图使用iOS 6+(我的应用程序是7.0+)State Preservation来保留从另一个View Controller以模态方式呈现的视图.因此,它具有典型的模态视图控制器解雇模式:

TNTLoginViewController.h包含

@protocol TNTLoginViewControllerDelegate <NSObject>

- (void)TNTLoginViewControllerDismiss:(TNTLoginViewController *)controller;

@end

@interface TNTLoginViewControllerDelegate : NSObject

@interface TNTLoginViewController : UIViewController

@property (weak, nonatomic) IBOutlet id <TNTLoginViewControllerDelegate> delegate;

- (IBAction)getStarted:(id)sender;

@end
Run Code Online (Sandbox Code Playgroud)

getStarted:实现

- (IBAction)getStarted:(id)sender
{
    // Perform login
    ...

    // Dismiss me
    [self.delegate TNTLoginViewControllerDismiss:self];
}
Run Code Online (Sandbox Code Playgroud)

TNTLoginViewControllerDismiss:委托上的方法,它提供了模态

- (void)TNTLoginViewControllerDismiss:(TNTLoginViewController *)controller
{
    [self dismissViewControllerAnimated:YES completion:nil];
}
Run Code Online (Sandbox Code Playgroud)

这一切都像一个魅力!直到国家保护.简单地说,我不知道TNTLoginViewController如何保留其委托.我理解为什么它不能:它只是一个指针!所以我尝试了各种派生委托的方法:

  1. 恢复类:遗憾的是,作为一种类方法,viewControllerWithRestorationIdentifierPath:coder:并没有帮助我指出我具体呈现的View Controller.
  2. 将我的演示VC设置为故事板中的模态VC代理:Xcode不会让我绘制该连接,即使我的演示VC的类公开采用TNTLogingViewControllerDelegate>其标题中的协议.这可能是一个单独的问题,或者可能不允许这样做.
  3. 使用application-delegate-level application:viewControllerWithRestorationIdentifierPath:coder:返回一个模态视图控制器,其委托设置为我呈现的View Controller.我必须能够从App Delegate派生出VC,但它可能有效.

我现在要和#3一起去,但如果有更好的解决方案,有人可以推荐,我会很激动.

设置会产生类似的问题:

  1. 设置数据源,比如表视图.

delegates objective-c ios uikit-state-preservation

5
推荐指数
1
解决办法
817
查看次数

iOS保留UIWebView的状态?

是否可以在当前的应用程序启动中保留UIWebView的状态(例如当前网页,后退/前端列表)?例如,如果我取消分析webview,并且在将来的某个时候,我想重新创建它 - 是否可以赋予它先前的状态?

iphone uiwebview ipad ios uikit-state-preservation

4
推荐指数
1
解决办法
1781
查看次数