@property 4.4前
@property 4.4增强 .h
// 基本数据类型
int _age;
// set方法的写法
-(void)setAge:(int) age
{
_age = age;
}
// 用assign修饰后,仍旧会生成以上标准的set方法
@property (assign) int age;
// oc对象类型
@property (retain) Car *car ;
// 用retain修饰后,生成如下内存管理代码
-(void)setCar:(int) car
{
if(_car ! = car)
{
[_car release];
_car = [car retain];
}
}
1.内存管理相关参数
验证assign如果作用在对象上,实际上就是直接赋值
//使用@property增强型 生成get和set方法
@property(nonatomic,assign)Car *car;
//.m文件中实际上生成的是
- (void)setCar:(Car *)cat
{
_car = car; //当对象release后,将无法使用该对象
}
// main函数
int main()
{
Person *p = [Person new];
Car *c = [Car new];
// 给人一辆车
p.car = c;
// 释放车
[c release];
// 让人开车
[p drive]; //此时p指向了僵尸对象
}
//使用@property增强型 生成get和set方法
@property(nonatomic,retain)Car *car;
//.m文件中实际上生成的是
- (void)setCar:(Car *)cat
{
if(_car != car)
{
[_car release];
_car = [car retain];
}
}
// main函数
int main()
{
Person *p = [Person new];
Car *c = [Car new];
// 给人一辆车
p.car = c;
// 释放车
[c release];
// 让人开车
[p drive];
}
- (void)dealloc
{
NSLog(@"Person -- dealloc");
[_car release];
[super dealloc];
}
1、是否要生成set方法(若为只读属性,则不生成)
2.多线程管理(苹果在一定程度上屏蔽了多线程操作)
atomic:低性能,默认
atomic是Objc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。
3.set和get方法的名称
控制set方法和get方法的名称
setter : 设置set方法的名称,一定有个冒号:
getter : 设置get方法的名称
@property(nonatomic,assign, setter=abc:,getter=haha)int age
可以理解为:
“`objc
@property(nonatomic,assign, setter=setVip:,getter=isVip) BOOL vip;
![](http://img.blog.csdn.net/20161009213635575)
* 用法: 设置值
![](http://img.blog.csdn.net/20161009213720825)
* 获取值
![](http://img.blog.csdn.net/20161009213749107)
##12、【理解】应用:电商App练习
####电商App类的设计
* 要求:利用OC+面向对象设计下面的三个类:
* 一、商品类-Goods
* 属性: 商品名称
* 单价
* 重量
* 商品展示图片
* 生产日期(暂时用结构体表示)produceDate
* 过期日期 expireDate
* 二、买家类(用户) Buyer
* 属性:
* 姓名
* 性别(枚举)
* 年龄
* 身高(单位:cm)
* 三、卖家类 - Seller
* 属性:
* 姓名
* 性别(枚举)
* 年龄
* 身高(单位:cm)
* 所出售商品(假设一个卖家就卖一件商品)
* 四、买家类、卖家类(抽象父类Person)
* 五、在main函数中创建卖家、商品、买家类的对象。
```objc
// 创建一个表示日期时间的结构体
typedef struct
{
int hour;
int min;
int sec;
}Time;
//表示日期
typedef struct{
int year;
int month;
int day;
Time time;
}MyDate;
MyDate produceDate = (MyDate){2011, 9, 10, {15, 16, 30}}; //注意,这句话是错误的
"se-preview-section-delimiter">
// 创建一个表示性别的枚举
typedef enum
{
GenderMale, // 男
GenderFemale // 女
} Gender;
![](image1/12.1.png)
* 原因是:
* goods.expireDate----->得到这个成员expireDate的值,是结构体类型
* expireDate.Time 这是访问结构体变量,time的值
* goods.expireDate.time 会被误认为是点语法,导致出错
```objc
// 创建一个表示性别的枚举
typedef enum
{
GenderMale, // 男
GenderFemale // 女
} Gender;
<div class="se-preview-section-delimiter">div>
具体使用
如下面代码:
A.h文件
#import "B.h"
@interface A : NSObject
{
B *b;
}
@end
通常引用一个类有两种办法:
这两种的方式的区别在于:
1)#import方式会包含被引用类的所有信息,包括被引用类的变量和方法;@class方式只是告诉编译器在 A.h文件中 B *b只是类的声明,具体这个类里有什么信息,这里不需要知道,等实现文件中真正要用到时,才会真正去查看B类中信息;
2)使用@class方式由于只需要知道被引用类(B类)的名称就可以了,而在实现类由于要用到被引用类中的实体变量和方法,所以需要使用#import来包含被引用类的头文件;
3)通过上面2点也很容易知道在编译效率上,如果有上百个头文件都#import了同一个文件,或者这些文件依次被#improt(A->B, B->C,C->D…),一旦最开始的头文件稍有改动,后面引用到这个文件的所有类 都需要重新编译一遍,这样的效率也是可想而知的.而相对来讲,使用@class方式就不会出现这种问题了;
所以:我们实际开发中尽量在.h头文件中使用@class
* 把其中的一个头文件中的import换成@class
* 面试题:#import和@class的区别。
* 作用上的区别
* import会包含引用类的所有信息(内容),包括引用类的变量和方法 @class仅仅是告诉编译器有这么一个类,具体这个类里有什么信息,完全不知道。
* 效率上的区别
* 如果有上百个头文件都#import了同一个文件,或者这些文件依次被#import,那么一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,编译效率非常低相对来讲,使用@class方式就不会出现这种问题了。
##13、【理解】@class的使用
* 场景
![](http://img.blog.csdn.net/20161009214217550)
####1.@class的使用
* 作用
* 可以简单地引用一个类
* 简单使用
* @class Dog; //类的引入
* 仅仅是告诉编译器:Dog是一个类;并不会包含Dog这个类的所有内容
* 具体使用
* 在.h文件中使用@class引用一个类
* 在.m文件中使用#import包含这个类的.h文件
* 如下面代码:
```objc
A.h文件
#import "B.h"
@interface A : NSObject
{
B *b;
}
@end
class="se-preview-section-delimiter">
通常引用一个类有两种办法:
这两种的方式的区别在于:
1)#import方式会包含被引用类的所有信息,包括被引用类的变量和方法;@class方式只是告诉编译器在 A.h文件中 B *b只是类的声明,具体这个类里有什么信息,这里不需要知道,等实现文件中真正要用到时,才会真正去查看B类中信息;
2)使用@class方式由于只需要知道被引用类(B类)的名称就可以了,而在实现类由于要用到被引用类中的实体变量和方法,所以需要使用#import来包含被引用类的头文件;
3)通过上面2点也很容易知道在编译效率上,如果有上百个头文件都#import了同一个文件,或者这些文件依次被#improt(A->B, B->C,C->D…),一旦最开始的头文件稍有改动,后面引用到这个文件的所有类 都需要重新编译一遍,这样的效率也是可想而知的.而相对来讲,使用@class方式就不会出现这种问题了;
所以:我们实际开发中尽量在.h头文件中使用@class
class "Dog.h";
@interface Person :NSObject
@property(nonatomic,retain)Dog *dog;
@end
@class "Person.h";
@interface Dog:NSObject
@property(nonatomic,retain)Person *owner;
@end
//main.m
//创建对象
Dog *d = [Dog new];
Person *p = [Person new];
//循环引用
p.dog = d;
d.owner = p;
//看似正确的释放代码
[d release];
[p release];
class="se-preview-section-delimiter">
程序执行结果: p和d都没有被释放掉
原理分析:
p.dog = d; //因为dog的set方法中是 进行了 [dog retain];dog2
d.owner = p;//会让p的引用计数+1 owner2
当执行了
[d release];
[p release];
dog和owner 的引用计数变成1
如图:
循环retain的场景
循环retain的解决方案
* 程序执行结果: p和d都没有被释放掉
* 原理分析:
![](http://img.blog.csdn.net/20161009215834728)
```objc
p.dog = d; //因为dog的set方法中是 进行了 [dog retain];dog2
d.owner = p;//会让p的引用计数+1 owner2
当执行了
[d release];
[p release];
dog和owner 的引用计数变成1