保存iOS应用程序场景状态

时间:2012-04-15 23:18:16

标签: ios objective-c iphone cocoa-touch

这可能是不可能的,但我正在尝试在场景转换之间保存我的应用程序状态,但我无法弄清楚要做什么。目前我喜欢这样一种方式:当你运行一个应用程序并点击主页按钮时,你可以回到你离开的地方回到那个应用程序,但如果你在场景之间转换(在故事板中),一旦你回到那个场景应用程序状态未保存。

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

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

Figure 1.1图1.1

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

Figure 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];

7 个答案:

答案 0 :(得分:2)

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

Segues(故事板上控制器之间的箭头)创建UIViewControllers版本。你有圆形的segues。因此,当您通过segue“返回”原始屏幕时,您可以通过创建新版本来带领您前进。

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

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

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

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

答案 1 :(得分:2)

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

制作segue的正确方法是从左侧的视图控制器到右侧的视图控制器。但是,要解雇右边的那个,你可以使用

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

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

为此,您可以创建单例类。 Singleton类只有一个实例,因此无论您转到右侧的视图控制器多少次,数据都将始终相同。

Singleton类实现(名为DataManager的类) - Header

@interface DataManager : NSObject {
}

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

Singleton类实现(名为DataManager的类) - Main

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 :(得分:0)

我明白你的意思了。这应该发生在每个应用程序中,因为当导航堆栈中的最后一个视图控制器转换离开时,它将被释放并释放。如果您需要保存文本或对象位置等值,则可以使用plist。有关如何使用plist的信息,请参阅this related question

答案 3 :(得分:0)

Apple不打算为你做这件事。您可能只需使用NSUserDefaults保存每个视图的状态,并且每次应用程序启动时都会重新加载已保存的数据。

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

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

我认为你不应该循环segues,只需使用一个连接viewcontroller 1来自viewcontroller 2就足够了,这样你就可以确保没有其他的viewcontrollers正在制作(可能是内存问题?)

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

最好的是,coredata非常高效,可以在应用程序重新启动时重新加载数据,或者进入前台,它会花费时间,并且我已经使用核心数据加载超过5k的记录,直到现在并且工作正常并且根本不慢。

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

答案 6 :(得分:0)

这里的关键是:

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

  2. 为每个视图控制器提供对模型的访问权限,或者至少为模型中完成其工作所需的部分提供访问权限。然后,视图控制器可以使用模型中的数据在创建时或在视图即将出现时自行配置。

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

  4. 您可以通过多种方式在内存中组织数据,并且可以通过多种方式将其存储在磁盘上(即长期存储)。属性列表,核心数据,普通旧数据文件和键控存档都是将数据写入文件的可能性。 NSArray,NSDictionary,NSSet等都是可用于帮助您在内存中组织数据的类。但是,这些与使视图控制器保持持久性无关。你肯定会使用它们,但是你选择哪一个对于更新你的视图控制器来说并不重要。重要的是,你有一些模型,你的视图控制器可以访问它。

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

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