保存 iOS 应用场景状态

Posted

技术标签:

【中文标题】保存 iOS 应用场景状态【英文标题】:Saving iOS Application Scene State 【发布时间】:2012-04-15 23:18:16 【问题描述】:

这可能是不可能的,但我试图在场景转换之间保存我的应用程序的状态,但我不知道该怎么做。目前我喜欢这样的方式,当你有一个应用程序运行并点击主页按钮时,你可以回到你离开的那个应用程序,但是如果你在场景之间转换(在故事板中),一旦你回到那个场景应用程序状态未保存。

我只有两个不同的场景需要保存(您从一个场景来回切换到另一个场景)。如何在不占用精确内存的情况下保存故事板场景状态?

更详细:这是我的整个故事板。您可以使用加号工具栏按钮在场景之间来回切换。在第二个场景中,用户可以点击表格视图单元格,一个真实的图像将填充图像视图(见图 1.2)

图1.1

在图 1.2 中,您可以看到当您点击多个表格视图单元格之一时会发生什么(弹出一个图像视图。)

图1.2

问题:当你点击一个表格视图单元格时,它会填充一个图像视图(如图 1.2 所示),如果你停留在那个场景甚至点击 iPhone 主页按钮(如果你点击 iPhone 的主页按钮,然后重新打开应用程序,场景的状态被保存,充满简单图像的图像视图仍然像我们离开它一样显示),但是如果我(使用加号按钮)转换回第一个场景,然后使用第一个场景上的加号按钮返回到第二个场景,我创建的图像视图(如图 1.2 所示)消失了,第二个场景加载而不保存我们填充的状态和图像视图。

编辑:我尝试对两个场景使用相同的视图控制器,但并没有解决问题。

更新:我刚刚找到了以下代码(我认为它存储了视图状态)。我该如何使用它,这就是我一直在寻找的东西吗?

MyViewController *myViewController=[MyViewController alloc] initWithNibName:@"myView" bundle:nil];
[[self navigationController] pushViewController:myViewController animated:YES];
[myViewController release];

【问题讨论】:

操作系统应该为你保存“场景”。您的案例有什么特别的不同? 当我点击主页按钮并重新打开应用程序时它会保存场景的状态,但当我切换到不同的场景并返回时它不会保存场景。 【参考方案1】:

我建议将两件事结合起来: 1. 听取DBD 的建议,确保不要不断创建新视图 2. 创建一个共享类,即数据控制器(针对高尔夫球手,使数据独立于场景)

制作segues的正确方法是让一个从左侧的视图控制器引导到右侧的视图控制器。但是,要关闭右侧的那个,您可以使用

-(IBAction)buttonPushed:(id)sender 
      [self dismissModalViewControllerAnimated:YES];

这将带您回到左侧的视图控制器,左侧的视图控制器处于其原始状态。现在的问题是如何保存右边的数据。

为此,您可以创建一个单例类。单例类只有一个实例,所以无论你去右边的视图控制器多少次,数据总是一样的。

单例类实现(一个名为 DataManager 的类) - 标题

@interface DataManager : NSObject 


+(id)initializeData;
-(id)init;
@end

单例类实现(一个名为 DataManager 的类) - 主要

static DataManager *sharedDataManager = nil;

@implementation DataManager
+(id)initializeData 
    @synchronized(self) 
        if (sharedDataManager == nil)
            sharedDataManager = [[self alloc] init];
    
    return sharedDataManager;


-(id)init  
    if(self == [super init]) 
     
    return self;

@end

然后,在您的视图控制器代码中,您可以像这样获取此实例

DataManager *sharedDataManager = [DataManager initializeDataManager];

这样,无论您切换多少次视图,您都将拥有相同的数据。 此外,您可以通过将数据和视图控制器分开来更好地遵守 MVC 编程。 (http://en.wikipedia.org/wiki/Model–view–controller)

【讨论】:

【参考方案2】:

图 1.1 有一个根本缺陷,我认为这是您问题的基础。

Segues(故事板上控制器之间的箭头)创建UIViewControllers 版本。你有循环序列。因此,当您通过 segue “返回”原始屏幕时,实际上是通过创建新版本来带您前进。

这可能会给内存使用带来重大问题,但这也意味着您无法维护状态,因为每个新创建的项目都是空的。

由于您使用的是UINavigationControllerpushViewController:animated:,您应该“弹出”您的控制器以摆脱它。

在您的“第二个”场景中,从 + 按钮中删除 segue,并在 touchUpInside 事件上创建一个 IBAction。在IBAction 代码中添加“pop”

- (IBAction)plusButtonTapped 
    [self.navigationController popViewControllerAnimated:YES];

【讨论】:

其实我并没有使用 UINavigation Controller,我该如何在我的场景中实现呢? 在您提到使用[[self navigationController] pushViewController:myViewController animated:YES]; 显示您的第二个屏幕的代码中,这意味着您正在使用UINavigationController【参考方案3】:

我明白你的意思。这应该发生在每个应用程序中,因为当导航堆栈中的最后一个视图控制器被转换离开时,它会被释放和释放。如果您需要保存诸如文本或对象位置之类的值,plist 可能是要走的路。请参阅this related question 了解如何使用 plist。

【讨论】:

有什么方法我不能释放/释放场景 我从来没有听说过 UIViewController 单例...我想这是可能的。【参考方案4】:

Apple 不会为您执行此操作。您可能应该只使用 NSUserDefaults 保存每个视图的状态,并且每次启动应用程序时重新加载您保存的数据。

如果您将所有内容存储在 CoreData 中,您只需要保存活动视图和一些对象 ID,否则您需要保存所有数据。

不要指望 ios 会在两次启动之间保存您在内存中的任何内容。只需将其存储在 NSUserDefaults 中并每次加载即可。

【讨论】:

如何存储场景状态?我要存储什么对象?你能告诉我示例代码吗? - 我是 iOS 新手,目标是 c...【参考方案5】:

将场景的状态存储在 NSUserDefaults 或 plist 文件中,然后在加载场景时只需从那里加载设置即可。如果图像是从 Internet 加载的,您可能还希望将它们本地保存在您的 iphone 硬盘上,以便运行更流畅。

【讨论】:

如何存储场景状态?我要存储什么对象?你能告诉我示例代码吗?【参考方案6】:

我认为您不应该循环使用 segue,只需使用从 viewcontroller 2 连接 viewcontroller 1 的一个就足够了,这样您就可以确保没有制作额外的 viewcontroller(可能是内存问题?)

但是对于您的特定问题,我认为您应该使用核心数据来保存表的确切状态,视图,因为 ios 不会始终保存视图的确切状态。这将需要工作,但你会实现你想要的。您将需要保存确切的照片(使用将保存的代码或枚举)、表格视图中的位置、分数或保存该状态所需的任何数据。

最棒的是,coredata 非常高效,当应用程序重新启动或进入前台时重新加载数据不需要时间,而且到目前为止,我使用 core data 加载了超过 5k 条记录并且工作得很好,而且它的一点也不慢。

当我回到家时,我会提供一个代码,您可能会用它来了解我的意思。

【讨论】:

【参考方案7】:

这里的关键是:

    为您的应用程序需要的数据提供某种存储空间。这是您的应用程序的数据模型。

    让每个视图控制器访问模型,或至少访问它需要完成工作的模型部分。然后,视图控制器可以使用模型中的数据在创建模型时或即将出现视图时对其进行配置。

    让每个视图控制器在适当的时间更新模型,例如视图即将消失时,甚至是每次用户进行更改时。

您可以通过多种方式在内存中组织数据,也可以通过多种方式将数据存储在磁盘上(即长期存储)。属性列表、核心数据、普通旧数据文件和密钥存档都是将数据写入文件的可能性。 NSArray、NSDictionary、NSSet 等都是可以用来帮助您在内存中组织数据的类。但是,这些都与让您的视图控制器感觉持久没有任何关系。当然,你会使用它们,但你选择哪一个并不重要,就更新你的视图控制器而言。同样重要的是,您拥有某种模型,并且您的视图控制器可以访问它。

通常,应用程序委托设置模型,然后根据需要将其传递给视图控制器。

其他可能有帮助的事情是,当您的视图控制器从导航堆栈中弹出时,您没有让它们被删除。如果需要,您可以在应用程序委托中设置两个视图控制器,以便它们保持不变。然后,您可以使用已有的,而不是一直创建新的,这样做您会自动获得一定程度的持久性。

【讨论】:

以上是关于保存 iOS 应用场景状态的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 13 中,何时保存数据?

行为型设计模式之备忘录模式

行为型设计模式之备忘录模式

简述 gevent模块的作用和应用场景。

keep-alive 作用以及应用场景

Key/Value之王Memcached初探:Memcached解决Session的分布式存储场景的应用