您的位置:首页 > 移动开发 > IOS开发

那些年,我们走过的零碎之路!---- 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常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率比宏定义要高
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: