1、IOS中单例模式的使用及出现的问题
单例模式是在代码间共享数据而不需要手动传递参数的一种最有用的方法。关于单例和其他设计模式,请参考这本书:《Cocoa design pattern》
单例模式的具体实现,请参见博文http://blog.csdn.net/kmyhy/article/details/8715764
由于现在IOS7系统在生成工程时都是默认的ARC模式,所以在使用单例模式时,特别要注意ARC和非ARC的不同。
而我在使用单例模式传递全局变量时,发现:在OC类中能正常使用,但是如果和C++混合编程,即在C++类中使用OC编写的全局变量单例模式类时,会出现内存不良增长的问题,即每使用一下单例模式类的成员变量,内存都会增加一点,且一直不释放,还没找到原因,如果哪位大神知道,请分享下。
2、使用AudioQueueNewInput出现内存泄露的问题
在IOS7中使用Audio Queue进行录放音时,如果是使用OC类函数调用 Audio Queue的接口,就会遇到类型强制转换的问题。
比如在oc类中调用函数AudioQueueNewInput的方式
AudioQueueNewInput(&iRecordDescription,
MyInputBufferHandler,
(__bridge void*)self,
NULL,
NULL,
0,
&iReceiveQueue);
其中,self必须经过强制类型转换才能使用(__bridge void*)self,当然,类型转换在不同情况下有不同转换方式,其他可参见博文http://blog.sina.com.cn/s/blog_65a8ab5d0101c8k2.html
但是,这样编译虽然可以通过,但如果用Instruments软件进行检测时会发现存在内存泄露的问题。
后来,我改为在C++类中调用函数,才避免了这个问题。
AudioQueueNewInput(&iRecordDescription,
MyInputBufferHandler,
this,
NULL,
NULL,
0,
&iReceiveQueue);
3、IOS中区分iPhone/iPad的三种方法
1)使用 UI_USER_INTERFACE_IDIOM() 进行区分 (ios 3.2 >=) 无法区分iphone和ipod
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// <define your constants here>
} else {
// <define your constants here>
}
区分目前UI_USER_INTERFACE_IDIOM()有2个返回值
UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad //ipad
UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone //ipad
2)使用 UIDevice.model 进行区分 (ios 2.0 >=)
NSString *deviceType = [UIDevice currentDevice].model;
if([deviceType isEqualToString:@"iPhone"]) {
//iPhone
}
else if([deviceType isEqualToString:@"iPod touch"]) {
//iPod Touch
}
else {
//iPad
}
3)使用系统的一个函数sysctlbyname 来获取设备名称
- (NSString *) platformString
{
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *machine = malloc(size);
sysctlbyname("hw.machine", machine, &size, NULL, 0);
NSString *platform = [NSString stringWithUTF8String:machine];
free(machine);
if ([platform isEqualToString:@"iPhone1,1"]) return @"iPhone 1G";
if ([platform isEqualToString:@"iPhone1,2"]) return @"iPhone 3G";
if ([platform isEqualToString:@"iPhone2,1"]) return @"iPhone 3GS";
if ([platform isEqualToString:@"iPhone3,1"]) return @"iPhone 4";
if ([platform isEqualToString:@"iPhone3,3"]) return @"Verizon iPhone 4";
if ([platform isEqualToString:@"iPod1,1"]) return @"iPod Touch 1G";
if ([platform isEqualToString:@"iPod2,1"]) return @"iPod Touch 2G";
if ([platform isEqualToString:@"iPod3,1"]) return @"iPod Touch 3G";
if ([platform isEqualToString:@"iPod4,1"]) return @"iPod Touch 4G";
if ([platform isEqualToString:@"iPad1,1"]) return @"iPad";
if ([platform isEqualToString:@"iPad2,1"]) return @"iPad 2 (WiFi)";
if ([platform isEqualToString:@"iPad2,2"]) return @"iPad 2 (GSM)";
if ([platform isEqualToString:@"iPad2,3"]) return @"iPad 2 (CDMA)";
if ([platform isEqualToString:@"i386"]) return @"Simulator";
return @"";
}
4、IOS检测耳机插入/拔出的问题
我们使用的音乐播放器,比如酷我,在耳机从手机中拔出时,会停止播放。这个功能的实现,手机得能检测到耳机的拔出。
实际上,在IOS6以前都留出了接口来检测耳机的插入/拔出。
这个是通过监听AudioSession的RouteChange事件然后判断耳机状态实现的。实现步骤分为两步,首先注册监听函数,然后再监听函数中判断耳机状态。
注册监听函数:
AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange,
audioRouteChangeListenerCallback,
self);
然后就是监听函数audioRouteChangeListenerCallback的实现,详情请参见http://blog.csdn.net/onlyou930/article/details/7442596
当然,这是指在软件运行过程中去检测插入/拔出。我们通常还会需要在开机时去检测是否有耳机。其检测方法如下:
1. 检测声音输入设备
- (BOOL)hasMicphone {
return [[AVAudioSession sharedInstance] inputIsAvailable];}
2. 检测声音输出设备
- (BOOL)hasHeadset {
#if TARGET_IPHONE_SIMULATOR
#warning *** Simulator mode: audio session code works only on a device
return NO;
#else
CFStringRef route;
UInt32 propertySize = sizeof(CFStringRef);
AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &route);
if((route == NULL) || (CFStringGetLength(route) == 0)){
// Silent Mode
NSLog(@"AudioRoute: SILENT, do nothing!");
} else {
NSString* routeStr = (NSString*)route;
NSLog(@"AudioRoute: %@", routeStr);
/* Known values of route:
* "Headset"
* "Headphone"
* "Speaker"
* "SpeakerAndMicrophone"
* "HeadphonesAndMicrophone"
* "HeadsetInOut"
* "ReceiverAndMicrophone"
* "Lineout"
*/
NSRange headphoneRange = [routeStr rangeOfString : @"Headphone"];
NSRange headsetRange = [routeStr rangeOfString : @"Headset"];
if (headphoneRange.location != NSNotFound) {
return YES;
} else if(headsetRange.location != NSNotFound) {
return YES;
}
}
return NO;
#endif
}
但是,苹果在IOS7以后,很多接口都被封了,比如AudioSessionGetProperty,网上暂时还没找到替代的方法。而且,IOS7以后,苹果对于耳机的检测更为细致,分为带耳麦和不带耳麦,其检测方法貌似和耳麦的阻抗有关,比如有的耳机带耳麦,但耳麦的阻抗比较小的话,会认为没带,当要使用耳麦进行录音时,会默认为苹果设备自带的耳麦。