添加NSNotification会导致应用程序崩溃

时间:2014-08-19 07:46:34

标签: objective-c override nsnotificationcenter subclassing nsnotification

我有两个类,一个是基类,另一个是子类。在基类中,我添加了一个通知,当应用程序进入后台时将触发该通知。但有些应用程序在执行handleAppBackground方法后崩溃了。我想它必须对子类实例做一些事情,因为当我从appDelegate中删除子类实例时,它不会崩溃。

#import <Foundation/Foundation.h>

@interface BaseClass : NSObject

+(BaseClass *) sharedManager;
- (void) handleAppBackground;

@end

实施文件

#import "BaseClass.h"

@implementation BaseClass
- (instancetype) init{
    if(self = [super init]){
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleAppBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];

    }
    return self;
}

+(BaseClass *) sharedManager{
    static BaseClass *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[BaseClass alloc] init];

    });
    return sharedInstance;
}
- (void) handleAppBackground{
    NSLog(@"Here");

}
@end

SubClass是标题

#import <Foundation/Foundation.h>
#import "BaseClass.h"

@interface SubClass1 : BaseClass
-(SubClass1 *) init;
-(void) method1;
@end

,实施是

#import "SubClass1.h"

    @implementation SubClass1

    -(SubClass1 *) init{
        if(self = [super init]){

        }
        return self;
    }


    -(void) method1{
        NSLog(@"Called in SubClass1");
    }
    @end

并在appDidFinnishLaunching

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    [BaseClass sharedManager];
    SubClass1 *class1 = [[SubClass1 alloc] init];
    [class1 method1];
    // Override point for customization after application launch.
    return YES;
}

这是崩溃日志中的任何帮助

 thread #1: tid = 0x31435, 0x015740e6 libobjc.A.dylib`lookUpImpOrForward + 59, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x0)
    frame #0: 0x015740e6 libobjc.A.dylib`lookUpImpOrForward + 59
    frame #1: 0x0157405c libobjc.A.dylib`lookUpImpOrNil + 62
    frame #2: 0x0156b84a libobjc.A.dylib`class_respondsToSelector_inst + 65
    frame #3: 0x0156b801 libobjc.A.dylib`class_respondsToSelector + 32
    frame #4: 0x017dd4cb CoreFoundation`___forwarding___ + 955
    frame #5: 0x017dd0ee CoreFoundation`__forwarding_prep_0___ + 14
    frame #6: 0x0123f049 Foundation`__57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke + 40
    frame #7: 0x01848f04 CoreFoundation`__CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 20
    frame #8: 0x017a0efb CoreFoundation`_CFXNotificationPost + 2859
    frame #9: 0x01178e41 Foundation`-[NSNotificationCenter postNotificationName:object:userInfo:] + 98
    frame #10: 0x002334b3 UIKit`-[UIApplication _handleApplicationSuspend:eventInfo:] + 817
    frame #11: 0x00240193 UIKit`-[UIApplication handleEvent:withNewEvent:] + 4030
    frame #12: 0x00240555 UIKit`-[UIApplication sendEvent:] + 85
    frame #13: 0x0022d250 UIKit`_UIApplicationHandleEvent + 683
    frame #14: 0x037e2f02 GraphicsServices`_PurpleEventCallback + 776
    frame #15: 0x037e2a0d GraphicsServices`PurpleEventCallback + 46
    frame #16: 0x01768ca5 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
    frame #17: 0x017689db CoreFoundation`__CFRunLoopDoSource1 + 523
    frame #18: 0x0179368c CoreFoundation`__CFRunLoopRun + 2156
    frame #19: 0x017929d3 CoreFoundation`CFRunLoopRunSpecific + 467
    frame #20: 0x017927eb CoreFoundation`CFRunLoopRunInMode + 123
    frame #21: 0x037e15ee GraphicsServices`GSEventRunModal + 192
    frame #22: 0x037e142b GraphicsServices`GSEventRun + 104
    frame #23: 0x0022cf9b UIKit`UIApplicationMain + 1225
  * frame #24: 0x00002a2d TestSubclass`main(argc=1, argv=0xbfffed60) + 141 at main.m:16

2 个答案:

答案 0 :(得分:1)

您遇到的问题是:致电:

SubClass1 *class1 = [[SubClass1 alloc] init];

您将class1注册为观察者,但在该行之后:

[class1 method1];

该对象被释放,当您转到后台时,NSNotificationCenter会尝试在该类(已解除分配)上调用方法handleAppBackground导致压缩的原因。 要解决此问题,只需将此类删除为观察者,将此方法添加到SubClass1.m:

-(void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

答案 1 :(得分:0)

您的应用看起来崩溃了,因为它无法找到您分配给通知的选择器。

在你的情况下,导致它的原因是你没有将SubClass1的类对象设置为AppDelegate的iVar。

  

SubClass1 * class1

因此,在didFinishLaunchingWithOptions方法之后释放对象,当应用程序转到后台时,由于对象被解除分配,观察者无法找到选择器。

在您的示例中,如果您将AppDelegae.m代码更改为

@interface AppDelegate()
{
    SubClass1 *class1;
}
@end
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [BaseClass sharedManager];
    class1 = [[SubClass1 alloc] init];
    [class1 method1];

.......
}

并且在释放SubClass1时不要忘记删除观察者

SubClass1.m
-(void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

所以这基本上是一个记忆问题。