这很奇怪。每当我启用 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