2010-02-28 4 views
3

iPhone 응용 프로그램의 프로그램 상태 (UINavigationController 스택 등)를 저장하는 좋은 방법을 누군가가 공유 할 수 있습니까?깊은 UINavigationController로 iPhone 프로그램 상태 저장

내 응용 프로그램은 네트워크에서 많은 정보를 얻고 3 ~ 4 개의 화면이 있더라도 마지막 화면으로 되돌리고 싶습니다.

UINavigation 컨트롤러를 다시 만들면서 네트워크에서 데이터를 다시로드해야한다고 가정합니다. 나는 이것이 반드시 문제가되는 것은 아니다.

어쩌면 내 UINavigationController 개체를 저장/설정 상태를 허용하는 프로토콜의 일부 형식을 구현하는 생각하고있어? 비슷한 시나리오를 구현해야하는 다른 사람들의 의견을 듣고 어떻게 성취했는지 알고 싶습니다.

내 응용 프로그램에는 각 탭 표시 줄 항목의 루트 및 UINavigationController 항목에 UITabbarController가 있습니다.

감사합니다. 난 당신이, 애니메이션 세트 뷰 컨트롤러에 그들을 밀어해야합니다 귀하의 TargetViewControllers의 각각에 대해 그 꽤 manuagel 과정

를 볼 수있는 내 애플 리케이션 중 하나와에서 이런 짓을

답변

1

다음은 해결 방법으로 나왔습니다.

나는 "상태를 얻는"방법과 "사전의 상태에서 초기화"라는 방법을 포함하는 프로토콜을 만들었습니다.

그래서 응용 프로그램이 닫히면 모든 컨트롤러를 반복하여 상태를 묻습니다. 그리고 나서 응용 프로그램이 다시 시작될 때, 나는 serialize 된 사전을 전달하면서 상태로 초기화를 수행합니다. 잘 작동한다!

+0

코드를 게시하십시오. 어떻게 할 수 있습니까? –

0

는에 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에 UIViewController를 저장하는 것처럼 보입니다. 내가 아는 한, .plist 개체는 NSUserDefaults에만 저장할 수 있습니다. 또한 변수를 저장하고 검색해야하는 다른 앱에서도 훨씬 더 복잡 할 수 있습니다. NSDictionary (NSUserDefaults에 저장되어 있음)로 작업하면 내 생각에 최선의 선택입니다. –

0

가 나는 종류의 (사용 추측) Jr.와 같은 접근법을 교육용으로 게시 할 것입니다.

FSViewControllerRestoration.h

#import <Foundation/Foundation.h> 


@protocol FSViewControllerStateRestoration <NSObject> 

@required; 
- (NSDictionary *)currentState; 
- (void)restoreState:(NSDictionary *)state; 

@end 

I는 적재 뷰 컨트롤러 스택을 저장하기 위해 사용되는 클래스를 가지고

는 I는 다음과 같다 프로토콜을 갖는다. 뷰 컨트롤러 스택을로드 할 때 클래스가 프로토콜을 준수하는지 확인한 후 클래스가 프로토콜을 준수하는지 확인하고 restoreState : 메소드를 호출합니다.다음과 같이 저장 클래스를 사용하는 FSViewControllerStorage.h

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


@interface FSViewControllerStateStorage : NSObject 

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

@end 

내 AppDelegate에에서

#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 

FSViewControllerStorage.m

...

- (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; 
    } 
} 

마지막으로 프로토콜을 준수하는 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; 
    } 

}