2010-02-28 17 views
3

有人可以共享保存iPhone应用程序的程序状态(UINavigationController堆栈等)的好方法。使用深度UINavigationController保存iPhone程序状态

我的应用程序从网络中获取一串信息,我想要返回到他们所在的最后一个屏幕,即使它是3或4屏幕深度。

我假设我将需要重新加载网络中的数据,因为我重新创建UINavigation控制器。我不一定有这个问题。

我在想也许让我的UINavigationController对象实现某种类型的协议,它允许我保存/设置它们的状态?我期望听到其他人可能需要实施类似的情况以及他们是如何完成的。

我的应用程序在根目录下有一个UITabbarController,每个标签栏项目有UINavigationController项目。

谢谢!

回答

1

这是我最终做的解决方案。

我创建了一个协议,其中包含一个方法来“获取状态”,然后到“从字典方法状态的init”。

因此,当应用程序关闭时,我遍历所有控制器并询问状态。然后当应用程序开始备份时,我使用状态初始化,传入我序列化的字典。它运作良好!

+0

能否请您发布您的代码,你怎么实现的呢? – 2012-05-22 12:25:39

0

我在我的应用程序之一,并从这样做我可以看到它的相当manuagel过程

对于每个TargetViewControllers,你将不得不将它们推到视图控制器,设置动画为NO,所以它看起来就像它正在恢复状态一样。

[[self navigationController] pushViewController:targetViewController animated:NO]; 

也许别人可以指向一个框架,允许你坚持这些视图控制器。

1

要保存并重新加载导航堆栈,我做了以下操作。

- (空)applicationDidBecomeActive:(UIApplication的*)应用程序{

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 

// if a navigation stack is stored in UserDefaults 
// loop through the array until all views are pushed onto the stack. 
// This will bring the user to the view they were on when the app terminated. 
if([prefs objectForKey:@"viewStack"] != nil){ 
    for (id viewItem in [prefs arrayForKey:@"viewStack"]) { 
     [self.navigationController pushViewController:viewItem animated:NO]; 
    } 
} 
} 

- (空)applicationWillTerminate:(UIApplication的*)应用程序{

// Create an array to store the array of viewControllers currently on the stack. 
NSArray *stackArray = [NSArray arrayWithArray:navigationController.viewControllers]; 

// if user has navigated beyond the rootview, save the nav stack. 
if([stackArray count] > 1) 
    [[NSUserDefaults standardUserDefaults] setObject:stackArray forKey:@"viewStack"]; 
} 
+0

你确定这是一个可行的方法吗?看起来好像你在NSUserDefaults中存储UIViewControllers。据我所知,你只能将.plist对象存储在NSUserDefaults中。另外,对于需要存储和检索变量的其他应用程序来说,这可能更加复杂。在我看来,使用NSDictionary(存储在NSUserDefaults中)是最佳选择。 – 2010-09-15 17:46:06

0

我猜我使用(排序)与Jr.一样的方法,我会为了教育而将它张贴出来。

我有一种协议,它看起来像这样:

FSViewControllerRestoration.h

​​

我也有一个用于装载和存储所述视图控制器堆栈的类。当加载视图控制器堆栈时,它检查类是否符合协议,如果是,则调用restoreState:方法。

FSViewControllerStorage.h

#import <Foundation/Foundation.h> 
#import "FSViewControllerStateRestoration.h" 


@interface FSViewControllerStateStorage : NSObject 

+ (BOOL)storeViewControllerStack:(NSArray *)stack; 
+ (NSArray *)loadViewControllerStack; 

@end 

FSViewControllerStorage.m

#import "FSViewControllerStateStorage.h" 


#define FS_PATH_APPLICATION_STATE_FILE [FS_PATH_DOCUMENTS_DIR stringByAppendingPathComponent:@"appstate.dat"] 


@implementation FSViewControllerStateStorage 

+ (BOOL)storeViewControllerStack:(NSArray *)stack 
{ 
    DLog(@"storing view controller stack ..."); 

    if (stack.count <= 1) 
    { 
     return [NSKeyedArchiver archiveRootObject:nil toFile:FS_PATH_APPLICATION_STATE_FILE]; 
    } 

    NSArray *items = @[]; 

    for (UIViewController *viewController in stack) 
    { 
     NSString *className = NSStringFromClass(viewController.class); 
     NSDictionary *state = @{}; 

     if ([viewController conformsToProtocol:@protocol(FSViewControllerStateRestoration)]) 
     { 
      state = [(id <FSViewControllerStateRestoration>)viewController currentState]; 
     } 

     items = [items arrayByAddingObject:@{@"Class" : className, @"State" : state}]; 
    } 

    return [NSKeyedArchiver archiveRootObject:items toFile:FS_PATH_APPLICATION_STATE_FILE]; 
} 

+ (NSArray *)loadViewControllerStack 
{ 
    DLog(@"loading view controller stack ..."); 

    NSArray *items = [NSKeyedUnarchiver unarchiveObjectWithFile:FS_PATH_APPLICATION_STATE_FILE]; 
    NSArray *stack = @[]; 

    for (NSDictionary *dictionary in items) 
    { 
     NSString *className = [dictionary objectForKey:@"Class"]; 
     NSDictionary *state = [dictionary objectForKey:@"State"]; 

     Class class = NSClassFromString(className); 
     UIViewController *viewController = [[class alloc] init]; 
     if ([viewController conformsToProtocol:@protocol(FSViewControllerStateRestoration)]) 
     { 
      [(id <FSViewControllerStateRestoration>)viewController restoreState:state]; 
     } 

     stack = [stack arrayByAddingObject:viewController]; 
    } 

    return stack; 
} 

@end 

在我的AppDelegate存储类的使用方法如下...

- (void)applicationDidEnterBackground:(UIApplication *)application 
{ 
    [FSViewControllerStateStorage storeViewControllerStack:self.navigationController.viewControllers]; 
} 

- (void)applicationDidBecomeActive:(UIApplication *)application 
{ 
    NSArray *viewControllers = [FSViewControllerStateStorage loadViewControllerStack]; 
    if (viewControllers.count > 0) 
    { 
     self.navigationController.viewControllers = viewControllers; 
    } 
} 

一ND终于存储和符合该协议的viewController恢复状态的一个例子:

#pragma mark - View controller state restoration 

- (NSDictionary *)currentState 
{ 
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; 

    if (_newsItem) 
    { 
     [dictionary setObject:_newsItem forKey:@"NewsItem"]; 
    } 

    if (_comments) 
    { 
     [dictionary setObject:_comments forKey:@"Comments"]; 
    } 

    return dictionary; 
} 

- (void)restoreState:(NSDictionary *)state 
{ 
    FSNewsItem *newsItem = [state objectForKey:@"NewsItem"]; 
    if (newsItem) 
    { 
     self.newsItem = newsItem; 
    } 

    NSArray *comments = [state objectForKey:@"Comments"]; 
    if (comments) 
    { 
     self.comments = comments; 
    } 

}