那些年,我们走过的零碎之路!---- iOS 工作笔记(1)

1 巧妙利用RunLoop来延迟加载图片 UITableView中可以借鉴

   //利用CFRunLoopMode的特性,可以将图片的加载放到NSDefaultRunLoopModemode里,这样在滚动UITrackingRunLoopMode这个mode时不会被加载而影响到。

 [myImageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"333"] afterDelay:0 inModes:@[NSDefaultRunLoopMode]];


2 总体来说卡顿的tableview可以使用:1 重用且记得清除视图 2 多线程 3 自定义Cell后将文字或图像渲染使用drawRect绘制到UIview或者CALayer上  且绘制时判断区域如CGRectIntersectsRectCGRectIntersectionCGRectContainsRect判断是否需要绘制imagetext,然后再调用绘制方法。


3 //NSOprationQueue GCD 的区别

    

    GCD是底层的C语言构成的API,而NSOperationQueue及相关对象是Objc的对象。在GCD中,在队列中执行的是由block构成的任务,这是一个轻量级的数据结构;而Operation作为一个对象,为我们提供了更多的选择;

    1 NSOperationQueue中,我们可以随时取消已经设定要准备执行的任务(当然,已经开始的任务就无法阻止了),而GCD没法停止已经加入queueblock(其实是有的,但需要许多复杂的代码)

    2 NSOperation能够方便地设置依赖关系,我们可以让一个Operation依赖于另一个Operation,这样的话尽管两个Operation处于同一个并行队列中,但前者会直到后者执行完毕后再执行;

    3 我们能将KVO应用在NSOperation中,可以监听一个Operation是否完成或取消,这样子能比GCD更加有效地掌控我们执行的后台任务;

    4 NSOperation中,我们能够设置NSOperationpriority优先级,能够使同一个并行队列中的任务区分先后地执行,而在GCD中,我们只能区分不同任务队列的优先级,如果要区分block任务的优先级,也需要大量的复杂代码;

    5 我们能够对NSOperation进行继承,在这之上添加成员变量与成员方法,提高整个代码的复用度,这比简单地将block任务排入执行队列更有自由度,能够在其之上添加更多自定制的功能。


4  链表和数组的区别  二者都属于一种数据结构

    从逻辑结构来看

    1. 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费;数组可以根据下标直接存取。

    2. 链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项,非常繁琐)链表必须根据next指针找到下一个元素

    从物理内存存储来看

    1. (静态)数组从栈中分配空间, 对于程序员方便快速,但是自由度小

    2. 链表从堆中分配空间, 自由度大但是申请管理比较麻烦

    

    从上面的比较可以看出,如果需要快速访问数据,很少或不插入和删除元素,就应该用数组;相反, 如果需要经常插入和删除元素就需要用链表数据结构了。


5 如果要25匹马中选出跑得最快的3匹,每次只有5匹马同时跑,最少要比赛几次?

    7

    首先分成5A,B,C,D,E,赛5

    得到a1b1c1d1e1,假设a1>b1>c1>d1>e1 (这里可以改变序号,但不改变次序)

    推出a1为第一的马,d1e1不可能是前三的马,所以d1e1不用参加最后一场。

    同时推理出可能是第二第三的马是:a2,a3,b1,b2,c1 ,(推理理由,有两匹以上比它快的就自动出局)

    然后a2,a3,b1,b2,c1再赛一场,其中前二的马即是第二,第三的马。


6 不直接定义为某一个类的实例类方法 直接写比如 NSString* UCSTipswithCode(NSString* tipscode); 可以在外部直接全局调用 比较危险但可以达到全局效果


7 NSDecimalNumberHandler 处理四舍五入时用到


8 EGOCache 可作为单独的缓存类 像AFNetworkingSDWebImage不是已经有这些功能了吗?是的,不过AFNetworkingSDWebImagehttp。我的项目用的是socket,所以我选择EGOCache来做缓存。EGOCache一个简单、线程安全的基于key-value的缓存框架,原生支持NSStringUI/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  PassKitApplePay支付         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  UIApplicationDidEnterBackgroundNotificationUIApplicationWillEnterForegroundNotification 注册这些通知后可以接受应用的状态


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常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率比宏定义要高


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值