Giter VIP home page Giter VIP logo

codingstandards's Introduction

优化代码编写

个人总结的代码编写规范及一些注意的地方:

<style type="text/css" id="wiz_todo_style_id" wiz_link_version="01.00.09">.wiz-todo, .wiz-todo-img {width: 16px; height: 16px; cursor: default; padding: 0 10px 0 2px; vertical-align: -10%;-webkit-user-select: none;} .wiz-todo-label { display: inline-block; padding-top: 7px; padding-bottom: 6px; line-height: 1.5;} .wiz-todo-label-checked { color: #666;} .wiz-todo-label-unchecked {text-decoration: initial;} .wiz-todo-completed-info {padding-left: 44px; display: inline-block; } .wiz-todo-avatar { width:20px; height: 20px; vertical-align: -20%; margin-right:10px; border-radius: 2px;} .wiz-todo-account, .wiz-todo-dt { color: #666; }</style>

ios最佳实践

OSChina : http://git.oschina.net/DarkHorse1919/ios-good-practices-the-lastest-version

Github : https://github.com/KevinHM/ios-good-practices-the-lastest-version 

2 、 MVVM 架构之 ReactiveCocoa 详解: iOS 的函数响应型编程 

OSChina: http://git.oschina.net/DarkHorse1919/FunctionalReactiveProgrammingOniOS

Github : https://github.com/KevinHM/FunctionalReactiveProgrammingOniOS 

3 、禅与 Objective-C 编程艺术 (主要贡献者及校验者) 
Github : https://github.com/oa414/objc-zen-book-cn


1.代码编写顺序:先是life cycle(程序生命周期),然后是Delegate(代理)方法实现,然后是event response(事件响应),然后才是getters and setters(viewOrAttribute的getters和setters)

示例:

#pragma mark - liftCycle

- (void)viewDidLoad {

    [super viewDidLoad];

}


- (void)viewWillAppear:(BOOL)animated{

    [super viewWillAppear:animated];

}


#pragma mark -vc push pop

//view加载等代码


#pragma mark -searchData

//加载数据代码

#pragma mark - delegate

//代理委托代码


#pragma mark - eventRespone(eg: UITableViewDelegate & UITableViewDataSource Support

//事件响应对应代码


#pragma mark - other

//一些共用代码


#pragma mark - getters and setter

//view加载等代码


#pragma mark - Layout

//layout代码

(void)makeViewConstraints;





2.-viewDidLoad中,做为逻辑的入口,代码会变少但是变清晰,代码如下:

    [self.view addSubview:self.topView];

    [self.view addSubview:self.bgView];

    [self.view addSubview:self.tabView];


然后重写view的getter方法,包括View和frame这些都可以使用({...})语法使代码结构化层次化:

- (UIView *)topView{

    if (!_topView) {

        _topView = ({

            UIImageView *imgBg = [UIImageView new];

            imgBg.frame = CGRectMake(0, 0, 320, 49);

            imgBg;

        });

    }

    return _topView;

}


3.代理Delegate写到一块去,写好代理块注释:

如UITableViewDelegate的方法要写上:#pragma mark - UITableViewDelegate。这样可以方便阅读和查看代理 实现


4.event response(事件响应)专门开一个代码区域

所有button、gestureRecognizer的响应事件都放在这个区域里面,不要到处乱放。


5.关于private methods(私有方法),正常情况下ViewController里面不应该写

不是delegate方法的,不是event response方法的,不是life cycle方法的,就是private method了。对的,正常情况下ViewController里面一般是不会存在private methods的,这个private methods一般是用于日期换算、图片裁剪啥的这种小功能。这种小功能要么把它写成一个category,要么把他做成一个模块,哪怕这个模块只有一个函数也行。

ViewController基本上是大部分业务的载体,本身代码已经相当复杂,所以跟业务关联不大的东西能不放在ViewController里面就不要放。另外一点,这个private method的功能这时候只是你用得到,但是将来说不定别的地方也会用到,一开始就独立出来,有利于将来的代码复用。(引用之http://casatwy.com/iosying-yong-jia-gou-tan-viewceng-de-zu-zhi-he-diao-yong-fang-an.html


6.AOP划分服务逻辑(对于像日志、异常系统、统计这种服务型代码,尽可能使用aop进行逻辑划分,避免过多耦合和干预ViewController的职责)

下面使用oc runtimer机制实现最常用的统计代码集成,以友盟统计为例,页面pv是衡量浏览量的主要指标,基本是必须集成的统计之一,页面pv由页面的进入和页面的结束组成,那么这就需要我们在viewController的生命周期中的viewWillAppear和viewWillDisappear里进行代码集成:

普通使用示例:

页面进入统计:

  - (void)viewWillAppear:(BOOL)animated

    {

        [super viewWillAppear:animated];

        [MobClick beginLogPageView:@"PageOne"];

    }

页面退出统计:

- (void)viewWillDisappear:(BOOL)animated 

    {

        [super viewWillDisappear:animated];

        [MobClick endLogPageView:@"PageOne"];

    }   

这种类型的代码是要在所有的ViewController里都要写的,那么我们每个ViewController都写一遍?要是业务改变更换统计集成代码不需要友盟了,哪么不就每个页面都需要重新替换,哪得要猴年马月,聪明的你说不定想到,这还不简单,使用继承这不就解决这个问题了么,所有ViewController都继承统一的父ViewController,嗯,这个是有点道理,但是这就要求我们创建项目的时候需要创建好唯一的父类ViewController,并且所有的ViewController都要继承于它,对于项目已经进行到中期了,项目没有唯一的父类ViewController该怎么办呢?写一个?再把所有的ViewController翻出来继承于父ViewController,想想都要加班的节奏,讨厌死啦。而且项目中并不是所有ViewController类都继承于UIViewController,有可能继承UITableViewController,UIConllectionViewContrtoller,对于这类继承了其它扩展类型的ViewController,我们又该怎么办,fack重写一下吧,OMG...,想想都应该叫老板,给我来碗“泪流满面”,说回重点,对于以上所说的问题,我们可以使用oc 的runtimer机制完美解决。

oc runtimer可以参考:

http://www.cocoachina.com/ios/20150120/10958.html 

http://my.oschina.net/panyong/blog/298631

简单多说一下,什么是runtimer机制,说白了就是运行时机制,它的作用是可以动态注入代码,动态创建类,创建属性等等。专业人士称它为黑魔法。下面就以runtimer机制修改上面的代码:

1.创建一个UIViewController的category,并引入

#import <objc/runtime.h>


2.实现+(void)load方法,并在load方法实现方法注入,代码如下:


+ (void)load {

 static dispatch_once_t onceToken;  dispatch_once(&onceToken, ^{

     Class class = [self class]; 

     swizzleMethod(class, @selector(viewDidLoad), @selector(aop_viewDidLoad));

      swizzleMethod(class, @selector(viewDidAppear:), @selector(aop_viewDidAppear:));

      swizzleMethod(class, @selector(viewWillAppear:), @selector(aop_viewWillAppear:));

      swizzleMethod(class, @selector(viewWillDisappear:),@selector(aop_viewWillDisappear:));

     });

}


void swizzleMethod(Class class, SEL originalSelector, SEL swizzledSelector)   {

     Method originalMethod = class_getInstanceMethod(class, originalSelector);

     Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

   BOOL didAddMethod =    class_addMethod(class,originalSelector,method_getImplementation(swizzledMethod),

   method_getTypeEncoding(swizzledMethod));if (didAddMethod) {

   class_replaceMethod(class,swizzledSelector,method_getImplementation(originalMethod),

   method_getTypeEncoding(originalMethod));

   } else {

       method_exchangeImplementations(originalMethod, swizzledMethod);

    }

}


- (void)aop_viewDidAppear:(BOOL)animated {

[self aop_viewDidAppear:animated];

}


-(void)aop_viewWillAppear:(BOOL)animated {

[self aop_viewWillAppear:animated];

[MobClick beginLogPageView:NSStringFromClass([self class])];

}


-(void)aop_viewWillDisappear:(BOOL)animated {

[self aop_viewWillDisappear:animated];

[MobClick endLogPageView:NSStringFromClass([self class])];

}


- (void)aop_viewDidLoad {

   [self aop_viewDidLoad];

     if ([self isKindOfClass:[UINavigationController class]]) {

 }

}


上面代码出现了一个陌生的单词swizzleMethodswizzleMethod是利用 Runtime 特性把一个方法的实现与另一个方法的实现进行替换。

swizzleMethod是一个非常好用的特性,代码库,框架的封装常常可以看到它哦。


第三方对swizzleMethod的封装:

Aspects:https://github.com/steipete/Aspects

    http://www.ios122.com/2015/08/aspects/


AOP相应注入Deom:https://github.com/okcomp/AspectsDemo


swizzleMethod参考:

http://blog.csdn.net/yiyaaixuexi/article/details/9374411

http://blog.csdn.net/mangosnow/article/details/34908365


SEL(@selector)参考:

http://blog.csdn.net/fengsh998/article/details/8612969



7.Block代替delegate,尽量使用block,对于有大量的delegate方法才考虑使用protocol实现.

1.Block语法总结及示例如下:

        //1.普通代码块方式block

    returnType (^blockName)(parameterTypes) = ^returnType(parameters) {

        // block code

    };

    使用未例:

    int (^abc)(int a) = ^int(int a){

        return a+1;

    };

    int aa = abc(2);

    NSLog(@"%d",aa);



    //2.属性方式block

    @property (nonatomic, copy) returnType (^blockName)(parameterTypes);

    使用示例:

    1.定义属性

    @property (nonatomic,copy) int (^testblock)(NSString *);

         2.设置使用属性

         [self setTestblock:^int(NSString *a) {

        return 0;

    }];



    //3.方法参数block

    - (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName {

        // block code

    };

    使用示例1:

    1.无参数型定义及实现:

    - (void)testBlockFun:(void(^)())completion{

     NSLog(@"执行");

        if (completion) { 

           completion();

        }

    }

    2.无参数型block调用:

    [self testBlockFun:^{

        NSLog(@"回调结束");

    }];


    使用示例2:

        1.带参数型定义及实现:

        - (void)testBlockFun:(int (^)(int a,int b))complate{

        if (complate) {

            int c = complate(3,5);

            NSLog(@"c:%d",c);

        }

    }

    2.带参数型block调用:

    [self testBlockFun:^int(int a, int b) {

        return a+b;

    }];


    // 4.作为参数

    [someObject someMethodThatTakesABlock: ^returnType (parameters) {

        // block code

    }];

    使用示例:

    1.定义及实现

    - (void) testBlockFun:(void (^)(NSString *))complate{

        if (complate) {

            complate(@"success");

        }

    }

    2.调用

    [self testBlockFun:^(NSString *str) {

       NSLog(@"str:%@",str);

   }];


    // 5.使用 typedef 定义

   typedef returnType (^TypeName)(parameterTypes);


   TypeName blockName = ^(parameters) { 

   };

   使用示例:

   typedef void (^blockTestName)(NSString *);

   调用:

   [self setName:^(NSString *a){

   }];


2.Block修改值:使用__block可以在block内部修改外部变量的值。

    __block int someIncrementer = 0;

   [someObject someMethodThatTakesABlock:^{

         someIncrementer++;

   }];


3.Block循环引用,block会持有对象,block的对象也有block,会造成block的循环引用,解决方法:

    __weak typeof(self) weakSelf = self;//@weakify(self); 

    [self someMethodThatTakesABlock:^{

        [weakSelf action]; 

    }];


8.错误处理注意:

如下处理会有问题:

    NSError *error;

    [self trySomethingWithError:&error];

    if (error) {


    }

在成功的情况下,有些Apple的APIs记录垃圾值(garbage values)到错误参数(如果non-NULL),那么判断错误值会导致false负值和crash。


应该如下:

     NSError *error;

    if (![self trySomethingWithError:&error]) {

        // Handle Error

    }


Block weakSelf宏:

#define WS(weakSelf)  __weak __typeof(&*self)weakSelf = self;


9.方法命名注意:

方法使用小驼峰法命名, 一个规范的方法读起来应该像一句完整的话,读过之后便知函数

的作用。执行性的方法应该以动词开头,小写字母开头,返回性的方法应该以返回的内容

开头,但之前不要加get。

示例:

- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;

(instancetype)arrayWithArray:(NSArray *)array;


如果有参数,函数名应该作为第一个参数的提示信息,若有多个参数,在参数前也应该有

提示信息(一般不必加and)

 一些经典的操作应该使用约定的动词,如initWith,insert,remove,replace,add等等


设置属性时能用.符号的尽量使用.符号,这样可以让表达式更加的清晰明了,容易区分出是属性调用还是方法调用


10.枚举、通知统一管理


11.多个target管理项目版本(开发、正式)


12.单例:

+ (AccountManager *)sharedManager  

{  

        static AccountManager *instance = nil;  

        static dispatch_once_t predicate;  

        dispatch_once(&predicate, ^{  

                instance  = [[self alloc] init];   

        });  

    return instance;  

}  


13.打印运行方法所在的Vc及方法名

NSLog(@"%s",__func__);

14.参考额外文章 :

http://www.jianshu.com/p/3beb21d5def2

http://www.jianshu.com/p/06bab2058c53

请求缓存:

http://www.jianshu.com/p/fb5aaeac06ef



Parse源码浅析系列(一)---Parse的底层多线程处理思路:GCD高级用法

https://github.com/ChenYilong/ParseSourceCodeStudy/blob/master/01_Parse%E7%9A%84%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%A4%84%E7%90%86%E6%80%9D%E8%B7%AF/Parse%E7%9A%84%E5%BA%95%E5%B1%82%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%A4%84%E7%90%86%E6%80%9D%E8%B7%AF.md

 

###如有更好的建议请联系qq:1213423761

codingstandards's People

Contributors

shiyuan17 avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.