2013-11-22 45 views
3

我正在使用名爲CSAppData的單例存儲我的iPhone應用程序的數據。我將一個名爲CSInbox的對象存儲在單例中。當我註銷我的應用程序時,我想清除該對象的數據。安全地清除單身數據的最佳方法?

這是我的單代碼,包括用於清除數據的方法:在我的視圖控制器之一

- (id)init { 
    self = [super init]; 
    if (self) 
    { 
     self.inbox = [[CSInbox alloc] init]; 
    } 
    return self; 
} 

+ (CSAppData *)appData { 
    static CSAppData * appDataInstance; 
    @synchronized(self) { 
     if(!appDataInstance) { 
      appDataInstance = [[CSAppData alloc] init]; 
     } 
    } 
    return appDataInstance; 
} 

+(void) clearData { 
    CSAppData *appData = [CSAppData appData]; 
    appData.inbox = [[CSInbox alloc] init]; 
} 

然而,在initWithCoder方法,我存儲在收件箱變量:

-(id) initWithCoder:(NSCoder *)aDecoder { 
    self = [super initWithCoder:aDecoder]; 
    if(self) { 
     self.inbox = [[CSAppData appData] inbox]; 
    } 
    return self; 
} 

因此,當應用程序註銷並調用clearData方法時,視圖控制器仍然指向舊的CSInbox對象。而且即使我初始化一個新的視圖控制器,並將其設置爲根視圖控制器(在AppDelegate中),就像這樣:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil]; 
MainTabControllerViewController *viewController = (MainTabControllerViewController *)[storyboard instantiateViewControllerWithIdentifier:@"mainView"]; 
[self.window setRootViewController:viewController]; 

具有CSInbox永遠不會重新初始化,並且將一個子視圖控制器依舊指向那個舊的CSInbox對象。 (我不知道爲什麼會發生這種情況。)

那麼,解決這個問題的最好方法是什麼?

  1. 更改clearData方法在單隻重置CSInbox對象的屬性,而不是alloc和init和新的?
  2. self.inbox = [[CSAppData alloc] init];移至視圖控制器類中的viewDidLoad,以便在第二次登錄時正確設置它?
  3. 更改AppDelegate中的註銷功能,以便釋放根視圖控制器和所有其他視圖控制器,以便它們在第二次登錄時重新初始化?

我傾向於1號或3 ...

按照要求,這裏是CSInbox.h:

@interface CSInbox : NSObject 

@property (nonatomic,strong) NSMutableArray *threads; 
@property (nonatomic, assign) NSInteger newCount; 
@property (nonatomic,strong) NSDate *lastUpdate; 

-(void) setThreadsFromJSON:(NSDictionary *)json; 

@end 

這裏是CSInboxViewController.h

@interface CSInboxViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate, CSThreadViewControllerDelegate> 

@property (strong, nonatomic) IBOutlet UITableView *inboxTableView; 
@property (strong,nonatomic) CSInbox *inbox; 

@end 

and CSAppData.h

@interface CSAppData : NSObject { 
    CSInbox *inbox; 
} 

@property(nonatomic,strong) CSInbox *inbox; 

+ (CSAppData *)appData; 
+ (void)clearData; 

@end 
+1

所以,它不是一個真正的單例對象......你如何創建一個單例類/對象? –

回答

5

我想答案不在於破壞單對象並重新創建它,但真正清除單對象中的實例變量。

你沒有表現的[CSAppData inbox]的聲明,但如果它是一個NSMutableArray,例如,那麼你就可以清除,並以單對象的任何現有的引用可以保持:

+(void) clearData { 
    CSAppData *appData = [CSAppData appData]; 
    [appData.inbox removeAllObjects]; 
} 
+0

這基本上是選項#1 ...我在上面添加了CSInbox.h代碼。我可以在那裏添加一個方法來重置數據,然後從CSAppData單例中調用該方法? –

+0

這也是我最初的想法 - 爲什麼重新分配項目而不是讓arc最終釋放它。 – GuybrushThreepwood

+0

@TrevorGehman是的。但是,如果任何UI元素包含數據(很可能),複雜性會增加。您可能想要使用通知來表示對此數據結構的更改。 – trojanfoe

1

一到方式處理這一點,遵守使用單身人士的精神,讓您的視圖控制器直接訪問您的單身人士,即:[CSAppData appData].inbox而不是self.inbox。這有點貴,但它會「神奇地」解決你的問題。

如果你不能接受,我會選擇你列出的選項#1。更妙的是,我會讓單身身上的inbox本身,或確保它永遠不會被另一個實例取代。

編輯:

你,是這樣,當inbox對象已經改變了它得到通知,在你的控制器使用志願另一種方法。不知道它是否值得,但可以使用。

+0

我想過這樣做,但我認爲最好的做法是將數據傳遞給視圖控制器,而不是讓視圖控制器訪問其他地方的數據... –

+0

我明白你的觀點,儘管你使用單例作爲一種方式有序訪問您的數據。這在你的應用中是一種基本的設計選擇,我不認爲這是堅持使用它的不好的習慣(你也會發現它是處理這個問題的最簡單的方法)。另一方面,有人會說,首先使用單身人士是不好的做法,因爲它創建的依賴關係。 – sergio