2010-02-28 16 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; 
    } 

}