黑马程序员——@property及其参数的详解

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------

@property详解

1.什么是@property?

@property是OC特有的一个关键字,它属于编译器一个特性,编译器碰到@property时,会自动展开为成员变量的set和get方法

在Xcode4.5之前,Xcode编译器碰到@property会将其转换为成员变量set、get方法的声明,碰到@synthesize会展开为成员变量set、get方法的实现,所以XCode4.5之前,@property与@synthesize是配对使用。在Xcode4.5以后,Xcode碰到@property关键字,其将自动帮我们转换为(成员变量的声明、相应set、get方法的声明与实现)。

2.我们怎么使用@property?

代码解释:

我们手动写的代码(关闭ARC机制):

@interface Person : NSObject
{
    NSString *_name;
}
- (void) setName:(NSString *)name;
- (NSString *) name;
@end

@implementation Person
-(void)setName:(NSString *)name
{
    if (_name != name) {
        [_name release];
        _name = [name retain];
    }
}
-(NSString *)name
{
    return _name;
}

-(void)dealloc
{
    [_name release];
    [super dealloc];
}
@end

Xcode4.5之前,利用@property与@synthesize配对写的代码

//Xcode 4.5以下的写法
@interface Person :NSObject

@property NSString *name;
/*
 *@property NSString *name;这句展开为:
 *{
 *  NSString *_name;
 *}
 *- (void) setName:(NSString *)name;
 *- (NSString *) name;
 */
@end

@implementation Person

@synthesize name = _name;//这里必须要写 =_name,否则展开的代码会自动创建一个私有变量:NSString *name;(其他类不可访问(包括子类))

/*@synthesize name = _name;这句展开如下:(展开的是不符合内存管理的)
 *-(void)setName:(NSString *)name
 *{
 *  _name = name;
 *}
 *-(NSString *)name
 *{
 *   return _name;
 *}
 */

@end

Xcode 4.5之后的写法,只用关键字@property:

#import <Foundation/Foundation.h>
//Xcode 4.5以上的写法
@interface Person : NSObject

@property NSString *name;
  /*
  *@property NSString *name;这句在@interface中展开有:
  *{
  *  NSString *_name;
  *}
  *- (void) setName:(NSString *)name;
  *- (NSString *) name;
  *
  *@property NSString *name;这句在@implementation中展开有:
  *
  *-(void)setName:(NSString *)name
  *{
  *  _name = name;
  *}
  *-(NSString *)name
  *{
  *   return _name;
  *}
  */

@end

@implementation Person
//Xcode4.5往后,都不用写@synthesize
@end

@propert的相关参数

[email protected]有哪些参数?

第一组:retain  assign  copy  strong    weak     unsafe_unretained     autoreleasing

第二组:readwrite  readonly

第三组:nonatomic  atomic

第四组:setter  getter

2.参数分别有何作用?

①参数说明

第一组(retain  assign  copy   strong    weak     unsafe_unretained     autoreleasing)用于:set方法内存管理

assign(默认参数):生成直接赋值的set方法(不考虑内存管理),适用于非OC对象(基本数据类型、复合数据类型)

retain:生成符合内存管理的set方法(release旧值,retain新值),适用于OC对象的成员变量

copy:生成符合内存管理的set方法(release旧值,copy新值),适用于NSString、NSArray等不可变对象。

Strong:强引用,决定了对象的存亡(一个对象如果没有强指针指向(引用计数器为0)时,对象将被销毁,释放内存),其指向一个对象,相当于该对象做了一次retain操作。适用于OC对象

weak:弱引用,其存在与否无所谓(弱指针指向对象与否(对象引用计算器不变)),适用于OC对象

unsafe_unretained:请查看:浪天涯的博客

注意:

weak与Strong一般在开启ARC机制下使用

Strong:强引用,决定了对象的存亡(一个对象如果没有强指针指向(引用计数器为0)时,对象将被销毁,释放内存),其指向一个对象,相当于该对象做了一次retain操作。

非ARC的retain,相当于ARC的strong,弱引用相当于assign

使用copy参数与使用retain参数产生的set方法一致(将生成set方法中的retain改为copy即可)

第二组(readwrite  readonly)用于:是否要生成set方法

readwrite(默认参数):同时生成set、get方法的声明与实现

readonly:只生成get方法的声明与实现(不生成set的方法的声明与实现)

第三组(nonatomic  atomic)用于:多线程管理

atomic(默认参数):原子性,性能低(一般开发OC中的APP不推荐使用,做金融等高安全的时候使用)

nonatomic:非原子性,性能高(强烈推荐使用,性能高)

atomic:(原子性操作)就是一个操作执行过程不能被中断, 要不就执行完, 要不就不执行(一个操作不可以被中途cpu暂停然后调度)。如果一个操作是原子性的,
那么在多线程环境下, 就不会出现变量被修改等奇怪的问题(保证数据同步)。原子操作就是不可再分的操作,在多线程程序中原子操作是一个非常重要的概念,它常常用来实现一些同步机制,同时也是一些常见的多线程Bug的源头。

nonatomic:(非原子性操作)操作是直接从内存中取数值(不考虑其是否被占用),因为它是从内存中取得数据,它并没有一个加锁的保护来用于cpu中的寄存器计算Value,它只是单纯的从内存地址中,当前的内存存储的数据结果来进行使用。在多线程环境下可提高性能,但无法保证数据同步。

第四组(setter  getter)用于:set、get方法重命名(常用于BOOL类型的成员变量的get方法,BOOL方法常以is开头(set方法很少用))

setter:给成员变量的set方法重命名,set方法默认命名:- (void) set成员变量名(成员变量名首字母大写):(成员变量数据类型)成员变量名

getter:给成员变量的set方法重命名,get方法默认命名:- (成员变量数据类型) 成员变量名

②代码证明

参数实例示范: 

main.m文件

/*
 *第一组:retain  assign  copy  strong    weak
 *第二组:readwrite  readonly
 *第三组:nonatomic  atomic
 *第四组:setter  getter
 */
#import <Foundation/Foundation.h>
#import "Student.h"
#import "Book.h"
int main(int argc, const char * argv[]) {
    Student *stu = [[Student alloc]init];
    Book *b = [[Book alloc]init];
    Book *b1 = [[Book alloc]init];
    /*******验证retain与assign********/
    NSLog(@"b = %ld",[b retainCount]);
    NSLog(@"b1 = %ld",[b1 retainCount]);
    stu.book = b;
    stu.book1 = b1;
    NSLog(@"book(参数:retain)使用后b = %ld",[b retainCount]);
    NSLog(@"book1(参数:assign)使用后b1 = %ld",[b1 retainCount]);

    /***********验证readonly*****************/
    //stu.age = 10;调用setAge方法报错,setAge方法不存在,说明没有生成setAge方法
    //可以输出stu中age的值,说明生成了get方法
    NSLog(@"Student age is %i",stu.age);
    /***********验证setter与getter****************/
    //可以调用stu的isMan方法,而我们又没有写setIsMan方法,说明重命名成功
    stu.isMan = YES;
    NSLog(@"%d",stu.isMan);

    [b1 release];
    [b release];
    [stu release];
    return 0;
}

Student.h文件

/*在非ARC(关闭ARC)下验证:
 *第一组:retain  assign  copy  strong    weak
 *第二组:readwrite  readonly
 *第三组:nonatomic  atomic
 *第四组:setter  getter
 */
#import <Foundation/Foundation.h>
@class Book;
@interface Student : NSObject

/***********验证retain*************/
@property (nonatomic,retain,readwrite) Book *book;
/*以上使用retain参数,展开的set实现方法为:
 *- (void) setBook:(Book *)book
 *{
 *  if(_book != book)
 *  {
 *    [_book release];
 *    _book = [book retain];
 *   }
 *}
**/

/***********验证assign*************/
@property (nonatomic,assign,readwrite) Book *book1;
/*以上使用retain参数,展开的set实现方法为:
 *- (void) setBook:(Book *)book
 *{
 *    _book = book;
 *}
 **/

/***********验证readonly*************/
@property (nonatomic,assign,readonly) int age;
/*以上使用readonly参数,只生成get方法:
 *- (int) age;
 *{
 *  return _age;
 *}
 **/

/***********验证setter与getter*************/
@property (nonatomic,assign,readwrite,setter=setIsMan:,getter=isMan) BOOL man;
/*以上使用setter参数,只生成set方法名被修改为:isMan
 *- (void) isMan:(BOOL)man;(默认方法名为:man)
 *{
 *  _man = man;
 *}
 *
 *以上使用getter参数,只生成get方法名被修改为:isMan
 *- (BOOL) isMan;(默认方法名为:man)
 *{
 *  return _man;
 *}
 **/

@end

Student.m文件

#import "Student.h"
#import "Book.h"
@implementation Student

-(void)dealloc
{
    [_book release];
    NSLog(@"Student被销毁!!");
    [super dealloc];
}
@end

Book.h文件

#import <Foundation/Foundation.h>

@interface Book : NSObject
@property (nonatomic,copy,readwrite) NSString *name;
@end

Book.m文件

#import "Book.h"

@implementation Book
-(void)dealloc
{
    [_name release];
    NSLog(@"book被销毁!!");
    [super dealloc];
}
@end

参数结果输出: 

2015-05-01 12:02:53.108 [email protected]及其参数[2364:221860] b = 1
2015-05-01 12:02:53.109 [email protected]及其参数[2364:221860] b1 = 1
2015-05-01 12:02:53.109 [email protected]及其参数[2364:221860] book(参数:retain)使用后b = 2
2015-05-01 12:02:53.110 [email protected]及其参数[2364:221860] book1(参数:assign)使用后b1 = 1
2015-05-01 12:02:53.110 [email protected]及其参数[2364:221860] Student age is 0
2015-05-01 12:02:53.110 [email protected]及其参数[2364:221860] 1
2015-05-01 12:02:53.110 [email protected]及其参数[2364:221860] book被销毁!!
2015-05-01 12:02:53.110 [email protected]及其参数[2364:221860] book被销毁!!
2015-05-01 12:02:53.110 [email protected]及其参数[2364:221860] Student被销毁!!
时间: 2024-10-10 02:46:10

黑马程序员——@property及其参数的详解的相关文章

黑马程序员---Java多线程的用法详解

------- android培训.java培训.期待与您交流! ---------- Java线程详解 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程.比如在Windows系统中,一个运行的exe就是一个进程. 线程是指进程中的一个执行流程,一个进程中可以运行多个线程.比如java.exe进程中可以运行很多线程.线程总是属于某个进程,进程中的多个线程

黑马程序员_ Objective-c 面向对象笔记详解

1)类,对象,方法 类 类名: 1) 类名的第一个字母必须是大写 2) 不能有下划线 3) 多个英文单词,用驼峰标识 类的声明和实现 类的声明 @interface 类名 : NSObject { @public 成员变量: } 方法声明; @end 类的实现 @implementation 类名 方法实现; @end 举例说明: view plaincopy //Horse类的声明 @interface Horse : NSObject { @public //使成员变量可以让外部访问 //定

黑马程序员——c语言学习—作用域详解

-----------Java培训.Android培训.IOS培训..Net培训.期待与您交流!------------ 本节我们系统学习一下c语言中的变量类型及作用域. 1.全局变量 全局变量是在从定义开始,到整个程序结束都存在的变量,他是在所有函数体的外面定义的变量,存储在静态存储区,所有的代码都可以访问,定义如下: #include <stdio.h> int a; // 定义全局变量 int main() { a = 10; // 函数内可以访问 return 0; } 需要注意的是,

黑马程序员——字符流的缓冲区详解

import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class Demo1 { /** * @param args * 字符流的缓冲区 * BufferedWriter * BufferedReader * 缓冲区要结合流才可以使用 * 在流的基础上对流动功能进行增强 * * 缓冲区的出现是为了提高,流的操作效率而出现的 * 所以在创建缓冲区之前,必须要先有流对象

黑马程序员-张老师基础加强4-注解

注解: 注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事.标记可以加在包,类,字段,方法,方法的参数以及局部变量上. 注解: @interface A{ } 应用了注解的类: @ class B{ } 对应用了注解的类记性反射操作 class C{ B.class.isAnnotionPresent(A.class); A a = B.

黑马程序员[email&#160;protected]和@synsthesize的使用

一.@property和@synthesize的基本使用 @property :可以自动生成某个成员变量的setter和getter的声明(@property int age;).写在@interface里面: @synthesize :自动生成age的setter和getter,并且在方法内部访问的是_age这个成员变量(@synthesize age = _age; // 如果后面不写=_age默认就是访问age成员变量).写在@implementation里面: 二.@property和@

黑马程序员-OC内存管理 @property的增强

涉及到内存管理,只读,多线程等很多功能时,setter和getter方法也就没那么简单了:当然@property依然强大,很好用: 1:内存管理相关参数: *:retain:  (如果是oc对象类型),生成的setter会自动release旧值,retain新值: *:assign:(适用于非oc对象)  这个是默认的值 *:copy:release旧值,copy新值: @property (retain) NSString *name; // 同类型的参数不能同时写 // @property

黑马程序员_OC学习笔记之@property和@synthesize

[objc] view plaincopyprint? <span style="font-size:24px;">#import <Foundation/Foundation.h> @interface Person : NSObject { int _age; int age; int _height; int height; int _weight; int weight; int _money; int money; } @property int ag

黑马程序员_浅谈out参数、ref参数和可变参数

1.out参数 out关键字会导致参数通过引用来传递,通俗点说,就是往外传值的. out参数的作用:用于以内部变量为外部变量赋值的,out一般适用于某个方法不只是使用return返回单个值,而是需要有多个返回值的情况. out参数的使用需要注意以下几点:  1)out参数传递的变量在传递之前不需要对其进行初始化. 分析:在调用方法之前,对out参数传递的变量只需声明,可以赋值也可以不赋值,不过反正都是要在调用时被覆盖掉,所以大可不必赋值,因为赋值了虽然不会报错,但却根本也没有用处,没必要多此一举