iOS技巧、特性及规范

一、编译器特性

1、ARC。

ARC是编译器特性。项目中使用了ARC,编译器会在项目编译的时候自动添加OC对象计数器release代码。并且使用了ARC,项目中将不允许出现release、retain、retainCount和[super dealloc]代码。

ARC不同于Java和.Net中的垃圾回收,Java和.Net中的垃圾回收是运行时特性。ARC只是将OC对象的计数器自动减1。非OC对象,像常见的数据类型、enum枚举和struct结构体不参与ARC,系统会自动销毁回收。(注:OC对象计数器在一个对象中占4个字节,当计数器为0时,如果该OC对象被strong强指针引用,那么此OC对象将成为僵尸对象不可再次访问,当然也无法“复活”该对象,应当手动将strong强指针置为nil;如果该OC对象被weak弱指针引用,那么此OC对象变为僵尸对象的时候,weak弱指针将自动销毁。)

2、@class

@class是在类的头文件中出现的。使用@class主要解决两个问题:

①在非ARC的项目中,解决因类之间的相互引用,导致OC对象计数器无法减为0的问题。在其中一个类头文件中引用另一个类的头文件使用@class,并且将其中一个类的所有OC对象指针设为assign类型即可。

②提高编译器特性。使用@class就相当于一个声明,告诉另一个类包含哪些成员变量和方法,具体在.m使用的时候,只需再#import此类的.h文件即可。如果不是用@class声明类的引用,全都是在.h文件中直接#import另一个类的.h文件,那么当一个.h文件改变,编译器在编译的时候就会再复制一遍此.h头文件,加入有上万个这样的应用,编译器就得复制一万遍。使用@class就可以不用复制,这样就提高了编译器性能。

3、[]

对于NSArray和NSDictionary,当需要直接根据索引index或者关键字key取得相应的值的时候,就可以像直接通过[index]或者[key]获得。注意,通过此方法获取到的对象都是id类型,想要再访问指定对象类型的方法或者成员变量还需要自己转一下。(注:为什么通过[]获取到的对象是id类型?因为[index]相当于调用了NSArray对象的objectAtIndex方法,[key]相当于调用了objectForKey,这两个方法返回的都是id类型的对象。)

4、@()和@20

@()和@20是在int整型转换为OC对象NSNumber的时候用到的。比如,@20就是将整型20转换为NSNumber的OC对象类型,进而可以在NSArray或者NSDictionary中使用。(注:NSArray和NSDictionary只允许添加OC对象作为元素。)。@(),是将常见数据类型临时变量转换为指定OC类型。比如int a = 20;NSNumber *aa = @(a);这样就将临时变量a的整型值转换为了NSNumber的OC类型。不可以这样写@a,一写就报错。

二、性能

1、SEL

SEL即Selector。SEL是指向类中方法的指针类型。通常情况下,当对象或者类调用对象方法或者类方法的时候,都先要将调用的方法包装成SEL类型,然后根据SEL类型数据找到对应类中所调用方法的地址,最后就是调用。这样一个对象或者类调用指定方法就经过了2步,如果涉及到同一个方法多次频繁的调用还是每次都要经过SEL这两步的话,无疑会耗费一定的性能。此时就可以将SEL单独保存起来,每次调用就可以直接根据SEL类型的指针地址找到对应方法进行执行。

2、nonatomic

在一个类的头文件中声明一个成员变量时,系统默认将此变量声明为atomic,atonmic就是原子的意思,是在多线程中使用,防止同一个成员或对象同时被多个线程同时访问造成死锁。默认是atomic,项目在编译的时候系统会自动在后台添加很多代码,平时不牵涉到多线程,此处就可以手动设置为nonatomic,提高性能。

3、[UIImage imageNamed:]

一个UIImageView使用此方法访问显示一个图片,系统会自动将此图片在内存中生成一份缓存,如果不从内存中清除此缓存,它将一直占用内存。如果使用imageWithContentsOfFile,当UIImageView由一张图片显示为另一张图片的时候,系统就会自动将上一张图片从内存中销毁移除。

4、自定义UITableViewCell,如果一张图片只是控制了其hidden属性,那么就可以在UITableViewCell初始化的时候将UIImageView的image设置为此图片,避免在UITableViewCell从缓存池中循环利用重复设置数据设置图片的时候造成的内存消耗。

5、自定义UITableViewCell出现高度不一致的时候,需要引入frame模型,在获取到数据以后马上计算每一个UITableViewCell的frame,使用的时候直接设置计算好的高度就可以了。避免了在UITableView上下滚动的时候造成的重复计算消耗性能造成的卡顿现象。

三、技巧

1、界面上显示一道线,在WPF中可以使用Border或者Line现成的控件来做,在OC里面苹果官方使用的是UIView。如果是横线,则UIView的height为1,同理竖线的情况with为1。

2、UITextField左右两侧有leftView和rightView。如果我们想在用户输入的时候自动在左侧留有空隙,那么就可以使用指定leftView为[[UIView alloc] initWithRect:CGRectMake(0, 0, 8, 0)];

3、给一个UIButton设置一个图标,且此图标不能伸缩变形显示,此时可以设置此UIButton的image来展示,而不是BackgroundImage。

4、图像平铺技术。比如QQ聊天窗口,每个人发的消息。其实程序就是指定了在一张图片的上、下、左、右多少范围内当图片拉伸的时候不变形,范围内的区域自动平铺填充图形。此技术在Win8里面叫NineGrid(九切片)。

四、调试

1、错误提示关键字:forUndefinedKey。一看就知道StoryBoard里面的线连错了。

2、Unrecoganized seletor sent to instance。一看就是到对象或类的方法为找到。

此种情况比较常见的原因有两点:

①、子类调用父类的自定义构造函数初始化,父类方法没有使用self,结果返回的还是父类对象,调用了子类的方法。

②、在定义对象方法的时候,返回值使用了id类型而不是instancetype。如上面所说,id类型是不能自动转换为指定对象,默认返回的是任意类型的对象,比如一个要返回一个Person对象,没有定义length成员,此时用NSString类型的指针是可以去指向该对象的,那访问NSString的length成员就会出现此错误。解决方法,可以通过强转为Person对象,或者将返回类型id换位instancetype。那是不是所有使用id的地方都可以换位instancetype呢?不是。只有在id作为返回类型的时候才可以替换为instancetype。

③、has been modified。一看就知道清下项目缓存就可以解决。

五、布局

当我们修改了界面运行的时候看不到变化,此时就可以试着去去掉autolayout。

六、.pch文件

1、尽量将我们自己定义的东西放在@ifdef __OBJC__ 里面。

举个例子:比如在.pch文件里导入了一个.h头文件,#import "Person.h"。并且没有写在@ifdef __OBJC__里面,此时我们在项目中写一个.c的文件,一运行就会报很多错误。为什么呢?因为在.pch导入#import的.h文件,会在项目所有文件中默认导入#import该.h头文件,但C语言的.c程序需要#include才可以导入.h头文件,使用#import显然不行,所以报错。

2、一定要使用自定义的日志打印策略,不然在项目发布的时候还会包含很多日志打印的代码,无疑会影响性能。自定义日志打印策略如下:

所以,看一个项目代码,首先去看.pch文件。

七、规范

类名和函数名单词首字母都大写,方法名和变量名单词第一个首字母小写,其他单词首字母大写。

八、理解

1、为什么UITableViewCell需要Identifier,而UIDatePick的自定义View不需要。

UITableViewCell使用Identifier主要考虑到以下两点:

①不同数据用不同cell模板,就可以根据Identifier不同从缓存池中循环利用指定的cell模板。

②、根据Identifier从缓存池中去除已存在的模板,循环利用,提高性能。

UIDatePick的View都是一样的模板,不存在同一数据源不同模板的情况,所以不需要Identifier直接去使用resuming就行了。

此外还要注意awakeFromNib、layoutSubView以及didMoveToSuperView方法的用法。

iOS还在学习中,有理解不到位或者错误的地方,还请各路大神指点。

时间: 2024-10-12 20:00:00

iOS技巧、特性及规范的相关文章

ios Swift 特性

特性提供了关于声明和类型的更多信息.在Swift中有两类特性,用于修饰声明的以及用于修饰类型的.例如,required特性,当应用于一个类的指定或便利初始化器声明时,表明它的每个子类都必须实现那个初始化器.再比如noreturn特性,当应用于函数或方法类型时,表明该函数或方法不会返回到它的调用者. 通过以下方式指定一个特性:符号@后面跟特性名,如果包含参数,则把参数带上: @attribute name@attribute name(attribute arguments) 有些声明特性通过接收

iOS 动态特性和RunTime

过去的几年中涌现了大量的Objective-C开发者.有些是从动态语言转过来的,比如Ruby或Python,有些是从强类型语言转过来的,如Java或C#,当然也有直接以Objective-C作为入门语言的.也就是说有很大一部分开发者都没有使用Objective-C太长时间.当你接触一门新语言时,更多地会关注基础知识,如语法和特性等.但通常有一些更高级的,更鲜为人知又有强大功能的特性等待你去开拓. 这篇文章主要是来领略下Objective-C的运行时(runtime),同时解释是什么让Object

CSS技巧----DIV+CSS规范命名大全集合

网页制作中规范使用DIV+CSS命名规则,可以改善优化功效特别是团队合作时候可以提供合作制作效率,具体DIV CSS命名规则CSS命名大全内容篇. 常用DIV+CSS命名大全集合,即CSS命名规则 DIV CSS命名目录 命名规则说明 重要CSS命名 CSS命名参考表 命名技巧 我们开发CSS+DIV网页(Xhtml)时候,比较困惑和纠结的事就是CSS命名,特别是新手不知道什么地方该如何命名,怎样命名才是好的方法. 一.命名规则说明:   -   TOP 1).所有的命名最好都小写2).属性的值

iOS技巧篇之UIViewController与UIView的双向交互

1.场景描述 在iOS开发过程中,一般都是UIViewController来控制UIView的行为,一般很少方向交互,即UIView的特性变化后调用UIViewController的相应的方法,在遇到这种情况,大多数都采用了在UIView的子类中放一个UIViewController的指针,当UIView需要调用UIViewController的方法的时候,就可以通过这个指针来实现了. 2.解决方案 这种方法是有效的(C/C++常用哦),但总是觉得不够优雅,有没有其他办法来实现呢,答案是肯定的,

iOS中书写代码规范

1.精简代码, 返回最后一句的值,这个方法有一个优点,所有的变量都在代码块中,也就是只在代码块的区域中有效,这意味着可以减少对其他作用域的命名污染.但缺点是可读性比较差 NSURL *url = ({ NSString *urlString = [NSString stringWithFormat:@"%@/%@", baseURLString, endpoint]; [NSURL URLWithString:urlString]; }); 2.关于编译器:关闭警告: #pragma

iOS中书写代码规范35条小建议

1.精简代码, 返回最后一句的值,这个方法有一个优点,所有的变量都在代码块中,也就是只在代码块的区域中有效,这意味着可以减少对其他作用域的命名污染.但缺点是可读性比较差 NSURL *url = ({ NSString *urlString = [NSString stringWithFormat:@"%@/%@", baseURLString, endpoint]; [NSURL URLWithString:urlString]; }); 2.关于编译器:关闭警告: #pragma

iOS端项目注释规范附统一代码块

代码的注释经常被人忽略,以至于在后期维护的时候较为困难.我们准备在XX项目开始之前制定一套规范的注释体系,致力于达到就算维护人员改变也能快速上手的效果. 1.属性注释 属性注释 使用 /** 注释*/ 的文档注释格式. 这种注释相较于// 注释的优点是此属性可以在后面的引用时,在智能提示的下方显示中文注释 如果你不是在董铂然博客园看到本文请点击查看原文. 例如: /** 回复率*/ @property(nonatomic,strong)MTPoiCompareM *replyRate; /**

iOS团队开发代码规范

iOS 开发代码规范 1.命名 https://github.com/Chinamobo/iOS-Team-Norms/blob/master/CodeStyle.md#naming-basic-principle https://github.com/foxsofter/ios-code-style https://github.com/andy0323/iOS-Code-Specification 新建.h,.m文件时,文件名称应与

ios培训:ios技巧总结,错过就不在!

今天给大家总结了一些iOS小技巧总结,绝对有你想要的!绝对有你想要的! UITableView的Group样式下顶部空白处理 //分组列表头部空白处理 UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 0.1)]; self.tableView.tableHeaderView = view; 获取某个view所在的控制器 - (UIViewController *)viewController { UIViewCon