0

我是 Objective c 的新手(从 .NET 开发到 iPhone)。好吧,现在我有一个简单的问题要问有 iPhone 开发经验的人。我正在编写一个静态库,它使用 audiotoolbox 对一些音频事件做出反应。我的标题看起来像:

@interface ccreaderlib : NSObject {
    id __unsafe_unretained delegate;
    SEL _DevicePluggedEvent;
    SEL _DeviceUnpluggedEvent;

}

@property (nonatomic, assign) id delegate;
@property (nonatomic, assign) SEL onDevicePlugged;
@property (nonatomic, assign) SEL onDeviceUnplugged;


- (id)init;
- (void)startMonitor;
- (void)stopMonitor;


@end

现在在 UIViewController 我这样做:

_lib = [[ccreaderlib alloc] init];
    _lib.delegate = self;
    _lib.onDevicePlugged = @selector(OnDevicePluggedIn);
    _lib.onDeviceUnplugged = @selector(OnDeviceUnplugged);
[_lib startMonitor];

我的想法是从我的静态库中调用 UIViewController 的选择器。我怎样才能做到这一点。目前我正在尝试以这种方式执行此操作:

void audioRouteChangeListenerCallback (
                                       void                      *inUserData,
                                       AudioSessionPropertyID    inPropertyID,
                                       UInt32                    inPropertyValueSize,
                                       const void                *inPropertyValue) 
{
    if (inPropertyID != kAudioSessionProperty_AudioRouteChange) return;

CFDictionaryRef routeChangeDictionary = inPropertyValue;
CFNumberRef routeChangeReasonRef =
CFDictionaryGetValue ( routeChangeDictionary, CFSTR (kAudioSession_AudioRouteChangeKey_Reason));
SInt32 routeChangeReason;
CFNumberGetValue (
                  routeChangeReasonRef,
                  kCFNumberSInt32Type,
                  &routeChangeReason);

CFStringRef oldRouteRef =
CFDictionaryGetValue (
                      routeChangeDictionary,
                      CFSTR (kAudioSession_AudioRouteChangeKey_OldRoute));
NSString *oldRouteString = (__bridge NSString *)oldRouteRef;
ccreaderlib *self = (__bridge id)inUserData;
id reactClass = [self delegate];
if (routeChangeReason == kAudioSessionRouteChangeReason_NewDeviceAvailable)
{
    if ([oldRouteString isEqualToString:@"Speaker"])
    {
        [reactClass performSelector:@selector(onDevicePlugged)];
        self.bIsReaderPlugged = YES;
    }


}
if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) {
    if ([oldRouteString isEqualToString:@"Headphone"]){
        [reactClass performSelector:@selector(onDeviceUnplugged)];
        self.bIsReaderPlugged = NO;
    }
}

}

但通过这种方式,我得到了 SIGABRT。请帮助我,已经花了 3 天时间试图解决这个问题。

***更新:自己找到答案。将我的 c 回调函数更改为这样:

if (routeChangeReason == kAudioSessionRouteChangeReason_NewDeviceAvailable)
{
    if ([oldRouteString isEqualToString:@"Speaker"])
    {
        if([self.delegate respondsToSelector:self.onDevicePlugged])
            [self.delegate performSelector:self.onDevicePlugged];
        self.bIsReaderPlugged = YES;
    }


}
if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) {
    if ([oldRouteString isEqualToString:@"Headphone"]){
        if([self.delegate respondsToSelector:self.onDeviceUnplugged])
            [self.delegate performSelector:self.onDeviceUnplugged];
        self.bIsReaderPlugged = NO;
    }
}

感谢http://brandontreb.com/objective-c-programming-tutorial-creating-a-twitter-client-part-1/

4

2 回答 2

1

您确定拼写正确吗?在一种情况下,它在另一种情况下显示为大写(第一个“o”)。

一开始你应该在课堂上做的是验证委托确实响应了选择器:

BOOL [delegate repondsToSelector:your_selector_variable];
BOOL [delegate respondsToSelector:@selector(TheActualSelector)]; // don't forget trailing ':' if it takes an arg

我会在开发过程中断言这些,因为如果你没有得到这个正确的,没有理由继续,

于 2012-07-21T12:32:09.583 回答
1

这是一种非常非典型的委派模式。通常,您会声明一个协议:

@protocol(DevicePlugDelegateP)
- (void)pluggedInDevice:(Device*)aDevice;
- (void)unpluggedDevice:(Device*)aDevice;
@end

然后像这样声明你的代表:

__weak NSObject<DevicePlugDelegateP>* delegate;

然后检查选择器响应并调用它(如果存在):

if ([delegate respondsToSelector:@selector(pluggedInDevice:)])
    [delegate pluggedInDevice:aDevice];

... ETC ...

并不是说您所做的事情是错误的,只是不典型。上述模式非常清楚哪些类可以充当该特定委托,并且稍后通过方法实现搜索揭示谁实现了哪些方法。

于 2012-07-21T18:21:33.203 回答