这很奇怪。每当我启用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
答案 0 :(得分:1)
我认为这是你没有正确复制到集合中的块(听众)。看看这个问题:Keep blocks inside a dictionary
您需要执行此操作的原因a very good write up