属性(,KVC,nonatomic,atomic,assign,retain,synthesize,readwrite,readonly)

属性(Property)

 

  封装一个学生类, 

        实例变量: name, age 

        自定义初始化方法 

        便利构造器 

        setter, getter 

        重写description方法

Student.h
#import <Foundation/Foundation.h>
@interface Student : NSObject {
    NSString *_name;
    NSInteger _age;
    NSString *_gender;
}
//属性的声明
@property NSString *gender;
- (void)setName:(NSString *)name;
- (NSString *)name;
- (void)setAge:(NSInteger)age;
- (NSInteger)age;
- (instancetype)initWithName:(NSString *)name age:(NSInteger)age;
+ (instancetype)studentWithName:(NSString *)name age:(NSInteger)age;
- (void)show;
@end
Student.m
#import "Student.h"

@implementation Student
//属性的实现
@synthesize gender;
- (void)setName:(NSString *)name {
    _name = name;
}
- (NSString *)name {
    return _name;
}
- (void)setAge:(NSInteger)age {
    _age = age;
}
- (NSInteger)age {
    return _age;
}
- (instancetype)initWithName:(NSString *)name age:(NSInteger)age {
    self = [super self];
    if (self) {
        _name = name;
        _age = age;
    }
    return self;
}
+ (instancetype)studentWithName:(NSString *)name age:(NSInteger)age {
//    Student *stu = [[Student alloc] init];
//    [stu setName:name];
//    [stu setAge:age];
    return [[Student alloc] initWithName:name age:age];
}
- (void)show {
    NSLog(@"name:%@, age:%ld", _name, _age);

}
- (NSString *)description
{
    return [NSString stringWithFormat:@"name:%@, age:%ld", _name, _age];
}
@end
    main.m    
       Student *student = [[Student alloc] initWithName:@"小花" age:18];
        NSLog(@"%@", student);
        //使用自定义的类生成的对象, 打印结果<类名: 地址>
        
        //打印对象的实例变量
        NSLog(@"name:%@, age:%ld", [student name], [student age]);
        
        //封装方法, 快速打印实例变量
        [student show];

        %@打印的实质: 打印度是这个对象调用description方法返回的字符串

        descriptionNSObject中的方法

        NSLog(@"%@", student);
        NSLog(@"%@", [student description]);
点语法
        Student *stu = [[Student alloc] init];
        NSLog(@"%@", stu);
        
通过setter为变量赋值
        [stu setName:@"李思思"];
        [stu setAge:28];
        
通过getter取实例变量的值
        NSLog(@"%@, %ld", [stu name], [stu age]);

        点语法的作用: 快速调用settergetter

        点语法的前提: 必须要有settergetter

        : 点语法出现在=号的左侧, 调用setter, 其他位置调用getter

        stu.name = @"小哇";
        stu.age = 28;
        NSLog(@"%@, %ld", stu.name, stu.age);

        属性: 快速生成settergetter方法

        属性声明

        格式: @property数据类型实例变量名;

        属性实现

        格式:

        @synthesize实例变量名;

        stu.gender = @"";
        NSLog(@"%@", stu.gender);

        定义一个手机类

        实例变量: 品牌, 价格, 颜色

        属性

        重写description

Phone.h
#import <Foundation/Foundation.h>
@interface Phone : NSObject {
//    NSString *_brand;
//    CGFloat _price;
//    NSString *_color;
}
@property NSString *brand, *color;
@property CGFloat price;
@end
Phone.m
#import "Phone.h"
@implementation Phone
//@synthesize brand, price, color;
//如果不写属性的实现, 默认系统补上的形式
//@synthesize  brand = _brand, price = _price, color = _color;
//@synthesize  brand;
//1.自动生成一个实例变量brand;
//2.setter方法和getter方法对实例变量brand进行操作
//@synthesize  brand = _brand;
//1.自动生成一个实例变量_brand;
//2.setter方法和getter方法对实例变量_brand进行操作
- (NSString *)description
{
    return [NSString stringWithFormat:@"brand:%@ price:%.2f color:%@", _brand, _price, _color];
}
@end
main.m
        Phone *phone = [[Phone alloc] init];
        phone.brand = @"iPhone 6s";
        phone.price = 1998;
        phone.color = @"土豪金";
        NSLog(@"%@", phone);

 属性的优化

        1.属性声明的优化, 如果数据类型相同, 可以写在一行, 用逗号隔开

        : 对象要加*

        2,属性实现的优化: 多个属性实现可以写在一行, 用逗号隔开

        3.属性的实现部分是可以省略的, 系统自动补上属性的实现部分

        4.实例变量可以省略, 属性会自动补上实例变量

 封装一个猫类

        实例: 姓名, 品种, 年龄, 颜色

Cat.h
#import <Foundation/Foundation.h>
@interface Cat : NSObject
@property (nonatomic, retain) NSString *name, *type, *color;
@property (nonatomic)NSInteger age;
//苹果的习惯: 如果属性是BOOL类型, 一般会修改getter方法的名字, 改成"is+实例变量"
@property (nonatomic, getter=isSame) BOOL same;
@end
Cat.m
#import "Cat.h"
@implementation Cat
- (NSString *)description
{
    return [NSString stringWithFormat:@"name:%@ type:%@ age:%ld color:%@", _name, _type, _age, _color];
}
@end

  属性的修饰词

        作用: 管理和控制settergetter

  1.多线程组

        a. atomic: 原子性, 同一时刻只能执行一种操作(gettersetter), 安全性高, 执行效率比较低, 一般用于多线程, 默认值

        b. nonatomic: 非原子性的, 同一时刻能执行多种操作(gettersetter), 执行效率高

        : 一般优先写nonatomic, 多线程下为了安全起见, 才写atomic

2.内存管理组

        a. assign: 基本数据类型(int, char, float, double, long, short, BOOL, NSInteger, CGFloat), 默认值

        b. retain: 对象

        c. copy: 对象, 必须遵守<NSCopying>协议

3.读写组

        a. readwrite: 读写, 会生成settergetter, 默认值

        b. readonly: 只读, 只生成getter

4.方法重命名组

        a. setter=名字

        b. getter=名字

KVC: key-value coding, 键值编码, 提供了一种间接访问属性的方式

Game.h
#import <Foundation/Foundation.h>
@interface Game : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic) CGFloat time;
@property (nonatomic) NSInteger count;
@end
Game.m
#import "Game.h"
@implementation Game
- (NSString *)description
{
    return [NSString stringWithFormat:@"name:%@ time:%.2f count:%ld", _name, _time, _count];
}
@end
main.m
        //setter
        [game setName:@"双升"];
        NSLog(@"%@", [game name]);
        //点语法
        game.name = @"斗地主";
        NSLog(@"%@", game.name);
        
        //间接访问(KVC)
        [game setValue:@"接竹竿" forKey:@"name"];
        NSLog(@"%@", [game valueForKey:@"name"]);
        //注: key内填写属性名

 KVC检索的过程

        1.getter,  setter

        2.实例变量_<key>, <key>

        3.setValue:forUndefinedKey:, valueForUndefinedKey

Boy.h
#import <Foundation/Foundation.h>
//在外部访问实例变量, 有哪些途径
//1. @public, 通过->访问
//2. setter, getter
//3. KVC
@interface Boy : NSObject {
    NSString *_name;
    NSInteger _number;
}
@end
Boy.m
#import "Boy.h"
@implementation Boy
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    NSLog(@"value:%@ key:%@", value, key);
    
}
- (id)valueForUndefinedKey:(NSString *)key {
    return nil;
}
@end
main.m
        Boy *boy = [[Boy alloc] init];
        [boy setValue:@"李磊" forKey:@"name"];
        NSLog(@"%@", [boy valueForKey:@"name"]);     
        [boy setValue:@"18" forKey:@"age"];
        NSLog(@"%@", [boy valueForKey:@"age"]);    
        [boy setValue:@15 forKey:@"number"];
        NSLog(@"%@", [boy valueForKey:@"number"]); 
        Boy *boy1 = [[Boy alloc] init];
        [boy1 setValuesForKeysWithDictionary:@{@"name": @"韩梅梅", @"number": @19}];
        NSLog(@"%@ %@", [boy1 valueForKey:@"name"], [boy1 valueForKey:@"number"]);

属性中出现的问题

Girl.h
#import <Foundation/Foundation.h>
@interface Girl : NSObject
@property (nonatomic) NSInteger age;
@end
Girl.m
#import "Girl.h"
@implementation Girl
//当同时重写了setter和getter方法后, @synthesize age = _age;就失效了
//解决方案: 自己补上@synthesize age = _age;
@synthesize age = _age;
//当属性生成的setter方法不满足需求时, 可以重写setter方法
- (void)setAge:(NSInteger)age {
    if (age > _age) {
        _age = age;
    }
}
//当属性生成的getter方法不满足需求时, 可以重写setter方法
- (NSInteger)age {
    return  _age - 2;
}
@end
main.m
        Girl *girl = [[Girl alloc] init];
        girl.age = 17;
        NSLog(@"%ld", girl.age);
        //每次赋值的年龄都大于上一次
        girl.age = 10;
        NSLog(@"%ld", girl.age);

 

 

 

 

The one who wants to wear a crown must bear the weight!
原文地址:https://www.cnblogs.com/OrangesChen/p/4866110.html