iPhone调用另一个类的选择器

时间:2012-07-21 10:19:05

标签: iphone objective-c

我是目标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/

2 个答案:

答案 0 :(得分:1)

你确定你的拼写是正确的 - 在一种情况下,它看起来大写在另一种情况下(首先是'o')。

在课程中你应该做的一切,就是验证委托实际上是否应该回到选择器:

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

我会在开发期间断言这些,如果你没有得到正确的话,没有理由继续,

答案 1 :(得分:1)

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

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

然后声明你的代表:

__weak NSObject<DevicePlugDelegateP>* delegate;

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

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

...等......

不是说你做的是错的,只是非典型的。上面的模式清楚地表明了哪些类可以作为特定的委托,一个方法实现搜索稍后会揭示谁实现了哪些方法。