把 Xcode 里的「提示」当做「错误」来思考。
1、你可以发送消息到一个 nil 对象,什么都不会发生。 2、只有常量指针的值不会改变
// 以下两个都不是常量指针 值可以改变
const NSString *first = @"Hello";
first = @"World";
NSString const *first = @"Hello";
first = @"World";
// 下面为常量指针
NSString * const first = @"Hello";
复制代码
3、如果你想要比较字符串是否完全相等,一定要用 isEqualToString ,不要用 "==","=="比较的是指针。 4、不可变的值赋值给可变对象,调用可变的方法会出现不可控的错误。
如下 会崩溃
NSMutableString *mutable = @"string";
[mutable replaceCharactersInRange:NSMakeRange(1, 2) withString:@"123"];
复制代码
5、不要把 NSMutableString 当成 NSString 来使用 如下 会改变second的值
NSMutableString *first = [@"My string" mutableCopy];
NSString *second = first;
[first setString:@"Something else"];
// print Something else
NSLog(@"%@", second);
// 应该使用下面方法
NSString *second = [first copy];
复制代码
6、NSArray初始化的时候,数组结尾的地方有个 nil ,因为 NSArray 需要知道这个数组在哪里结束,如果你不写这个 nil,Xcode会报错。 7、疑问 swift字典是有序的么? 8、NSSet&NSCountedSet 在 NSCountedSet 里,相同的对象也只能出现一次。但是每当你添加或删除这个对象时,它会记下你添加或删除的次数,这就让它在统计集合元素数量时,速度更快。
NSArray *array = @[@1,@2,@3,@1,@4];
NSSet *set = [NSSet setWithArray:array];
NSLog(@"%@",set);
// {(3, 2, 1, 4 )}
NSCountedSet *count = [NSCountedSet setWithArray:array];
NSLog(@"%@\n%lu",count,(unsigned long)[count countForObject:@1]);
// {(3, 2, 1, 4 )}
// 2
复制代码
9、Objective-C中的泛型概念是用了一个叫做「类型擦除」的黑科技,但是这是黑科技诶。稍有不慎,就会导致代码报错,程序崩溃。
NSMutableArray<NSString *> *names = [NSMutableArray
arrayWithCapacity:4];
[names addObject:@"Sophie"];
[names addObject:@42]; // 警告
复制代码
10、instancetype 的意思「返回当前类对应的实例」,以确保编译器正确地使用数据类型。 11、属性修饰符
- strong: 属性的默认特征,也就是强引用,表示「储存在内存里」。
- weak: 弱引用,用于避免循环引用。
- copy: 拷贝,当属性有对象的时候,自动复制。
- assign: 用来修饰基本数据类型,确保把值给了实例变量。
- nonatomic: 原子性(atomic)属性,是指在多线程运行的时候,某一线程访问存或者取方法,其他线程不可以进入该存、取方法。非原子性(non-atomic)则相反,你要保证没有同时存取。
- retain: strong 的旧格式,如果你看到了这个修饰符,说明真的接手了一个超级老的项目。
- readonly: 只读,不能使用 setter 访问器。
- readwrite: 读写,所有属性的默认特征,可以使用 getter 和 setter 访问器。
- atomic: 看上面的 nonatomic,atomic 让代码更安全,也是所有属性的默认特征,会降低性能(iOS在移动端性能要求比价高,所以都使用nonatomic)。只是读写线程安全,正在使用的时候其他地方release就会出错。
- getter=: 改变 getter 访问器的名称。
- setter=: 改变 setter 访问器的名称。
- 默认使用的组合(strong, atomic, readwrite),修饰String替换为(copy, atomic, readwrite)
有些人会把原子性和线程安全混为一谈,但这个理解是不对的。原子属性确保的是,如果两个不同的线程想要同时设定一个值,那么会有第三个线程来监视它们,读值然后返回。所以,当你的属性是原子性的时候,多线程并行要么发生,要么不发生,不可能发生一半。 那线程安全的他完全是另外一些事情,他表示的是部分代码的安全执行。举个例子。如果说你从旧金山搬家到巴黎,你居住的街道,城市和国家都会发生改变。如果这时候,我想要读取你的街道住址,我会读到香榭丽舍大街上,但是你的城市和国家依然是旧金山跟美国。 当你创建了控件(IBOutlet)的时候,你会发现 Xcode 默认把他们定义为 nonatomic。因为控件不会在主线程以外的地方被读取到,在单线程环境中,使用 nonatomic 可以提升性能。
12、类扩展里有一个 redefine 属性
// 原类中
@property (readonly) NSString *name;
// 拓展中 实现
@interface Person ()
@property (readwrite) NSString *name;
@end
复制代码