Objective-C编码规范补充

1、使用预编译指令#pragma mark组织代码

(1) 视图或控制器生命周期相关的代码

#pragma mark - Life Cycle

- (void)dealloc {}

- (instancetype)init {}

- (void)viewDidLoad {}

- (void)viewWillAppear:(BOOL)animated {}

- (void)viewDidAppear:(BOOL)animated {}

- (void)viewWillDisappear:(BOOL)animated {}

- (void)viewDidDisappear:(BOOL)animated {}

(2)通知相关的代码

#pragma mark - Notifications

- (void)addNotifications {}

- (void)removeNotifications {}

- (void)applicationDidEnterBackgroundNotification:(NSNotification *)notification {}

(3)事件响应相关代码

#pragma mark - Event Responses

- (void)actionForSettingButton:(UIButton *)button {}

- (void)actionForTapGestureRecognizer:(UITapGestureRecognizer *)tap {}

(4)协议相关的代码

#pragma mark - UIScrollViewDelegate

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {}

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {}

(5)私有的辅助方法

#pragma mark - Helper

- (NSString *)titleForItemAtIndex:(NSUInteger)index {}

(6)Setter与Getter方法

#pragma mark - Accessors

- (UIImageView *)imageView
{
    if (_imageView) { return _imageView; }
    _imageView = [UIImageView new];
    return _imageView;
}

2、注释

(1)头文件对外公开的属性、方法、变量、枚举、常量使用统一的注释(快捷键alt + command + /)

/**
 按钮上显示的标题
 */
@property (nonatomic, copy) NSString *title;


/**
 图片编辑完成回调方法

 @param vc 图片编辑控制器
 @param result 图片编辑结果
 */
- (void)photoEditViewController:(TuSDKICViewController *)vc didCompleteWithResult:(TuSDKResult *)result;

(2)实现文件中关键代码或需要特别说明的代码要添加注释

3、属性声明

属性修饰符书写顺序:原子性,读写权限,内存管理,别名。另外注意weak、copy、readonly修饰符的使用。

@property (nonatomic, weak) id<UIScrollViewDelegate> delegate;
@property (nonatomic, assign) NSUInterger selectedIndex;
@property (nonatomic, readonly) UIView *view;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) void (^completionHandler)();
@property (nonatomic, strong) NSArray<UIImageView *> *imageViews;

4、instancetype

对于明确返回类实例的方法,其返回类型应使用instancetype代替id类型。

5、命名

方法命名时谨慎使用前缀alloc/init/copy/mutableCopy/new/set/get

编译器约定,对于alloc/init/copy/mutableCopy/new这几个家族的方法,声明后面默认加NS_RETURNS_RETAINED标识;而其他方法默认添加NS_RETURNS_NOT_RETAINED标识。

系统自动生成的属性设置方法是以set开头的,另外可能对KVC查找键名称会有影响。

根据苹果推荐的命名规范,一般避免使用get作为方法名前缀。

6、使用预编译指令忽略特定的警告

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"

//确定这里不会发生内存泄漏时,使用预编译指令忽略警告
[myObj performSelector:mySelector withObject:name];

#pragma clang diagnostic pop

7、注意block的循环引用

(1)block本身没有被作为属性引用的情况

[UIView animateWithDuration:0.25 animations:^{
    self.view.alpha = 0;
}];

NSInteger (^setIndexBlock)(NSInteger, NSInteger) = ^(NSInteger a, NSInteger b) {
    self.index = a + b;
    return a + b;
};
setIndexBlock(1, 2);

(2)block被作为属性引用的情况1

比如block只会在主线程执行,或block内部只有一条语句:

__weak typeof(self) weakSelf = self;
backButton.clickBlock = ^{
    [weakSelf popViewControllerAnimated:YES];
};

(3)block被作为属性引用的情况2

比如block同时被多个对象引用,并且在子线程执行,则有可能在block执行过程中weakSelf变成nil:

__weak typeof(self) weakSelf = self;
myObj.myBlock =  ^{
    __strong typeof(self) strongSelf = weakSelf;
    if (strongSelf)
    {
      [strongSelf doSomething];
      [strongSelf doSomethingElse];
    }
};

(4)主动解除循环引用

对于大部分情况,通过弱引用可以避免发生循环引用。但有些场合由于需求不能使用弱引用,即要求被引用的对象在block执行完成前不允许被释放,这种情况只要能保证block一定会被执行到,则可以在block内部主动解除循环引用。

self.myBlock = ^{
    NSLog(@"%@", self);
    self.myBlock = nil;
};

(5)其他

两个常用的宏定义:

#define weakify(o) __weak typeof(o) weakObj = o;
#define strongify(o) __strong typeof(o) strongObj = o;

weakify(self)
self.myBlock = ^{
    NSLog(@"%@", weakObj);
    strongify(weakObj)
    NSLog(@"%@", strongObj);
};

8、避免if语句多层嵌套

// 不推荐写法
if (condition1)
{
    if (condition2)
    {
        if (condition3)
        {
            //doSomething
        }
    }
}

// 推荐写法  
if (!condition1) { return; }
    
if (!condition2) { return; }
    
if (!condition3) { return; }
    
//doSomething

9、工程目录组织结构

一般工程目录主要结构:

  • MyProject:项目代码
  • MyProjectTests:单元测试代码
  • Frameworks:系统框架
  • Pods:第三方框架

项目代码目录MyProject:

  • Main

包括main文件、AppDelegate、定制的ViewController基类、TabBarController等整个应用结构相关,与具体功能无关的代码文件。

  • Common

放置应用中全局功能相关的代码文件,比如启动闪屏、登录、帐号系统、消息推送等。

  • Module1..n

通常按照TabBar上功能模块划分的一个模块。

  • Categories

放置所有的分类。

  • Utilities

放置工具类,比如网络工具、数据库工具、缓存管理工具等。

  • Venders

放置所有第三方库文件。

  • Resources

放置全局的资源类文件,比如plist文件、图片资源、视频音频文件、pch文件、JSON文件等。

每个功能模块下,比如Module1,可以根据不同子功能建立不同的子目录。目录中的文件包括该功能相关的全部文件,不包括一些全局或公共的文件,目录内不再划分view/viewController/model。目的是将代码尽量按照功能进行组织,而不是按照类型。另外,工程中的group应与实际目录一一对应。

工程目录结构示例
功能模块子目录示例

参考资料:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容