我是目标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/
答案 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];
...等......
不是说你做的是错的,只是非典型的。上面的模式清楚地表明了哪些类可以作为特定的委托,一个方法实现搜索稍后会揭示谁实现了哪些方法。