1

我正在尝试编写一个简单的iOS程序,该程序会在插入/拔出耳机时发出通知。我对Objective-Cand很陌生iOS,很多代码是由其他人编写的,我现在正在尝试调整它,所以我在解决这个问题时遇到了问题。代码在这里:

AppDelegate.m

#import "AppDelegate.h"

@implementation AppDelegate

static void onHeadsetChange(void *, AudioServicesPropertyID, UInt32, const void *);

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.headsetOnHandler = self.headsetOffHandler = ^{};
    NSLog(@"%lu", AudioSessionInitialize(NULL, NULL, NULL, NULL));
    NSLog(@"%lu", AudioSessionSetActive(true));
    NSLog(@"%lu", AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, &onHeadsetChange, (__bridge void *)self));
    return YES;
}

static void onHeadsetChange(void *inUserData, AudioSessionPropertyID inPropertyID, UInt32 inPropertyValueSize, const void *inPropertyValue) {
    if (inPropertyID != kAudioSessionProperty_AudioRouteChange) return;
    NSLog(@"The headset changed");
    AppDelegate *const delegate = (__bridge AppDelegate *)inUserData;

    const CFDictionaryRef routeChangeDictionary = inPropertyValue;
    const CFNumberRef routeChangeReasonRef = CFDictionaryGetValue(routeChangeDictionary, CFSTR(kAudioSession_AudioRouteChangeKey_Reason));
    SInt32 routeChangeReason;
    CFNumberGetValue(routeChangeReasonRef, kCFNumberSInt32Type, &routeChangeReason);
    switch (routeChangeReason) {
        case kAudioSessionRouteChangeReason_NewDeviceAvailable:
            //NSLog([delegate description]);
            [delegate headsetOnHandler];
            break;
        case kAudioSessionRouteChangeReason_OldDeviceUnavailable:
            [delegate headsetOffHandler];
            break;
        default:
            break;
    }
}
@end

视图控制器.m

#import "ViewController.h"

@implementation ViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor redColor];
    AppDelegate *delegate = (AppDelegate *)([UIApplication sharedApplication].delegate);
    delegate.headsetOnHandler = ^{ self.view.backgroundColor = [UIColor greenColor];};
    delegate.headsetOffHandler = ^{ self.view.backgroundColor = [UIColor redColor];};
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

我得到EXC_BAD_ACCESS error, code=1 at [delegate headsetOnHandler] and [delegate headsetOffHandler]. 如果我需要包含这些.h文件以使其有意义,我会的,如果我还缺少其他任何东西,请告诉我。

编辑:我添加了人们认为应该添加的声明:

@property (readwrite, assign) void (^headsetOnHandler)(void);
@property (readwrite, assign) void (^headsetOffHandler)(void);
4

2 回答 2

2

headsetOnHandlerheadsetOffHandler属性是如何声明的?

如果是assignretain,那很可能是您的问题的根源。由于它们是块,因此需要copy(甚至在某些情况下,在 ARC 下)。如果它们是atomicand retain,那么您的 getter 将有效地调用[[block retain] autorelease]getter,这将解释您的崩溃。

有点长镜头。

  • 当你发生崩溃时,总是发布回溯

  • 当您知道崩溃所在的代码行时,请始终在该行上发布任何变量的变量声明

请注意,ARC 会稍微改变这种行为,在某些情况下会自动处理这些块,但是——IIRC——在这种情况下你仍然需要copy它们。

于 2013-05-22T05:56:44.167 回答
1

这是 Ray Wenderlich 关于 EXC_BAD_ACCESS 的一篇好文章。

http://www.raywenderlich.com/10209/my-app-crashed-now-what-part-1

于 2013-05-22T06:22:15.317 回答