1、UITextField 和 UITextView 在 iOS7 下不能重写 dealloc 方法
在 iOS7 的情况下,如果在 Category 重写了 UITextField 或 UITextView 就会发生莫名其妙的崩溃问题。
得到崩溃的调用栈如下:
可以看出,系统发出了一个通知,NSNotification,然后 Runloop 往 Observer 发送回调,然后 UITextSelectionView 执行 textSelectionViewActivated 的时候崩溃了。
很明显在 iOS7 的情况下,iOS 系统默认会在 UITextField 和 UITextView 的 dealloc 方法下去释放一些通知方法,减少 Observer。所以上面我重写了 dealloc 方法,在 iOS7 下不会去释放通知,导致 Runloop 发送了 通知方法的时候找不到对象,从而野指针崩溃。
iOS系统使用第三方键盘收到三次 UIKeyboardWillShowNotification 通知
使用搜狗键盘,确实引起了不必要的麻烦,哎,但是 UIKeyboardWillHideNotification 却只会出现一次,Lucky。
解决方法:
NSDictionary* dict = [aNotification userInfo];
CGRect endKeyboardFrame = [[dict objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect beginKeyboardFrame = [[dict objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
/**
abson issu1: iOS使用第三方键盘的情况下,收到三次键盘通知,傻B iOS 系统
*/
if (isShowKeyBoard ) {
if (false == (fitBeginKeyBoardFrame.size.height > 0 && fitBeginKeyBoardFrame.origin.y - fitEndKeyBoardFrame.origin.y)) {
return;
}
}
iOS7的情况下,如果键盘还在显示的时候,旋转屏幕,系统会分别很快的发出 UIKeyboardWillHideNotification、UIKeyboardWillShowNotification 这两个通知。
使用键盘的时候注意旋转屏幕出现的这个恶心bug,如果不少心在 UIKeyboardWillHideNotification 的时候做动画,并在动画结束时执行某些动做,例如如下:
那么就会有一个问题,因为系统很快就发出了 UIKeyboardWillShowNotification 这个通知,但是上图的 manageViewPositionForKeyBoard:
这个方法却被 0.25秒后执行了,而界面却没有发生变化,从而导致数据错乱的问题。
解决方法:加上一个属性判断动画是否执行中,如果 UIKeyboardWillShowNotification 引发的动画在执行中,那么,即使 0.25 秒后也不能让他执行 completion:
这个 block。
iOS7 下两次录音会导致 record 方法返回 false
_audioRecorder = [[ AVAudioRecorder alloc] initWithURL:url settings:recordSettings error:&error];
_audioRecorder.delegate = self;
if ([_audioRecorder prepareToRecord] == YES){
sleep(0);
BOOL result = [_audioRecorder record];
_isRecording = result;
}
如果上面代码不添加 sleep(0)
, 就会导致 iOS7 [_audioRecorder record]
第二次创建的时候返回false。
sleep(0)
的作用:
Sleep(n)的作用是让当前线程睡眠n毫秒,以便执行其他线程,如果没有其他线程,那睡眠n毫秒后,继续执行。
而如果n=0,Sleep(0)
是指CPU交出当前线程的执行权,让CPU去执行其他线程。也就是放弃当前线程的时间片,转而执行其他线程。
一般来说,如果当前线程比较耗时比较占CPU资源,可以在结尾处加上Sleep(0)
, 这样效率会得到大大的提高。
另外,还可以用这种方法来保证线程同步,线城池工作时,主线程使用Sleep(0)
来等待线程池里所有的线程都完成运行。当线程池线程非常多的时候,这种方法确实是一种非常有效的节省 cpu 的方式,因为它节省了在线程里使用内核来进行同步的开销。
对比上面:
由于 [_audioRecorder prepareToRecord]
为给录音分配资源的api,包括内部线程池分配资源等,所以,加上 Sleep(0)
目的在于等待其线程池资源分配成功。
iOS 的文件路径保存数据库不可保存全路径
[[NSUserDefaults standardUserDefaults] setObject:filePath forKey:SocialAudioDataBase];
上面这句话中,如果 filePath 为 /var/mobile/Containers/Data/Application/A07505E5-9A3B-4CF2-B424-738294B1589F/Documents/94538510998/audio/94538510998/3351b914c4c937134c0f57efbc2dcb1b.wav
这样的全路径,下次取出 filePath 的时候,使用
bool result = [[NSFileManager defaultManager] fileExistsAtPath:audioPath]
result
会返回false。因为每次应用运行的 Application/A07505E5-9A3B-4CF2-B424-738294B1589F
这个路径都在改变。所以保存路径不能保存全路径,只能保存 Documents
文件夹后的部分路径,下次使用的时候,再使用
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *documentsFilePath = [paths lastObject];
NSString* fullPath = [documentsFilePath stringByAppendingPathComponent:savePath];
这样去拼接得到全路径路径。
未完待续....