0

这很奇怪。每当我启用 LLVM 编译器优化(-O/-O1 或更高版本)时,当访问我的类上的属性时,我会收到 EXC_BAD_ACCESS 错误。在代码流的早期访问该属性没有问题,但在“某个时候”(我知道,它很模糊)应用程序崩溃了。

我已经查看了其他几个 Stack Overflow 问题:严格别名,但没有看到(或理解)我可能在代码中破坏它的地方。这是违规课程:(在课程结束时显示崩溃)

#import "MessageManager.h"
#import "NSURL+Additions.h"
#import "NSString+Guid.h"

static MessageManager *_instance = NULL;

@interface MessageManager ()

@property (nonatomic, strong) NSMutableDictionary *listeners;
@property (nonatomic, strong) NSMutableDictionary *senders;

@end

@implementation MessageManager

@synthesize listeners, senders;

+ (MessageManager *) getInstance
{
    @synchronized(self)
    {
        if (self == [MessageManager class] && _instance == NULL) {
            _instance = [[self alloc] init];
            _instance.listeners = [NSMutableDictionary dictionary];
            _instance.senders = [NSMutableDictionary dictionary];
        }
    }
    return (_instance);
}

#pragma mark
#pragma mark Senders

- (void) addMessage:(Message *)message sender:(void (^) ())sender callback:(void (^) (Message *))callback
{
    [self addMessage:message sender:sender callback:callback sendImmediately:NO];
}

- (void) addMessage:(Message *)message sender:(void (^) ())sender callback:(void (^) (Message *))callback sendImmediately:(BOOL)sendNow
{
    message.id = [NSString stringWithGuid];
    [senders setObject:[NSDictionary dictionaryWithObjectsAndKeys:message, @"message", [sender copy], @"sender", nil] forKey:message.id];

    // note: callbacks use the message id and not the key, so that they remain tied to the message and not other keyed events
    if (callback) [self registerListener:callback forKey:message.id];

    if (sendNow) {
        message.isSent = YES;
        sender();
    }
}

- (void) sendAll
{
    [self sendAllForTags:nil];
}

- (void) sendAllForTags:(NSArray *)tags
{
    typedef void (^SenderBlock) ();
    [senders enumerateKeysAndObjectsUsingBlock:^(NSString *messageId, id wrapper, BOOL *stop) {

        Message *message = (Message *)[(NSDictionary *)wrapper objectForKey:@"message"];
        id sender = [(NSDictionary *)wrapper objectForKey:@"sender"];
        BOOL validTag;
        if (tags && tags.count) {
            if (message.tags.count) {
                validTag = false;
                for (NSString *tag in tags) {
                    if ([message.tags containsObject:tag]) {
                        validTag = true; // found match! ok to send.
                        break;
                    }
                }
            } else validTag = false; // tags specified, but none in message, never send
        } else validTag = true; // no tags specified, always send

        if ((!message.isSent || message.isRepeatable) && validTag) {
            message.isSent = YES;
            ((SenderBlock)sender)(); // send message!
        }
    }];
}

#pragma mark
#pragma mark Listeners

- (void) registerListener:(void (^) (Message *))listener forKey:(NSString *)key
{
    if (![listeners objectForKey:key]) {
        [listeners setObject:[NSMutableArray array] forKey:key];
    }
    [(NSMutableArray *)[listeners objectForKey:key] addObject:listener];
}

- (BOOL) handleOpenURL:(NSURL *)url
{
    Message *message = [[Message alloc] initWithJson:[[url queryParams] objectForKey:@"message"]];
    NSLog(@"%@", listeners); // <<<<----- CRASH HAPPENS HERE (or the first place in this method that "listeners" is referenced)
    NSMutableArray *keyedListeners = (NSMutableArray *)[listeners objectForKey:message.key];
    typedef void (^ListenerBlock)(Message *);
    for (ListenerBlock keyedListener in keyedListeners) {
        keyedListener(message);
    }
    return YES;
}


@end

注意: registerListener:forKey: 在 handleOpenUrl: 被调用之前被调用多次,没有任何错误,即使它引用了“listeners”属性。

对于上下文,这是我创建的允许发送和接收消息和事件的消息传递框架的一部分。

编辑:堆栈跟踪

0 MyApp 0x00026206 testflight_backtrace + 158
1 MyApp 0x00026e30 TFSignalHandler + 244
2 libsystem_c.dylib 0x36fc67ec _sigtramp + 48
3 MyApp 0x00024f7c -[MessageManager handleOpenURL:] (MessageManager.m:112)
4 MyApp 0x0001c29a -[WebViewController webView:shouldStartLoadWithRequest:navigationType:] (WebViewController.m:327)
5 UIKit 0x32492482 -[UIWebView webView:decidePolicyForNavigationAction:request:frame:decisionListener:] + 182
6 CoreFoundation 0x352cf7e3 __invoking___ + 67
7 CoreFoundation 0x3522a7b0 -[NSInvocation invoke] + 160
8 CoreFoundation 0x3522a3ce -[NSInvocation invokeWithTarget:] + 50
9 WebKit 0x338b1e0c -[_WebSafeForwarder forwardInvocation:] + 252
10 CoreFoundation 0x352cea82 ___forwarding___ + 666
11 CoreFoundation 0x3522964f _CF_forwarding_prep_0 + 47
12 CoreFoundation 0x352cf7e3 __invoking___ + 67
13 CoreFoundation 0x3522a7b0 -[NSInvocation invoke] + 160
14 WebCore 0x37060648 _ZL11SendMessageP12NSInvocation + 24
15 WebCore 0x37073b44 _ZL20HandleDelegateSourcePv + 80
16 CoreFoundation 0x352a0ad2 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 14
17 CoreFoundation 0x352a029e __CFRunLoopDoSources0 + 214
18 CoreFoundation 0x3529f044 __CFRunLoopRun + 652
19 CoreFoundation 0x352224a4 CFRunLoopRunSpecific + 300
20 CoreFoundation 0x3522236c CFRunLoopRunInMode + 104
21 GraphicsServices 0x3651e438 GSEventRunModal + 136
22 UIKit 0x32318e7c UIApplicationMain + 1080
23 MyApp 0x0001aa32 main (main.m:34)
24 MyApp 0x0001a9e7 start + 39
4

1 回答 1

1

我认为这是您没有正确复制到集合中的块(侦听器)。看这个问题:Keep blocks inside a dictionary

一篇很好的文章说明你为什么需要这样做

于 2012-06-29T09:14:44.793 回答