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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© gd32376300 中级黑马   /  2015-12-10 17:06  /  865 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

1 @property 参数(二)     // 重点掌握   
A.是否要生成set方法( 若为只读属性,则不生成)
readonly:只读,只会生成getter的声明和实现
readwrite:默认的,同时生成setter和getter的声明和实现


2.多线程管理(苹果在一定程度上屏蔽了多线程操作)
nonatomic :高性能,一般使用这个     // 一般使用nonatomic
atomic :低性能,默认

3.set和get方法的名称
修改set和get方法的名称,主要用于布尔类型.因为返回布尔类型的方法名一般以is开头,修改名称一般用在布尔类型中的getter.

@property (nonatomic ,assign,setter=haha:,getter=abc) int age
可以理解为把[p setAge:haha]---->[p abc:], [p age]->[p haha];

@property (nonatomic ,assign,setter=setVip:,getter=isVip) BOOL vip;
用法:设置值 [ person setVip:YES];  获取值 BOOL vip=[person isVip];


1.@class 的使用格式: @class 加类名 :     // 重点
含义: 告诉编译器, Dog 是一个类,至于类有哪些属性和方法,并没有检查.
好处:如果Dog文件内容发生了改变,而不需要重新编译.

2.具体使用
在.h 文件中使用@class引用一个类
在.m 文件中使用#import包含这个类的.h文件

#import "B.h"
@interface A :NSObject {
B *b;
}
end

为了简单起见: A类是引用类,B类是被引用类,这里先不考虑A类的实现文件.

通常引用一个类有两种方法: 一种是通过#import 方式引入; 另一种是通过@class引入

6.两种方式的区别是什么?   //   面试题
1.作用上的区别  2.效率上的区别
A.#import方法会包含被引用类的所有信息,包括被引用类的变量和方法

B.使用@class方式由于只需要被引用类(B类)的名称就可以了,而在实现类由于要用到被引用类中的实体变量和方法,所有需要使用#import来包含被引用类的头文件.

C.一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,这样的效率也是可想而知的.

7.对于循环依赖关系来说,比方A类引用B类,同时B类也引用A类



8.循环retain问题
@class Person;
@interface Dog :NSObject
@property(nonatomic,retain) Person *owner;
@end
#import <Foundation/Foundation.h>
@class Dog;
@interface Person :NSObject
@property (nonatomic ,assign) Dog *dog;
@end
Dog *d=[ Dog new];
Person *p=[Person new];

循环retain的场景 ,比如A对象retain了B对象,B对象retain了A对象
循环retain的弊端,这样会导致A对象和B对象永远无法释放

循环retain的解决方案
当两端互相引用时,应该一端用retain,一端用assign

9.autorelease是什么?
答:A.在ios程序运行过程中,会创建无数个池子,这些池子都是以栈结构(先进后出)存在的. B. 当一个对象调用autorelease时,会将这个对象放到位于栈顶的释放池中.

10. 为什么会有autorelease?
答:OC的内存管理机制中比较重要的一条规律是:谁申请,谁释放.

11.使用autorelease的好处
a.不需要再关心对象释放的时间  b.不需要关心什么时候调用release

12.autorelease基本用法
a. 会将对象放到一个自动释放池中
b. 当自动释放池被销毁时,会对池子里的所有对象做一次release
c.  会返回对象本身
d. 调用完autorelease方法后,对象的计数器不受影响(销毁时影响)

13.autorelease 什么时候被释放?
a.手动释放autorelease pool         b.run loop 结束后自动释放
#import "Person.h"
int main( ){
// 创建自动释放池
Person *p= [ Person new] ;    // p  = 1
@autoreleasepool {
[p run];
NSLog(@" %lu",p.retainCount);   // 1
//  p autorelease ] 把对象p加入到自动释放池中
// 注意:加入到自动释放池中以后,引用计算不会变化
[p autorelease];   // 加入自动释放池
NSLog(@"%lu",p.retainCount);   // 1
[p run];
}
return 0;
}

14.[掌握] autorelease 使用注意:
a. 并不是放到自动释放池代码中,都会自动加入到自动释放池,因为没有调用 autoreleaase方法.
b. 自动释放池的嵌套使用
c. 自动释放池中不适宜放占用内存比较大的对象

15.autorelease的应用场景:经常用来在类方法中快速创建一个对象.
16.完善快速创建对象的方法: instancetype 可以智能判断返回的类型和接受的类型是否一致.

int main( ){
NSString *str=[NSString stringWithForma:@"xxx"];
NSArray * array =[NSArry array ];
NSDictionary *dic= [NSDictionary dictionary]   // 系统数组字典,快速创建方法
Person *p= [Person person];
//1.  创建一个对象  p
// 2. 用完之后,系统把对象释放掉 p
Person *p =[[ Person alloc] init];
[ p autorelease];


17.构造方法特点
初始化 --->构造方法 init
          --->自定义构造方法
// new 方法执行两个方法
1.+ alloc :去给对象分配一块内存空间
2. -init :初始化这个对象

// 下面两步操作等效于:[Person new];
  // Person *per1= [Person alloc];
// Person *per2 =[per1 init] ;

等效于上面两步,方法的级连调用.
Person *per3=[[Person alloc]init];
per3.age=10;
NSLog(@"%d",Per3.age);
      1) 对象
      2) 返回值是id或者 instancetype
      3) initWithXXX
id 指针的用法: 是一个指针,这个指针的类型是id类型.
作用:可以表示任意的OC对象的指针--万能指针,等效于:NSObject *;
注意: id不用加 *, 其里面已经封装好了,相对于id==NSObject *
        访问指向类对象的独有方法时,必须要强转.
id per2=[Person new];
((Person *)per2).name=@"张山";
NSLog(@"%@",((Person *)Per2).name);



#import "Student.h"
@implementation Student
-(void) dealloc
{
  
   NSLog(@" Student dealloc");    // 快速创建
   [super dealloc] ; // 调用父类方法 释放
}
+(instancetype)personWithAge:(int)age{
    return [[[ self alloc] initWithAge :age] autorelease];
}
-(instancetype)initWithAge:(int)age{    // 自定义一个构造方法
if (self =[super init])  {  }         // 先初始化父类的,并且判断是否初始化成功


18. 指针分类     
1)  强指针 : 默认的情况下,所有的指针都是强指针, 关键字 strong
2) 弱指针: _ _weak 关键字修饰的指针  
    声明一个弱指针如下: _ _ weak Person *p;

1 个回复

倒序浏览
非常好, 学习了!   
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马