2

很抱歉对我的问题的解释不好。这是我更新的代码和步骤。我也更新了标题。
!!!编辑!!!

1)我正在使用 CoreData 数据库在 ARC 项目中实现搜索。
2) 搜索 viewController 从 mainStoryboard 实例化,如下所示:

搜索控制器在故事板中,标识符为“搜索”

SearchTableViewController *searchController = (SearchTableViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:@"Search"];
[[[self tabBarController] parentViewController] presentViewController:searchController animated:NO completion:nil];

3) 显示的带有搜索的视图控制器在事件控制器DidEndSearch 上关闭(例如通过单击 UISearchBar 中的取消按钮)。

-(void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
    [self dismissViewControllerAnimated:NO completion:nil];
}

我的错误仅在我使用搜索打开和关闭视图控制器时发生。

4) 有一个单例对象正在监听刷新事件。

刷新服务.m

+(RefreshService *)getDefaultRefreshService {
    if (DefaultRefreshService == nil) DefaultRefreshService = [[self allocWithZone:nil] init];
    return DefaultRefreshService;
}
-(id)init {
    self = [super init];
    if (self) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:NSSelectorFromString(@"refresh:") name:@"refresh_event" object:nil];
    }
    return self;
}  

5)有一个刷新按钮,通过发布通知触发刷新

-(IBAction)refreshAction:(id)sender {
    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:@"refresh_event" object:@"OK"]];
}

好案例场景:
1.启动应用程序。
2. 单击刷新按钮
3. 一切正常,refreshService 收到通知并触发刷新方法 - 定义在第 4 点)

和失败的糟糕用例:
1. 启动应用程序。
2. 单击搜索按钮 - 见第 2) 点
3. 单击取消 - 见第 3) 点
4. 单击刷新按钮 - 见第 5) 点
5. 现在它在 refreshService 收到通知之前失败,而是我收到错误:

-[NSAutoresizingMaskLayoutConstraint refresh:]: unrecognized selector sent to instance

或者

-[__NSCFDictionary refresh:]: unrecognized selector sent to instance

或者它在主要功能上因 SIGABART 而失败。

对我来说,似乎有些东西发布得不好,但我使用的是 ARC,所以我不手动处理释放对象...

4

1 回答 1

4

在尝试了各种选项后,我得出结论,在 NSNotificationCenter 事件上使用单例作为观察者不是线程安全的。在将观察者逻辑从单例移动到普通控制器之后,一切正常。我已经尝试了各种单例实现,这些实现应该是 ARC 的线程安全的,但它们都不是作为观察者工作的。

经过测试的单例实现:

1)我的单例实现

+(RefreshService *)getDefaultRefreshService {
    if (DefaultRefreshService == nil) DefaultRefreshService = [[self allocWithZone:nil] init];
    return DefaultRefreshService;
}

2) 从这里实现如何实现与 ARC 兼容的 Objective-C 单例?

+ (RefreshService *)getDefaultRefreshService
{
    static RefreshService *DefaultRefreshService = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        DefaultRefreshService = [[self alloc] init];
    });

    return DefaultRefreshService;
}

3) 从这里开始实施:我的 Objective-C 单例应该是什么样子?

+ (void)initialize
{
    static BOOL initialized = NO;
    if(!initialized)
    {
        initialized = YES;
        DefaultRefreshService = [[RefreshService alloc] init];
    }
}

对于每三个选项,我都使用了这个 init() 方法:

-(id)init {
    self = [super init];
    if (self) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:NSSelectorFromString(@"refresh:") name:@"refresh_event" object:nil];
    }
    return self;
}
于 2013-11-11T17:05:00.617 回答