A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© silenCetestifY 中级黑马   /  2016-2-17 10:44  /  930 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

假设这时候Student类里有很多对象做属性,那么代码是这样:
#import "Student.h"
#import "Book.h"
#import "Card.h"
@implementation Student
-(void)setBook:(Book *)book{
    if (_book != book){
        [_book release];
        _book = [book retain];
    }
}
-(void)setCard:(Card *)card{
    if (_card != card){
        [_card release];
        _card = [card retain];
    }
}
-(void)dealloc{
    [_book release];
    [_card release];
    [super dealloc];
}
@end
这些内存管理的set方法太啰嗦了,所以可以不手写这些set方法,而在属性定义的时候这样:
@class Book;
@class Card;
@interface Student : NSObject
@property (retain) Book *book;
@property (retain) Card *card;
@end
这里的retain代表先release旧值,然后retain新值,就不用写内存安全的成员对象的set方法了。所以所有OC对象最好都这么写,但是如果不写,就会生成不管理内存的标准getset方法。
对于常量类型的成员变量,有这样的写法:
@property (assign) int age;
这个assign可以不写,默认就是这样,而且不能写retain,非OC对象不需要管理内存。
Property后面可以带多个参数,用逗号间隔,比如:
@property (nonatomic,retain) Card *card;
这里可以写的属性有三种:
getter的处理:readwrite(默认)/readonly(只生成get方法),
setter的处理:assign(默认,直接赋值)/retain(先释放后ratain/copy(先释放后copy),
原子性:atomic(默认,给getset方法加锁,线程安全)/nonatomic(禁止多线程保护,性能更好)。通常iphone开发不考虑线程安全。
对于BOOL类型,需要保证get方法变成IsXxxx,需要加上参数:
@property (nonatomic, getter = isRich) BOOL rich;
OC有自动释放池机制,这与java垃圾回收不同,在池子释放时,会对池子里所有的对象调用一次release方法(并不是销毁)。OC对象只要发送一条autorelease消息,OC就会把这个对象添加到释放池当中。所以说autorelease实际是把对象的释放延迟到池子释放了,但是它并不会改变计数器。
最常用的写法是:
    @autoreleasepool {
        Student *stu = [[[Student alloc]init]autorelease];
    }
OC中有一个潜规则,用来快速创建一个对象的静态方法和类名相同,而且静态方法都自动释放,比如有一个创建Student的静态方法:
@interface Student : NSObject
+(id)student;
@end
实现的时候一定要注意自动释放:
+(id)student {
    return [[[Student alloc]init]autorelease];
}
静态方法一般都不需要我们手动来管理内存。
注意点:
ARC下,只能使用@符号创建一个释放池。
不要把大量循环操作放在释放池下,因为这会导致大量循环内的对象没有被回收,这种情况下应该手动写release代码。
尽量避免对大内存对象使用autorelease,否则会延迟大内存的回收。
ios中很多对象都已经自动释放了,不需要手动再release
Category(分类)可以动态地给已经存在的类添加方法,类似C#的扩展方法。需要新建一个文件,类型是OCcategory,在Category on当中选择目标类,会生成类名+分类名”.h.m两个文件,生成的类名右边括号里就是分类名。需要注意的是这个类的.h文件里必须import原始类,不能@class,原因是要知道原先类里有什么方法。
#import "Student.h"
@interface Student (Test)
-(void)test2;
@end
#import "Student+Test.h"
@implementation Student (Test)
-(void)test2{
    NSLog(@"调用了test2方法");
}
@end
#import <Foundation/Foundation.h>
#import "Student.h"
#import "Student+Test.h"
int main(int argc, const char * argv[])
{
    @autoreleasepool {
        Student *stu = [Student student];
        [stu test2];
    }
    return 0;
}

1 个回复

倒序浏览
沙发!!!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马