pod私有化,在组件中包含*.xcassets资源时需要做什么

在百度上搜索了上百条信息,我是真的要吐槽一下,真的搜不到呀,下面的文章记录一下,以防以后忘记了!

这里只是针对这个问题做一个解释,如有问题,请留下宝贵意见:

1、需要在*.podspec文件中加入如下代码

1
2
3
4

s.resource_bundle = {
'AAA' => ['目录/Assets/*.xcassets'] #AAA为生成boudle的名称,随便起,记下,下面要用
}

2、在需要引入*.xcassets中的图片资源时,调用如下方法:

1
2
3
4
5
6
7
8
9
10
11
12

UIImage *img = [self getImageWithBoudleName:@"AAA" imgName:@"图片名称"];

- (UIImage *)getImageWithBoudleName:(NSString *)boudleName imgName:(NSString *)imgName {
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSURL *url = [bundle URLForResource:boudleName withExtension:@"bundle"];
NSBundle *targetBundle = [NSBundle bundleWithURL:url];
UIImage *image = [UIImage imageNamed:imgName
inBundle:targetBundle
compatibleWithTraitCollection:nil];
return image;
}

特别鸣谢

iPad全部机型
ipad 1-6 (9.7)
ipad mini 1-4(7.9)
ipad Air 1-2 (9.7)
ipad Pro 1-3 (12.9)
ipad Pro (9.7)
ipad Pro (10.5)
ipad Pro (11)
需要适配的机型
ipad 5-6 (9.7)
ipad mini 4(7.9)
ipad Air 2 (9.7)
ipad Pro 1-3 (12.9)
ipad Pro (9.7)
ipad Pro (10.5)
ipad Pro (11)
机型识别:https://support.apple.com/zh-cn/HT201471#ipadair

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
iOS-Component/
|- readme.md (说明)
|- 工程/
| |- Config/ (基础配置文件)
| |- Modules/ (功能模块)
| | |- Home/
| | | |- Connector/ (接入点)
| | | |- Model/ (内部数据模型)
| | | |- Service/ (该组件的网络接口请求以及网络回调回来的数据转Model工作)
| | | |- UI/ (页面存放位置)
| | | |- / ()
| | |- Mine/
| | |- .../
| | |- Login/
| |- Manager/ (管理模块)
| |- CommonParty/ (基础内部通用文件,如添加或修改,需经过论证)
| | |-
| | |-
| | |-
| |- ThirdParty/ (基础外来三方文件,如添加或修改,需经过论证)
| | |-
| | |-
| | |-
| |- Define/ (全局宏定义)
| |- Base/ (基础文件,如修改,需经过论证)
| | |- Frame/ (布局)
| | | |- UIViewAdditions/
| | |- DataBase/ (数据库)
| | |- HttpReq/ (网络请求)
| | |- Root/ (基类)
| | |- PostModel/ (基础Model)
| | |- Utils/ (工具类)
| | |-
| | |-
| | |-
| |- Assets.xcassets/ (图片)
| |- Resource/ (资源文件夹)
| |- Supporting Files
|
|
| |-Pod/ (Pod导入文件列表)
| | |- AFNetWroking
| | |- SDWebImage
| | |- FMDB
| | |- Reachability
| | |- MJRefresh
| | |- MJExtension
| | |- MBProgressHUD
| | |- NullSafe
| | |- IQKeyboardManager
| | |- FSCalendar
| | |- pop
| | |-
| | |-
| | |-
|
|
|
|
|
|
|

面试心得

  • 什么是arc?(arc是为了解决什么问题诞生的?)
    现在有不少程序员是直接从arc上手的,从没接触过mrc,对arc的理解仅仅停留在apple帮助管理内存的层面。这个问题真正想了解的是对内存管理的理解,retain release虽然不用写了,但arc下还是会有内存泄漏野指针crash的bug存在。如果能从retain count这种内存管理策略的角度去阐述arc诞生的意义就算答对了。如果还能扯下其他类型的策略,比如java里的mark and sweep,那就加分点赞。
    请解释以下keywords的区别: assign vs weak, block vs weak
    这道题属于基础语法题,可以网上搜到答案。不过真有不少同学不知道weak在对象释放后会置为nil。__block关键字的理解稍微难点,因为在arc和mrc下含义(对retain count的影响)完全不同。理解了这几个关键字就能应付使用block时引入retain cycle的风险了。这题还在内存管理的范畴之内。
  • 使用atomic一定是线程安全的吗?
    看这题的问法不用想答案肯定是NO。有些人说不出所以然,有些人知道通过property的方式使用才能保证安全,还有人知道这个用来做多线程安全会有性能损耗,更有出色的候选人能谈atomic,synchronized,NSLock,pthread mutex,OSSpinLock的差别。好奇宝宝点我。
    描述一个你遇到过的retain cycle例子。(别撒谎,你肯定遇到过)
    说没遇到过的我很难相信你有过成熟项目的经历。这题答不出了会扣很多很多分。用过block,写过delegate的肯定都踩过坑。
  • +(void)load; +(void)initialize; 有什么用处?
    这题属于runtime范畴,我遇到过能说出对runtime的理解却不知道这两个方法的候选人。所以答不出来也没关系,这属于细节知识点,是加分项,能答出两个message各在什么阶段接收就可以了。
    为什么其他语言里叫函数调用, objective c里则是给对象发消息(或者谈下对runtime的理解)
    这题考查的是objective c这门语言的dynamic特性,需要对比c++这类传统静态方法调用才能理解。最好能说出一个对象收到message之后的完整的流程是如何的。对runtime有完整理解的候选人还能说出oc的对象模型。
  • 什么是method swizzling?
    说了解runtime但没听过method swizzling是骗人的。这题很容易搜到答案。定位一些疑难杂症bug,hack老项目实现,阅读第三方源码都有机会接触到这个概念。
  • UIView和CALayer是什么关系 7
    能答出UIView是CALayer的delegate就及格了,能说出UIView主要处理事件,CALayer负责绘制就更好,再聊下二者在使用过程中对动画流畅性影响的注意点就superb。UI流畅性是个大话题,推荐看下这两篇文章。中餐,西餐。
  • 如何高性能的给UIImageView加个圆角?(不准说layer.cornerRadius!)5
    这题讨论的最多,还有说美工切图就搞定的。答主在项目里做过圆角头像的处理,里面的坑还真不少。cornerRadius会导致offscreen drawing有性能问题,美工切图无法适用有背景图的场景,即使加上shouldRasterize也有cache实效问题。正确的做法是切换到工作线程利用CoreGraphic API生成一个offscreen UIImage,再切换到main thread赋值给UIImageView。这里还涉及到UIImageView复用,圆角头像cache缓存(不能每次都去绘制),新旧头像替换等等逻辑。还有其他的实现方式,但思路离不开工作线程与主线程切换。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- (UIImage*)circleImage {
UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0);
CGContextRefctx = UIGraphicsGetCurrentContext();
CGRectrect = CGRectMake(0, 0, self.size.width,self.size.height);
CGContextAddEllipseInRect(ctx, rect);
CGContextClip(ctx);
[selfdrawInRect:rect];
UIImage*image =UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
returnimage;
}


UIImageView*imageView = [[UIImageViewalloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
imageView.center = CGPointMake(200,300);
UIImage*anotherImage = [UIImageimageNamed:@"image"];
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0); [[UIBezierPathbezierPathWithRoundedRect:imageView.bounds cornerRadius:50] addClip];
[anotherImage drawInRect:imageView.bounds];
imageView.image =UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.view addSubview:imageView];
  • UITableView优化方法
    cell重用,异步执行耗时操作这种就不用提了,这都是大家能想到的,我们可以说一点其他的。
    1:减少视图层次;
    2:正确使用api,比如设置rowHeight而不去取dataSource;
    3:减少离屏渲染;
    圆角图片
    阴影
    …
    4:设置视图不透明减少渲染代价,如果有透明度则会根据多个视图才知道一个像素点显示什么颜色;
    5:RunLoop空闲计算cell高度并缓存;
    6:利用RunLoop的mode在滚动时不执行耗时操作。
  • 如何用GCD同步若干个异步调用?(如根据若干个url异步加载多张图片,然后在都下载完成后合成一张整图)
  • dispatch_barrier_async(栅栏函数)的作用是什么?
    1.在它前面的任务执行结束后它才执行,它后面的任务要等它执行完成后才会开始执行。
    2.避免数据竞争
  • 以下代码运行结果如何?
1
2
3
4
5
6
7
8
- (void)viewDidLoad {
[superviewDidLoad];
NSLog(@"1");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"2");
});
NSLog(@"3");
}
  • 使用drawRect有什么影响?(这个可深可浅,你至少得用过。。)
    不少同学都用过drawRect或者看别人用过,但不知道这个api存在的含义。这不仅仅是另一种做UI的方式。drawRect会利用CPU生成offscreen bitmap,从而减轻GPU的绘制压力,用这种方式最UI可以将动画流畅性优化到极致,但缺点是绘制api复杂,offscreen cache增加内存开销。UI动画流畅性的优化主要平衡CPU和GPU的工作压力。推荐一篇文章:西餐
    ASIHttpRequest或者SDWebImage里面给UIImageView加载图片的逻辑是什么样的?(把UIImageView放到UITableViewCell里面问更赞)
    很多同学没有读源码的习惯,别人的轮子拿来只是用用却不知道真正的营养都在源代码里面。这两个经典的framework代码并不复杂,很值得一读。能对一个UIImageView怎么通过url展示一张图片有完整的理解。涉及到的知识点也非常多,UITableViewCell的复用,memory cache, disk cache, 多线程切换,甚至http协议本身都需要有一定的涉及。
    麻烦你设计个简单的图片内存缓存器(移除策略是一定要说的)
    内存缓存是个通用话题,每个平台都会涉及到。cache算法会影响到整个app的表现。候选人最好能谈下自己都了解哪些cache策略及各自的特点。常见的有FIFO,LRU,LRU-2,2Q等等。由于NSCache的缓存策略不透明,一些app开发者会选择自己做一套cache机制,其实并不难。
  • 讲讲你用Instrument优化动画性能的经历吧(别问我什么是Instrument)
    Apple的instrument为开发者提供了各种template去优化app性能和定位问题。很多公司都在赶feature,并没有充足的时间来做优化,导致不少开发者对instrument不怎么熟悉。但这里面其实涵盖了非常完整的计算机基础理论知识体系,memory,disk,network,thread,cpu,gpu等等,顺藤摸瓜去学习,是一笔巨大的知识财富。动画性能只是其中一个template,重点还是理解上面问题当中CPU GPU如何配合工作的知识。
    loadView是干嘛用的?
    不要就简单的告诉我没用过,至少问下我有什么用。。这里是apple给开发者自己设置custom view的位置。说UI熟悉的一定要知道。
    viewWillLayoutSubView你总是知道的。。
    controller layout触发的时候,开发者有机会去重新layout自己的各个subview。说UI熟悉的一定要知道。
  • GCD里面有哪几种Queue?你自己建立过串行queue吗?背后的线程模型是什么样的??
    两种queue,串行和并行。main queue是串行,global queue是并行。有些开发者为了在工作线程串行的处理任务会自己建立一个serial queue。背后是苹果维护的线程池,各种queue要用线程都是这个池子里取的。GCD大家都用过,但很多关键的概念不少人都理解的模凌两可。串行,并行,同步,异步是GCD的核心概念。
    用过coredata或者sqlite吗?读写是分线程的吗?遇到过死锁没?咋解决的?
    没用过sqlite是说不过去的。用过CoreData的肯定有很多血泪史要说。多谢线程模型你肯定做过比较选择。死锁是啥肯定也是要知道的,没遇到过至少能举个简单的例子来说明。单个线程可以死锁(main thread里dispatch_sync到main queue),多个线程直接也可以死锁(A,B线程互相持有对方需要的资源且互相等待)。
  • http的post和get啥区别?(区别挺多的,麻烦多说点)
    这个可以说很多。不希望听到的答案有
    两个差不多,随便用一个。
    post比get安全(其实两个都不安全)
    能说下两个http格式有什么不同,各自应用的场景就合格了。更多可以阅读下这个答案。

1、如何令自己所写的对象具有拷贝功能?

2、说说你理解weak属性?

3、题目:Swift mutating关键字的使用?

4、UIView和CALayer是什么关系?

5、下面的代码输出什么?

6、@synthesize 和 @dynamic 分别有什么作用?

7、动态绑定

8、Category(类别)、 Extension(扩展)和继承的区别

9、为什么代理要用weak?代理的delegate和dataSource有什么区别?block和代理的区别?

10、id和NSObject*的区别

11、如何令自己所写的对象具有拷贝功能?

12、使用系统的某些block api(如UIView的block版本写动画时),是否也考虑引用循环问题?

13、用@property声明的NSString(或NSArray,NSDictionary)经常使用copy关键字,为什么?如果改用strong关键字,可能造成什么问题?

14、UIView和 CALayer是什么关系?

15、static有什么作用?

底层:

16、main()之前的过程有哪些?

17、KVO基本原理?

18、Swift 下的如何使用 KVC?

19、:Swift有哪些模式匹配?

20、objc在向一个对象发送消息时,发生了什么?

21、静态库的原理是什么?你有没有自己写过静态编译库,遇到了哪些问题?

22、runloop是来做什么的?runloop和线程有什么关系?主线程默认开启了runloop么?子线程呢?

23、不手动指定autoreleasepool的前提下,一个autorealese对象在什么时刻释放?(比如在一个vc的viewDidLoad中创建

24、不手动指定autoreleasepool的前提下,一个autorealese对象在什么时刻释放?(比如在一个vc的viewDidLoad中创建)

25、OC完整的消息转发机制+代码实现【暴击】

26、、以+ scheduledTimerWithTimeInterval…的方式触发的timer,在滑动页面上的列表时,timer会暂定回调,为什么?如何解决?

27、如何手动触发一个value的KVO

28、如何对定位和分析项目中影响性能的地方?以及如何进行性能优化?

29、串行并行,异步同步的区别?

30、线程是什么?进程是什么?二者有什么区别和联系?

31、RunLoop是什么?

32、假设有一个字符串aabcad,请写一段程序,去掉字符串中不相邻的重复字符串,即上述字符串处理之后的输出结果为:aabcd

@autoclosure(自动闭包)

34、iOS app启动如何优化?

35、swift面试题:

36、怎样防止反编译?

37、UITableView性能优化,超实用

线程:

37、 不要阻塞主线程

38、谈谈你对多线程开发的理解?ios中有几种实现多线程的方法?

39、进程和线程的区别?同步异步的区别?并行和并发的区别?

40、ViewController生命周期

41、iOS 中的多线程

42、内存管理的几条原则时什么?按照默认法则.那些关键字生成的对象

需要手动释放?在和property结合的时候怎样有效的避免内存泄露?

谁申请,谁释放

43、dispatch_barrier_async的作用是什么?

44、如何用GCD同步若干个异步调用?(如根据若干个url异步加载多张图片,然后在都下载完成后合成一张整图)

http:

46、http与https的区别?

47、服务器能否知道APNS推送后有没有到达客户端的方法?

app:

48、1.什么方式可以看到上架App的头文件?

2.阅读过哪些框架的源码?能说说它的架构方式吗

49、iOS iAP内购审核可能失败的问题

50、IAP内购中虚拟货币导致审核无法通过的问题?

面试整理
1、TableView卡顿的优化~案例~tableView的重用机制?
2、

1
2
3
3、三方库的解析
4、LRU、LFU,数据持久化储存(Least Frequently Used)(Least recently used,最近最少使用)
5、GCD用的多吗?都怎么用的,```group、notify,berries,semaphore

6、布局方式
7、KVO的实现原理,NSKVONotifying_A
8、性能优化
9、runtime用的多吗
10、

11、擅长的东西
12、js交互
13、移动端目前的打包方式,内部发布的时候怎么进行安装!
14、property的修饰符有哪些来自 简书

15、runloop,mode有timer、source、common和observer等
16、bug处理,dsym,
17、移动端线上测试,mqc,最大崩溃率,体验不好,临时处理方式
pod ‘Bugly’腾讯出品,都怎么调试,

18、一个Universal程序还是iPhone、iPad俩个版本 ?
19、老鼠的问题
20、iOS 以scheduledTimerWithTimeInterval的方式触发的timer,在滑动页面上的列表时,timer会暂停,为什么?该如何解决
21、OC中protocol、category和继承的区别 extension 来自 cocoachina

用category的好处
(可以添加实例方法,类方法,甚至可以实现协议,添加属性)和不可为(无法添加实例变量)。
22、介绍项目,注册用户最多的一个
23、招合适的人
24、本地推送,远程推送
25、typedef 和 define 使用注意 来自 简书
26、UIImage加载图片性能问题 来自 简书
27、你大概知道一个类的名字,现在你定位到这个类!
28、收费视频处理流程
29、AutoreleasePool的释放有如下两种情况 runloop即将结束,drain
30、字典转模型,MJExtension
31、怎么发现离屏渲染 来自 cnblog
32、JSPatch 来自 cnblog

代码规范

目的

为了利于项目维护以及规范开发,促进成员之间Code Review的效率,故提出以下开发规范,如有更好的建议,欢迎提出。
本文档的预期读者包括:iOS开发人员。

代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。正确的英文拼写和语法可以让阅读者易于理解,避免歧义。

*注意:即使纯拼音命名方式也要避免采用。但alibab、taobao、youku、hangzhou等国际通用的名称,可视同英文.

小驼峰原则:第一个单词首字母小写,其余都大写。例:nameTextField。

项目命名

  • 项目名都遵循大驼峰命名。例如:AoRiseProject。
  • Bundle Identifier 命名
  • Bundle Identifier:采用反域名命名规范,全部采用小写字母,以域名后缀+公司顶级域名+应用名形式命名,例如:com.hlsk.hedpapp
    类名
  • 类的命名都遵循大驼峰命名。一般是:前缀 + 功能 + 类型。例如:HYC + Login + ViewController。
  • 在实际开发中,一般都会给工程中所有的类加上属于本工程的前缀。
  • 常用控件类命名类型对照表(下表中前缀为:HYC,如果用到下表中没有列举出来,请去掉UI首字母,遵循实际规则即可。)
控件名 类型 示例
UIViewController ViewController HYCBaseViewController
UView View HYCBaseView
UITableView TableView HYCOrderTableView
UITableViewCell Cell HYCOrderListCell
UIButton Button HYCSuccessButton
UILabel Label HYCSuccessLabel
UIImageView ImgView HYCGoodsImgView
UITextField TextField HYCNameTextField
UITextView TextView HYCSuggestTextView
  • 其它类相关对照表
功能 类型 示例
工具类 Tool HYCOrderTool
代理类 Delegate HYCOrderListDelegate
管理类 Manager HYCOrderListModel
模型类 Model HYCOrderListModel
Service类 Service HYCOrderService
布局类 Layout HYCHomeLayout
数据库类 DataBase、表名+DBHelper HYCFriendDataBase、HYCUserTableDBHelper

类目
XXX+(范围,例如Extension, Additions 或者功能,例如Frame,Nib,Block)
HYCUIButton+Additions、HYCUIButton+Block

1
2
3
4
5
6
7
UIViewController请按照如下分类
#pragma mark - life cycle
#pragma mark - event response
#pragma mark - UITableViewDelegate && UITableViewDataSource
(代理顺序往下排列)
#pragma mark - getters and setters
#pragma mark - private

注意:所有视图或者对象的创建请尽量使用懒加载,调用的时候全部使用self.textBtn这样的方式。如果是确定的不可变数组、字典,可直接给定数组中的元素。(getters and setters分类中,懒加载可出现_调用对象,其它情况请遵循self.调用原则)

1
2
3
4
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong)UIButton * textBtn;
@end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    @implementation ViewController

#pragma mark - life cycle
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.textBtn];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - private

#pragma mark - event response

#pragma mark - UITableViewDelegate && UITableViewDataSource
//(代理顺序往下排列)

#pragma mark - CTAPIManagerCallBackDelegate

#pragma mark - getters and setters
- (UIButton *)textBtn
{
if (_textBtn == nil) {
_textBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_textBtn.frame = CGRectMake(300, 250, 100, 100);
_textBtn.backgroundColor = [UIColor yellowColor];
_textBtn.titleLabel.text = @"text";
[_textBtn addTarget:self action:@selector(text) forControlEvents:UIControlEventTouchUpInside];
}
return _textBtn;
}
@end

变量和方法
变量和方法的命名都遵循小驼峰命名。例如:textVariableStr, - (void)textAction响应事件。
变量命名对照表(如果用到下表中没有列举出来,请去掉UI、NS遵循实际规则即可。或者一看就知道的通用简写)
方法命名对照表(方法多为动词或动名词)

功能/示例

- (id)initXX
初始化相关方法,使用init为前缀标识,如初始化布局- (id)initView

- (BOOL)isXX
方法返回值为boolean型的请使用is前缀标识

- (UIView *)getXX
返回某个值的方法,使用get为前缀标识

- (void)setXX
设置某个属性值或者相关数据

- (void)updateXX
更新数据

- (void)saveXX
保存数据

- (void)drawXX
绘制相关,使用draw前缀标识

- (void)clearXX
清除数据

- (void)XXXAction
响应事件,使用Action为后缀标识

- (void)loadData
加载数据(一般情况下VC中都会有这个方法)

- (void)loadMoreData
加载更多数据

- (void)setupUI
加载布局(一般情况下VC中都会有这个方法)

方法的命名
当方法参数在三个以及三个以上,换行保持对齐(冒号对齐,冒号前是参数变量,冒号后是参数值).
方法声明:

1
2
3
4
5
+ (instancetype)initWithPersonName:(NSString *)name
withAge:(int)age
withSex:(NSString *)sex
withHeight:(float)height
withWeight:(float)weight;

方法调用:避免使用冒号对齐的方式.

常量
宏:小写k+大驼峰 即为:#define kUserAgeKey @“ageKey”
全局常量:工程前+缀全大写,下划线隔开 即为:extern const NSString MW_USER_AGE_KEY
参数名
参数名以小驼峰命名,尽量参考苹果原生方法风格编写。尽量可读性好,看到方法名就知道这个方法是用来干什么的。参数应该避免用单个字符命名。例:- (void)setDataImageUrl:(NSString *)imageUrl name:(NSString *)nameStr content:(NSString *)contentStr
资源文件命名
全部小写,采用下划线命名法,加前缀区分。所有的资源文件都需要加上工程前缀(小写形式)。
命名模式:可加后缀_small表示小图,_big表示大图,逻辑名称可由多个单词加下划线组成,采用以下规则:

用途_模块名_逻辑名称 用途_模块名_颜色 用途_逻辑名称 用途_颜色

说明 前缀(工程前缀示例MW) 示例
按钮相关 hyc_btn_ hyc_btn_home_normal、hyc_btn_red,hyc_btn_red_big
背景相关 hyc_btn_ hyc_bg_home_header、hyc_bg_main
图标相关 hyc_ic_ hyc_ic_home_location、hyc_bg_input
分割线相关 hyc_div_ hyc_ic_home_location、hyc_bg_input
默认相关 hyc_def_ hyc_ic_home_location、hyc_bg_input

文件夹命名
创建文件夹最好创建实体文件夹,找到工程目录,创建相应文件夹并拖入工程。文件夹命名使用相应模块结构分层的英文,首字母要大写。例:Model,View,Controller,Tool,Other,Service等等。

采用US(美式)英语,不使UK(英式)英语或汉字拼音.

1
2
3
US: UIColor *myColor =[UIColor blueColor];
UK: UIColor *myColour =[UIColor blueColor];
拼音: UIColor *wodeYanSe =[UIColor blueColor];

宏的命名
以两个大写字母作为前缀,后面遵循大驼峰命名法.

1
2
#define KKScreenWidth ([UIScreen mainScreen].bounds.size.width)
#define KKAppVersion @"appVersion"

枚举的命名
遵循Objective-C内部框架定义方式.
Enum中枚举内容的命名需要以该Enum类型名称开头.

1
2
3
4
5
6
7
typedef NS_ENUM(NSInteger, FulowersMoveDestination)
{
FulowersMoveDestinationTop,
FulowersMoveDestinationBottom,
FulowersMoveDestinationLeft,
FulowersMoveDestinationRight,
};

赋值
在”=”号左右两边各间隔一个空格.

1
static const int count = 0;

类方法或对象方法
方法的”+/-”号和左侧小括号间隔一个空格,方法名称与大括号间隔一个空格

1
2
3
- (void)viewDidLoad {

}

版本规范

采用A.B.C 三位数字命名,比如:1.0.2,当有版本更新的时候,依据下面的情况来确定版本号规范。

版本号 说明 示例
A.b.c 属于重大更新内容 1.0.2 -> 2.00
a.B.c 属于小部分更新内容 1.0.2 -> 1.2.2
a.b.C 属于补丁更新内容 1.0.2 -> 1.0.4

第三方库规范

希望Team能用时下较新的技术,对开源库的选取,一般都需要选择比较稳定的版本,作者在维护的项目,要考虑作者对issue的解决,以及开发者的知名度等各方面。选取之后,一定的封装是必要的。
项目使用cocoapods统一管理开源第三库文件,不需要手动导入和手动添加依赖库。如果第三方不支持cocoapods,可手动导入工程。

类注释
为了减少他人阅读你代码的痛苦值,请在关键地方做好注释。

1
2
3
4
5
6
7
//
// MyViewController.m
// text
//
// Created by Jade on 2017/9/12.
// Copyright © 2017年 Jade. All rights reserved.
//

该注释是自动生成的,在xcode中设置即可。Created by 电脑用户名on 创建该文件的时间。Copyright 2017 后面的名字和邮箱是自己填写和设置的。具体可在xcode工程,Project Document中设置。这样便可在每次新建类的时候自动加上该头注释。
方法注释

方法注释,方法外部统一用option + command + /,方法内部统一用//注释。

/**
测试
*/
- (void)text
{
   //测试按钮事件响应
}


注释

注释是为了解释说明,方法或变量等命名规范合理,清楚易懂,可以不添加注释,含有复杂逻辑的代码必须添加注释.注释需要实时更新,跟随代码的变动进行更改或者删除.
1.公开类方法注释
在.h文件中声明类方法,采用文档注释,要写明方法的具体作用,所有参数的含义以及返回的参数值.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
创建person对象的类方法

@param name 姓名
@param age 年龄
@param sex 性别
@param height 身高
@param weight 体重
@return 返回person类对象
*/
+ (instancetype)initWithPersonName:(NSString *)name
withAge:(int)age
withSex:(NSString *)sex
withHeight:(float)height
withWeight:(float)weight;

方法内部逻辑代码注释
复杂逻辑代码在代码上方进行注释,注释方式采用双斜杠+单个空格+具体注释内容

1
2
3
4
5
6
7
8
9
- (void)viewDidLoad
{
[super ViewDidLoad];
// 注释
if(...)
{
...
}
}

for循环
for和左侧小括号间隔一个空格, i和”<=”间隔一个空格, ”<=”和”3”间隔一个空格, ”3”后面紧跟着封号 ,封号和i间隔一个空格.大括号换行,一对大括号上下位置对齐.

1
2
3
4
for (int i = 0; i <= 3; i++)
{
// 语句
}

条件语句
关于大括号,任何需要大括号的都不能省略.
采用

1
2
3
4
if (isLogin)
{
return success;
}

不是

1
2
if (isLogin)
return success;

也不是

1
if (isLogin) return success;

case语句
当一个case语句包含多行代码时,大括号应该加上.如case 2所示.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
switch (condition) 
{
case 1:
// ...
break;
case 2:
{
// ...
// Multi-line example using braces
break;
}
case 3:
// ...
break;
default:
// ...
break;
}

当在switch使用枚举类型时,default是不需要的.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
switch (FulowersMoveDestination) 
{
case FulowersMoveDestinationTop:
// ...
break;
case FulowersMoveDestinationBottom:
// ...
break;
case FulowersMoveDestinationLeft:
// ...
break;
case FulowersMoveDestinationRight:
// ...
break;
}

单例
统一采用shared+类名作为单例类的方法名

1
2
3
4
5
6
7
8
9
10
11
12
13
@implementation LBYNetworkTool
+ (instancetype)sharedBYNetworkTool
{
static LBYNetworkTool *instance;
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[LBYNetworkTool alloc]init];
});
}
return instance;
}
@end

UI整理
搭建UI时,使用setup作为方法名前缀,将相应UI布局放在对应方法中

1
2
3
- (void)setupTableViewUI
- (void)setupNavigationUI
- (void)setupCollectionViewUI

标记
在函数分组和使用#pragma mark - 给重要逻辑代码添加标记,方便阅读

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#pragma mark - Lifecycle
- (instancetype)init
- (void)dealloc
- (void)viewDidLoad
- (void)viewWillAppear:(BOOL)animated
- (void)didReceiveMemoryWarning

#pragma mark - IBActions
- (IBAction)submitData:(id)sender

#pragma mark - Public
- (void)publicMethod

#pragma mark - Private
- (void)privateMethod

#pragma mark - Custom Protocol
- (void)tabbarBottomView:(LBYTabbarBottomView *)tabbarBottomView didSelectIndex:(NSUInteger)index didSelectBtn:(BYBottomButton *)selectBtn

#pragma mark - UITextFieldDelegate
- (void)textViewDidBeginEditing:(UITextView *)textView;
- (void)textViewDidEndEditing:(UITextView *)textView;

#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

#pragma mark - UITableViewDelegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;

#pragma mark - NSObject
- (NSString *)description

模型注释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
每个model中的,包含的每个属性,都必须要写上相对应的注释,用///注释。阅读者一看这个model,就清楚知道model中的每个字段代表的意思,用来做什么事情的。
@interface DeliveryModel : NSObject
///提货劵所在商圈id
@property (nonatomic, assign) long long mallId;
///商圈全称
@property (nonatomic, copy) NSString *mallFullName;
///商圈简称
@property (nonatomic, copy) NSString *mallShortName;
///提货劵号
@property (nonatomic, copy) NSString *credentialsCode;
///总金额
@property (nonatomic, assign) NSInteger totalAmount;
///提货劵所在店铺id
@property (nonatomic, assign) long long storeId;
///货劵所在店铺名称
@property (nonatomic, copy) NSString *storeName;
///提货劵id
@property (nonatomic, strong) NSNumber *credentialsId;
///状态:0:未提货、1:已提货、2:已分享、3:已退款
@property (nonatomic, assign) NSInteger state;
///提货商品(以下为提货商品参数)
@property (nonatomic, strong) NSArray<DeliveryGoodslist *> *goodsList;
///二维码
@property (nonatomic, copy) NSString *qrCode;
///商品总个数
@property (nonatomic, assign) NSInteger goodsCount;
@end

如果不是model的属性,是其它类属性,需要注释,请按照model属性注释方式。

属性和对象的命名
采用修饰+类型的方式命名,BOOL类型添加is前缀,单词遵循小驼峰命名法.声明属性时,小括号中的顺序依次是:nonatomic,readonly,strong.

1
2
3
4
5
@property (nonatomic, assign) BOOL isLogin;
@property (nonatomic, weak) UITextField *loginNameTextField;
@property (nonatomic, copy) NSString *studentClientName;
@property (nonatomic, weak) UILabel *loginTipLabel;
@property (nonatomic, weak) UIButton *loginButton;

编码规范

  • 所有的方法之间空一行。
  • 所有的代码块之间空一行,删除多余的注释。
  • 所有自定义的方法需要给出注释。
  • 尽量使用懒加载,在控制器分类时有提及和要求,其它自定义类按照控制器格式分类,没有的分类不写即可。
  • 代码后的’{‘不需要独占一行,包括方法之后,if,switch等。
  • 必须要统一的要求,属性的定义请按照下图property之后,空一格,括号之后空一格,写上类名,空一格之后跟上*和属性名。

    1
    2
    3
    4
    @property (nonatomic, strong) UITableView *tableView;
    @property (nonatomic, strong) DeliveryModel *delivery;
    @property (nonatomic, strong) DeliveryLookAdapter *lookAdapter;
    @property (nonatomic, strong) DeliveryLookAPIManager *lookManager;
  • 遵循一般代码规范,多模仿苹果API。

  • 删除不用的代码。
  • 如果有方法一直不会用到,请删除(除工具类)。
  • 没有执行任何业务逻辑的方法,请删除或给予注释,删除多余的资源或文件,添加必要的注释。
  • 比较大的代码块需要给出注释。

其它规范

  • 建议项目统一使用Masonry和xib结合的方式布局。不允许出现直接设置frame的情况。如果是纯代码的项目,不允许出现xib和拉约束的情况。不建议使用纯storyboard开发。???
  • 数据提供统一的入口。无论是在 MVP、MVC 还是 MVVM 中,提供一个统一的数据入口,都可以让代码变得更加易于维护。比如可使用一个DataManager,把 http、preference、eventpost、database 都放在DataManger里面进行操作,我们只需要与DataManger打交道
  • 提取方法,去除重复代码。对于必要的工具类抽取也很重要,这在以后的项目中是可以重用的。(如果是想组件化,重复代码不可避免,而且会增加工作量,因为模块之前是独立的,页面层面的雷同不做抽提)
  • 尽可能的使用局部变量
  • 尽量减少对变量的重复计算。
  • 尽量在合适的场合使用单例。使用单例可以减轻加载的负担,缩短加载的时间,提高加载效率。但并不是所有的地方都适用于单例,简单来说单例主要适用于以下三个方面:
  1. 控制资源的使用,通过线程同步来控制资源的并发访问。
  2. 控制实例的产生,以达到节约资源的目的。
  3. 控制数据的共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信。
    最后不要忘了检测内存泄漏。可使用Instruments分析内存。

文章来源1
文章来源2