1

iOSヘッドフォンが差し込まれたり抜かれたりしたときに通知する簡単なプログラムを作成しようとしています。私は と に非常にObjective-C慣れ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

ViewController.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

headsetOnHandlerandheadsetOffHandlerプロパティはどのように宣言されますか?

assignまたはの場合retain、それが問題の原因である可能性があります。それらはブロックであるため、ブロックである必要がありますcopy(場合によっては、ARC の下でも)。それらがatomicretainの場合、ゲッターは効果的にゲッターで呼び出し、[[block retain] autorelease]クラッシュを説明します。

ちょっと遠回り。

  • クラッシュが発生した場合は、常にバックトレースを投稿してください

  • クラッシュが発生しているコード行がわかっている場合は、常にその行の変数の変数宣言を投稿してください

ARC はこの動作を少し変更し、場合によってはブロックを自動的に処理しますが、IIRCcopyはこの場合でもブロックが必要になることに注意してください。

于 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 に答える