参考文章
字面数值
//使用方法来创建显得繁琐复杂
NSNumber *someNumber = [NSNumber numberWithInt:1];
//上下两句结果完全一致的同时这样写明显简单多了
NSNumber *someNumber = @1;
//而且根据不同的字面值直接能创建不同类型的,不用换方法
NSNumber *floatNumber = @2.5f;
NSNumber *boolNumber = @YES;
字面量数组
//一样简单方便
NSArray *animals = @[@"cat", @"dog"];
//这样写还有一大好处就是如果数组元素里有nil,使用字面量创建会直接报错,方法创建却不会,会直接断开。
//也就是说使用字面量数组可以避免数组元素出错(因为会直接报错)
//另外在查找某下标的元素时也可以像C语言那样直接
NSString *dog = animals[1];
字面量字典
//创建字典使用字面量简单易懂,也有出现nil报错的特性
NSDictionary *personData = @{@"firstName" : @"Matt", @"age" : @28};
//同样按照特定键来查找元素也方便多了
NSString *lastName = personData[@"lastName"];
可变数组与字典
//修改方便
mutableArray = @"dog";
mutableDictionary[@"lastName"] = @"Galloway";
使用字面量的局限性
- 使用字面量创建的都是不可变的
- 如果想要可变数组需要NSMutableArray *mutable = [@[@1, @2, @3, @4] mutableCopy];
多用类型常量
- 使用#define无法说明数据的类型,只是简单的代码替换,在大型合作时会显得疲惫
- 定义常量格式:static const 类型 名称 =
- 命名习惯:
- 在单独文件内可见:前面加k
- 在类之外可见:以类名做前缀
- 在实现文件内使用的常量还是直接写在.m文件里#import下面
- const代表常量不可变,一旦修改会报错
- static代表该变量只会在定义次变量的编译单元中可见
- 事实上这样写本质上和#define已经没有什么区别了,依然直接是代码替换
- 如果希望实现的是对外公开即放在“全局符号表”,我们需要这么写
//in the header file
extern NSString *const EOCStringConstant;
//in the implementation file
NSString *const EOCStringConstant = @"VALUE";
//记住要以类名为前缀
用枚举表示状态, 选项, 状态
- 枚举值多是用在状态码,选项和状态码值
- 下面是iOS自带枚举类型,使用了NS_ENUM, NS_OPTIONS两种宏
//不需要使用按位操作或操作组合的枚举使用NS_ENUM
typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
UIViewAnimationTransitionNone,
UIViewAnimationTransitionFlipFromLeft,
UIViewAnimationTransitionFlipFromRight,
UIViewAnimationTransitionCurlUp,
UIViewAnimationTransitionCurlDown,
};
//需要使用按位操作或操作组合的枚举使用NS_OPTIONS
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
- 枚举值用二进制表示, 在使用位操作后会有独一无二的值, 从而可以判断是否启用
- 在switch语句里使用枚举注意不要default
理解“属性概念”这一概念
- 属性特质
- 原子性
- 一般只使用nonatomic
- 想了解具体可以看第一篇参考文章
- 读/写权限
- readwrite
- readonly
- 只有getter方法, 只有用@synthesize才能指定setter方法
- 可以公开设置成readonly, 在class-continuation分类里定义为readwrite
- 内存管理语义
- 影响setter方法的特性
- 一共五种
- assign:对“纯量类型”简单赋值
- strong:保留新值,释放旧值,设置新值
- weak:同assign,只是可以设定的对象广
- unsafe_unretained:同weak,只是摧毁时不会自动清空属性
- copy:同strong,主要在于可以拷贝
- 这本书讲的好像不是很好,还是推荐看这个iOS关于属性关键字,你又知道多少?
- 方法名
- 可以加入getter/setter = 指定setter/getter方法名
在对象内部尽量直接访问实例变量
- 用不用点语法差别很大
- 比如我有一个name属性
- self.name我们叫点语法访问,而_name这样叫做直接访问
- 直接访问比较快,不经过“方法派发”环节
- 直接访问直接跳过内存管理语义(assign等)
- 直接访问不会触发KVO
- 点语法访问可以在setter/getter处设置断点检验错误
- 因此推荐是读取直接读取, 写入通过属性, 初始化与dealloc用直接
- 惰性初始化
-(NSMutableArray *)cards
{
if(!_cards)
_cards = [[NSMutableArray alloc]init];
return _cards;
}
理解“对象等同性”这一概念
- ==比较的是两个指针, 而isEqual比较的是对象本身
- 自己写一个判断等同性的方法
//这个方法就是比较每一个属性, 如果都是相等的就返回YES
- (BOOL)isEqualToPerson:(EOCPerson *)otherPerson {
if (self == object) return YES;
if (![_firstName isEqualToString : otherPerson.firstName])
return NO;
if (![_lastName isEqualToString : otherPerson.lastName])
return NO;
if (_age != otherPerson.age)
return NO;
return YES;
}
//重写isEqual方法, 如果属于同一个类就使用自己的方法, 不然就交给超类判断
- (BOOL)isEqual : (id)object {
if ([self class] == [object class]) {
return [self isEqualToPerson:(EOCPerson *)object];
} else {
return [super isEqual : object];
}
}
- super关键字:self和super都是指向当前实例的,不同的是,[self class]会在当前类的方法列表中去找class这个方法,[super class]会直接开始在当前类的父类中去找calss这个方法,两者在找不到的时候,都会继续向祖先类查询class方法,最终到NSObject类。
- 对于唯一的实例,我们可以仅仅比较一个主键来判断是否相等
以“类族模式”隐藏实现细节
- 简单来说就是使用基类, 结合枚举, 将大量的重复的细节放在基类去实现
- OC没办法标明抽象类,一般抽象类没有初始化方法