iOS杂记
- iOS拦截电话
-
CTCallCenter *callCenter = [[CTCallCenter alloc] init]; callCenter.callEventHandler = ^(CTCall* call) { if ([call.callState isEqualToString:CTCallStateDisconnected]) { NSLog(@"Call has been disconnected"); } else if ([call.callState isEqualToString:CTCallStateConnected]) { NSLog(@"Call has just been connected"); } else if([call.callState isEqualToString:CTCallStateIncoming]) { NSLog(@"Call is incoming"); } else if ([call.callState isEqualToString:CTCallStateDialing]) { NSLog(@"call is dialing"); } else { NSLog(@"Nothing is done"); } };
- 为什么UIKit不是线程安全的?
像UIKit这样大的框架上确保线程安全是一个重大的任务,会带来巨大的成本。改变非原子property为原子property只是所需要改变的一小部分。通常你想要一次改变多个property,然后才能看到更改的结果。对于这一点,Apple不得不暴露一个方法,像CoreData的performBlock:和同步的方法performBlockAndWait:。如果你考虑大多数调用UIKit类是有关配置(configuration),使他们线程安全更没有意义。
然而,即使调用不是关于配置(configuration)来共享内部状态,因此它们不是线程安全的。如果你已经写回到黑暗时代iOS3.2及以前的应用程序,你一定经历过当准备背景图像时使用NSString的drawInRect:withFont:随时崩溃。值得庆幸的是随着iOS4的到来,Apple提供了大部分绘图的方法和类,例如UIColor和UIFont在后台线程中的使用。
不幸的是,Apple的文档目前还缺乏有关线程安全的主题。他们建议只在主线程访问,甚至连绘画方法他们都不能保证线程安全。所以阅读iOS的版本说明总是一个好主意。
在大多数情况下,UIKit类只应该在程序的主线程使用。无论是从UIResponder派生的类,还是那些涉及以任何方式操作你的应用程序的用户界面。
解除分配问题
另一个在后台使用UIKit对象的风险是“解除分配问题”。Apple在TN2109里概括了这个问题,并提出了多种解决方案。这个问题是UI对象应该在主线程中释放,因为一部分对象有可能在dealloc中对视图层次结构进行更改。正如我们所知,这种对UIKit的调用需要发生在主线程上。
由于它常见于次线程,操作或块保留调用者,这很容易出错,并且很难找到并修复。这也是在AFNetworking中长期存在的一个bug,只是因为不是很多人知道这个问题,照例,显然它很罕见,并且很难重现崩溃。在异步块操作里一贯使用__weak和不访问ivars会有所帮助。
- iOS 通知观察者的被调函数不一定运行在主线程 http://itony.me/289.html
-------------------------------------------------------------------------------------------------------
- iOS AVFoundation 调用摄像头时 相机手动聚焦怎么写:
device.focusMode = AVCaptureFocusModeContinuousAutoFocus; - (void)focusWithMode:(AVCaptureFocusMode)focusMode exposeWithMode:(AVCaptureExposureMode)exposureMode atDevicePoint:(CGPoint)point monitorSubjectAreaChange:(BOOL)monitorSubjectAreaChange { dispatch_async(_sessionQueue, ^{ AVCaptureDevice *device = [_videoDeviceInput device]; NSError *error = nil; if ([device lockForConfiguration:&error]) { if ([device isFocusPointOfInterestSupported] && [device isFocusModeSupported:focusMode]) { [device setFocusMode:focusMode]; [device setFocusPointOfInterest:point]; } if ([device isExposurePointOfInterestSupported] && [device isExposureModeSupported:exposureMode]) { [device setExposureMode:exposureMode]; [device setExposurePointOfInterest:point]; } [device setSubjectAreaChangeMonitoringEnabled:monitorSubjectAreaChange]; [device unlockForConfiguration]; } }); } - (void)focusAndExposeTap:(UIGestureRecognizer *)gestureRecognizer { CGPoint touchPoint = [gestureRecognizer locationInView:_filterContainer]; float ox = touchPoint.x / CGRectGetWidth(_previewView.bounds); float oy = touchPoint.y / CGRectGetHeight(_previewView.bounds); [self focusWithMode:AVCaptureFocusModeAutoFocus exposeWithMode:AVCaptureExposureModeAutoExpose atDevicePoint:CGPointMake(ox, oy) monitorSubjectAreaChange:YES]; }
-------------------------------------------------------------------------------------------------------
- 构建对象多参数的解决方案:
http://www.cocoachina.com/ios/20150313/11328.html?from=singlemessage&isappinstalled=1
self.collectionView = [MGJFlowCollectionView collectionViewWithBuilder:^(MGJFlowCollectionViewBuilder *builder) { builder.scrollDirection = UICollectionViewScrollDirectionHorizontal; builder.minimumInteritemSpacing = 10; builder.minimumLineSpacing = 10; builder.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10); CGSize itemSize = CGSizeMake(81, 100); builder.itemSize = itemSize; builder.dataSource = @[@1,@2,@3,@4,@5,@6, @7,@8, @9, @10]; builder.cellBuilder = ^UIView *(NSNumber *number){ UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, itemSize.width, itemSize.height)]; view.backgroundColor = [UIColor mgj_random]; return view; }; }];