那些年,我们走过的零碎之路!---- iOS 工作笔记(1)
2016-05-25 09:47
357 查看
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常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率比宏定义要高
//利用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常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率比宏定义要高
相关文章推荐
- iOS9强制横屏
- iOS标准时间与时间戳相互转换
- iOS 设置启动页 不显示问题解决
- 别再为了iOS新系统设备而重新安装一个新版Xcode了.其实我们可以添加版本支持
- 【审核】检查iOS项目中是否使用了IDFA
- 【审核】检查iOS项目中是否使用了IDFA
- iOS上架被拒原因
- 【代码笔记】iOS-使图片两边不拉伸,中间拉伸
- 【代码笔记】iOS-使图片两边不拉伸,中间拉伸
- iOS开发浮点数问题
- iOS cookies
- iOS cookie
- iOS之CoreImage图像处理框架
- iOS开发中的错误整理,AFN框架和MJRefresh框架搭配应该注意的问题
- iOS开发小技巧--iOS8之后的cell自动计算高度
- 偏好设置存储
- iOS开发小技巧--学会包装控件(有些view的位置由于代码或系统原因,位置或者尺寸不容易修改或者容易受外界影响)
- [实践]iOS 单元测试(二)实战经验
- iOS通过URL调用第三方地图进行导航
- 在iOS上实现一个简单的日历控件