Objective-C学习小记 | Lemtter 

JerryXia 发表于 , 阅读 (0)
Syntax And Notes

旧数组方法

  • 在OC中数组除了可以用下标访问还可以用ObjectAtIndex:方法来访问,同样的创建数组也可以用旧方法arrayWithObjects:来访问。

Demo Code

1
2
3
4
/*创建数组需以nil作为结束标记*/
NSArray *anyArray = [NSArray arrayWithObjects:objectOne, ObjectTwo, nil];
/*返回第一个对象*/
id object = [anyArray objectAtIndex:0];
  • 创建数组可以向对象发送消息,也可以用字面量语法创建,但要注意用字面量创建数组不可包含nil对象不然会抛出异常。用发送消息的方式创建数组时会在遇到第一个nil时结束

Demo Code

1
2
3
4
5
6
7
8
id objectOne = @"xx";
id objectTwo = nil;
id objectThree = @"oo";

/*实际上anyArray所指的数组只包括objectOne,arrayWithObjects:会对传入的对象作检查,发现nil会认为数组创建到止结束*/
NSArray *anyArray = [NSArray arrayWithObjects:objectOne, objectTwo, objectThree, nil];
//用字面量创建数组会抛出异常,因为对象中不可包含nil
NSArray *otherArray = @[objectOne, objectTwo, objectThree];

旧Dictionary方法

在OC引入下标前,使用setObject:forKey:方法来替代方括号来对’键-值’进行访问。字典是无序集合

Demo Code

1
2
3
4
/*定义一个可变字典*/
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
/*用方法对指定键进行访问*/
[dictionary setObject: anyObejct forKey: anyKey];

不可修改的对象(NSArray、NSString、NSData…)

  • 不可修改对象的copy方法不会做任何其它操作,仅仅返回指向自己的指针
  • 可修改(Mutable)对象(如:NSMutableArray,NSMutableString…)的copy方法会复制一份自己的拷贝

继承

  • 子类不能访问父类通过@porperty生成的属性,但可以通过调用父类的get,set方法访问父类的属性

    Demo code

    / 在父类.h中定义一个属性 /

    @property (nonatomic) NSMutableArray *array;

    / 在子类中不能直接通过如下方法调用在父类中定义属性方法 /

    [array addObject:@”xxxx”];

    / 但是可以通过其生成的set,get方法来访问属性 /

    [self.array addObject:@”xxxx”]

  • 在@interface中定义的属性默认是保护(protect)的,在@implementation定义的属性默认是私有的
  • 不在.h中声明的方法为私有方法
  • 类工厂方法中用self来alloc,init对象

分类

  • 在分类中所声名的属性与方法都是私有的

instancetype 和 id 区别

instancetype作方法返回值类型,编绎器会结合上下文作类型检查。如返回值的类型与所赋值的类型不一致会给出警告信息。id则不会作任何类型检查,但instancetype只能作为方法返回值类型,id则无此限制。

类方法

  • 类方法可以直接访问类方法
  • 类方法不可以直接调用对象方法
  • 类方法不能访问成员变量

@property 和 @synthesize

单独用@property生成实例变量或者属性时带’ ‘而结合@synthesize时生动生成的实例变量或者属性不带’

Demo Code

1
2
3
4
//在.h中用@property声明一个实例变量
@property int number;
//在.m中用@synthesize实现set,get方法.此生成的是number变量,而不是_number
@sythesize number;

Block 对象

Block对象通会使用外部变量,对于基本变量Block会拷贝变量的值,并使用Block对象的局部变量保存。对于指针变量,Block对象会使用强引用。这意味着凡是Block对象用到的对象,都会被保留。所以在相应的Block对象被释放前,这些对象一定不会被释。这也是Block对象和函数的区别。

assign VS retain and copy

assingn

  • 在用@property生成的set方法中,直接把变量赋值给属性

Demo Code

1
2
3
- (void)setString:(NSString *)newString {
_string = newString;
}

retain

  • 在set方法中会relesae旧的属性并且retain新传进来的属性

Demo Code

1
2
3
4
5
6
-(void)setString:(NSString *)newString {
if (_string != newString) {
[_string release];
_string = [newString retain];
}
}

copy

  • 在set方法中会拷贝一份原始对象赋值给将要set的值,这可以保证你在使用属性的时候不用担心它会被改变

Demo Code

1
2
3
4
5
6
-(void)setString:(NSString *)newString {
if (_string != newString) {
[_string release];
_string = [newString copy];
}
}
  • 如果property是readonly的,在自定义的构造方法中强烈建议用如下方式写

Demo code

1
2
3
4
5
6
initWithFirstName:(NSString *)string {
if ( (self = [super init]) != nil ) {
_lastName = [string copy];
}
return self;
}

KVC and KVO

  • KVC只能传对象值,对于如像int,float等的类型可以通过转换为NSNumber对象

Demo Code

1
[object setValue:value forKey:key]

单例

  • 单例需要重写allocWithZone:方法,因为alloc,new方法最终都会调用到allocWithZone:方法.
  • 在单例模式下自定义的copyWithZone:与mutableCopyWithZone:都只需返回静态的object

Demo Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static DemoClass *object = nil;
+(instancetype)allocWithZone(struct _NSZone *)zone {

/* 多线程访问时会有问题
if (object == nil) {
object = [[super allocWithZone:zone] init];
} */
// 多线程下的正确写法
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
object = [[super allocWithZone:zone] init];
}
);

return object;
}

自定义的copy方法

必让对象继承NSCopying和NSMutableCopying协议,实现协议中copyWithZone:与mutableCopying方法

Demo Code

1
2
3
4
5
6
- (id)copyWithZone:(NSZone *)zone {
//这里用[self class]是因为在对象方法中无法获取到类对象,但能通过class方法可以返回类对象
DemoClass *object = [[[self class] allocWithZone:zone] init];
[object setProperty];
return object;
}