2013-11-22 42 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