1 巧妙利用RunLoop来延迟加载图片 UITableView中可以借鉴
//利用CFRunLoopMode的特性,可以将图片的加载放到NSDefaultRunLoopMode的mode里,这样在滚动UITrackingRunLoopMode这个mode时不会被加载而影响到。
[myImageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"333"] afterDelay:0 inModes:@[NSDefaultRunLoopMode]];
2 总体来说卡顿的tableview可以使用:1 重用且记得清除视图 2 多线程 3 自定义Cell后将文字或图像渲染使用drawRect绘制到UIview或者CALayer上 且绘制时判断区域如CGRectIntersectsRect、CGRectIntersection或CGRectContainsRect判断是否需要绘制image和text,然后再调用绘制方法。
3 //NSOprationQueue 与 GCD 的区别
GCD是底层的C语言构成的API,而NSOperationQueue及相关对象是Objc的对象。在GCD中,在队列中执行的是由block构成的任务,这是一个轻量级的数据结构;而Operation作为一个对象,为我们提供了更多的选择;
1 在NSOperationQueue中,我们可以随时取消已经设定要准备执行的任务(当然,已经开始的任务就无法阻止了),而GCD没法停止已经加入queue的block(其实是有的,但需要许多复杂的代码);
2 NSOperation能够方便地设置依赖关系,我们可以让一个Operation依赖于另一个Operation,这样的话尽管两个Operation处于同一个并行队列中,但前者会直到后者执行完毕后再执行;
3 我们能将KVO应用在NSOperation中,可以监听一个Operation是否完成或取消,这样子能比GCD更加有效地掌控我们执行的后台任务;
4 在NSOperation中,我们能够设置NSOperation的priority优先级,能够使同一个并行队列中的任务区分先后地执行,而在GCD中,我们只能区分不同任务队列的优先级,如果要区分block任务的优先级,也需要大量的复杂代码;
5 我们能够对NSOperation进行继承,在这之上添加成员变量与成员方法,提高整个代码的复用度,这比简单地将block任务排入执行队列更有自由度,能够在其之上添加更多自定制的功能。
4 链表和数组的区别 二者都属于一种数据结构
从逻辑结构来看
1. 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费;数组可以根据下标直接存取。
2. 链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项,非常繁琐)链表必须根据next指针找到下一个元素
从物理内存存储来看
1. (静态)数组从栈中分配空间, 对于程序员方便快速,但是自由度小
2. 链表从堆中分配空间, 自由度大但是申请管理比较麻烦
从上面的比较可以看出,如果需要快速访问数据,很少或不插入和删除元素,就应该用数组;相反, 如果需要经常插入和删除元素就需要用链表数据结构了。
5 如果要25匹马中选出跑得最快的3匹,每次只有5匹马同时跑,最少要比赛几次?
7次
首先分成5组A,B,C,D,E,赛5场
得到a1,b1,c1,d1,e1,假设a1>b1>c1>d1>e1 (这里可以改变序号,但不改变次序)
推出a1为第一的马,d1,e1不可能是前三的马,所以d1,e1不用参加最后一场。
同时推理出可能是第二第三的马是:a2,a3,b1,b2,c1 ,(推理理由,有两匹以上比它快的就自动出局)
然后a2,a3,b1,b2,c1再赛一场,其中前二的马即是第二,第三的马。
6 不直接定义为某一个类的实例类方法 直接写比如 NSString* UCSTipswithCode(NSString* tipscode); 可以在外部直接全局调用 比较危险但可以达到全局效果
7 NSDecimalNumberHandler 处理四舍五入时用到
8 EGOCache 可作为单独的缓存类 像AFNetworking和SDWebImage不是已经有这些功能了吗?是的,不过AFNetworking和SDWebImage是http。我的项目用的是socket,所以我选择EGOCache来做缓存。EGOCache一个简单、线程安全的基于key-value的缓存框架,原生支持NSString、UI/NSImage、和NSData,也支持储存任何实现<NSCoding>协议的类,可以设定缓存过期时间,默认是1天。只提供了磁盘缓存,没有提供内存缓存.
9 SFHFKeychainUtils 和 KeychainItemWrapper 是基于KeyChain的封装直接可以存储用户名和密码信息 使用都非常简单 设置或去删除三个方法搞定
10 //删除本地的所有NSUserDefaults方法
//方法一
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
//方法二
NSUserDefaults * defs = [NSUserDefaults standardUserDefaults];
NSDictionary * dict = [defs dictionaryRepresentation];
for (id key in dict) {
[defs removeObjectForKey:key];
}
[defs synchronize];
11 tableView.tableFooterView=backgroundView; 可以替换当网络数据返回为空时当前显示的画面为此
12 uitextField.font.pointSize 即是当前输入框的文字大小
13 找当前界面中所有的输入框UITextField
- (NSArray *)responders{
NSArray *textInputs = EditableTextInputsInView([[UIApplication sharedApplication] keyWindow]);
return [textInputs sortedArrayUsingComparator:^NSComparisonResult(UIView *textInput1, UIView *textInput2) {
UIView *commonAncestorView = textInput1.superview;
while (commonAncestorView && ![textInput2 isDescendantOfView:commonAncestorView])
commonAncestorView = commonAncestorView.superview;
CGRect frame1 = [textInput1 convertRect:textInput1.bounds toView:commonAncestorView];
CGRect frame2 = [textInput2 convertRect:textInput2.bounds toView:commonAncestorView];
return [@(CGRectGetMinY(frame1)) compare:@(CGRectGetMinY(frame2))];
}];
}
- (void)selectLastResponder:(UIBarButtonItem*)sender{
NSArray *responders = self.responders;
NSArray *firstResponders = [responders filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(UIResponder *responder, NSDictionary *bindings) {
return [responder isFirstResponder];
}]];
UIResponder *firstResponder = [firstResponders lastObject];
NSInteger offset = -1;
NSInteger firstResponderIndex = [responders indexOfObject:firstResponder];
NSInteger adjacentResponderIndex = firstResponderIndex != NSNotFound ? firstResponderIndex + offset : NSNotFound;
UIResponder *adjacentResponder = nil;
if (adjacentResponderIndex >= 0 && adjacentResponderIndex < (NSInteger)[responders count]){
//可用
adjacentResponder = [responders objectAtIndex:adjacentResponderIndex];
[adjacentResponder becomeFirstResponder];
}else{
//不可用,循环
adjacentResponderIndex = [responders count] -1 ;
adjacentResponder = [responders objectAtIndex:adjacentResponderIndex];
[adjacentResponder becomeFirstResponder];
}
}
- (void)selectNextResponder:(UIBarButtonItem*)sender{
NSArray *responders = self.responders;
NSArray *firstResponders = [responders filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(UIResponder *responder, NSDictionary *bindings) {
return [responder isFirstResponder];
}]];
UIResponder *firstResponder = [firstResponders lastObject];
NSInteger offset = +1;
NSInteger firstResponderIndex = [responders indexOfObject:firstResponder];
NSInteger adjacentResponderIndex = firstResponderIndex != NSNotFound ? firstResponderIndex + offset : NSNotFound;
UIResponder *adjacentResponder = nil;
if (adjacentResponderIndex >= 0 && adjacentResponderIndex < (NSInteger)[responders count]){
adjacentResponder = [responders objectAtIndex:adjacentResponderIndex];
[adjacentResponder becomeFirstResponder];
}else{
adjacentResponderIndex = 0 ;
adjacentResponder = [responders objectAtIndex:adjacentResponderIndex];
[adjacentResponder becomeFirstResponder];
}
}
//返回所有文本框
static NSArray * EditableTextInputsInView(UIView *view)
{
NSMutableArray *textInputs = [NSMutableArray new];
for (UIView *subview in view.subviews)
{
BOOL isTextField = [subview isKindOfClass:[UITextField class]] && [(UITextField *)subview isEnabled] ;
BOOL isEditableTextView = [subview isKindOfClass:[UITextView class]] && [(UITextView *)subview isEditable] ;
if (isTextField || isEditableTextView)
[textInputs addObject:subview];
else
[textInputs addObjectsFromArray:EditableTextInputsInView(subview)];
}
return textInputs;
}
14 ios7以后是视差偏移效果 类似壁纸位移的酷炫
UIInterpolatingMotionEffect *horizontalEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
horizontalEffect.minimumRelativeValue = @(-10.0);
horizontalEffect.maximumRelativeValue = @( 10.0);
UIInterpolatingMotionEffect *verticalEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
verticalEffect.minimumRelativeValue = @(-10.0);
verticalEffect.maximumRelativeValue = @( 10.0);
UIMotionEffectGroup *motionEffectGroup = [[UIMotionEffectGroup alloc] init];
motionEffectGroup.motionEffects = @[horizontalEffect, verticalEffect];
[myUIView addMotionEffect:motionEffectGroup];
15 通过xcode 本身来判断系统的版本号NSFoundationVersionNumber_iOS_7_1
16 控件集合 @property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *buttonsTips;
17 uint64_t start = mach_absolute_time();
//做自己的调用和方法后前后能计算出所耗的时间 精确到纳秒级
uint64_t drawTime = mach_absolute_time() - start;
18 iOS 9 中的 ReplayKit框架 可供游戏玩家录制屏幕视频等功能
19 代码重构记得用Refactor
20 PassKit是ApplePay支付 StoreKit 是IPA内购
21 函数式编程总结
如果想再去调用别的方法,那么就需要返回一个对象;
如果想用()去执行,那么需要返回一个block;
如果想让返回的block再调用对象的方法,那么这个block就需要返回一个对象(即返回值为一个对象的block)。
22 HealthKit健康应用的框架
23 如果设置圆角尽量不要使用masksToBounds 使用UIGraphicsGetImageFromCurrentImageContext UIGraphicsBeginImageContextWithOptions获取一个圆形返回更好并插入到子视图
24 UIPrintInteractionController 以及 UIPrintInfo 对应 打印机AirPrint
25 LocalAuthentication 这个是使用iPhone的指纹密码解锁功能TouchID 包含生物技术的 LAContext 的context [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error] 判断是否支持 如果支持再 evaluatePolicy……… 后拿到回调error.code的类型分为LAErrorAuthenticationFailed LAErrorTouchIDLockout等等状态
26 UINavigationController *navigationController; // If this view controller has been pushed onto a navigation controller, return it. 所以假如你得UINavigationController push的是一个自定义的被UINavigationController包装后的UIviewController那么,即便你在这个封装的UINavigationController里重写push等方法还是可以获取当前的self.navigationController 因为只要被push过的UIviewController,而UINavigationController也是UIviewController的继承,当然就能获取到push它的那个NavigationController
27 ReactiveCocoa ReactNative 是完全不一样的框架 前者是信号函数式编程后者是利用js调用系统原生控件
28 UIApplicationDidEnterBackgroundNotification和UIApplicationWillEnterForegroundNotification 注册这些通知后可以接受应用的状态
29 //UDID被弃用,使用UUID来作为设备的唯一标识。获取到UUID后,如果用NSUserDefaults存储,当程序被卸载后重装时,再获得的UUID和之前就不同了。使用keychain存储可以保证程序卸载重装时,UUID不变。但当刷机或者升级系统后,UUID还是会改变的。但这仍是目前为止最佳的解决办法了,如果有更好的解决办法,欢迎留言。
30 直接在面板上查到的属性
IB_DESIGNABLE
@interface KaedeTextField : UITextField
@property (nonatomic,copy) IBInspectable NSString *tipstext;
@property (nonatomic) IBInspectable BOOL NotGetRespond;//是否不获取响应
31 storyboard遇到UITableView的控件 应该添加section控件
32 alertView出来后在VC中的self.view.window.rootVC 就是当前的NavigationVC 但此时用Application获取出来的RootViewController则是在Delegate中的那个
33 CGPointEqualToPoint 比较两个点
34 //【Dispatch】执行一次,延迟提交
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
});
//【Dispatch】重复执行
dispatch_queue_t mainQueue = dispatch_get_global_queue(0, 0);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, mainQueue);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW,1.0 * NSEC_PER_SEC, 1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
NSLog(@"start");
});
//开始
dispatch_resume(timer);
//取消
dispatch_source_set_cancel_handler(timer, ^{
NSLog(@"cancel");
});
35 const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝..编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率比宏定义要高