zoukankan      html  css  js  c++  java
  • iOS学习笔记---oc语言第八天

    属性

    能在一定程度上简化代码,并且增强实例变量的访问安全性

    属性的声明:使用@property声明属性  eg:@property NSSstring *name;相当于@interface中声明了两个方法

    - (void)setName:(NSString *)name;

    - (NSString *)name;

    属性的实现:使用@synthesize实现属性 ,eg:@synthesize name = _name;

    相当于@implementation 实现了

    - (void)setName:(NSString *)name;

    - (NSString *)name;

    //Person.h
    @interface Person : NSObject
    {
        NSString *_name;   //姓名
        NSInteger _age;    //年龄
        CGFloat _score;
        NSString *_sex;
    }
    @property CGFloat score;
    //可以把相同类型的属性放在同一行进行声明,但是通常分开写
    @property NSString *name,*sex;
    //等价于下面两行
    //- (void)setName:(NSString *)name;//设置名字
    //- (NSString *)name;//获得名字
    
    @property NSInteger age;
    //等价于下面两行
    //- (void)setAge:(NSInteger)age;//设置年龄
    //- (NSInteger)age;//获得年龄
    @end
    //Person.m
    #import "Person.h"
    
    @implementation Person
    //=号前面是你声明的属性
    //=号后面填写setter为哪个实例变量赋值,getter获取哪个实例变量的值
    @synthesize name = _name,sex = _sex,age = _age,score =_score;//可以写成一行,一般写成两行,一行可读性差
    //@synthesize age = _age;//实现age属性
    //@synthesize score = _score;//实现score属性
    //- (void)setName:(NSString *)name//设置名字
    //{
    //    _name = name;
    //}
    //- (NSString *)name//获得名字
    //{
    //    return  _name;
    //}
    //- (void)setAge:(NSInteger)age//设置年龄
    //{
    //    _age = age;
    //}
    //- (NSInteger)age//获得年龄
    //{
    //    return _age;
    //}
    @end

     属性的属性

    第一类:读写性控制(readonly、readwrite、setter、getter)

    如果读写性控制的关键字是readonly,是告诉编译器,只声明getter⽅方法(无setter⽅方法)。
    例如:@property(readonly)NSString *name;

    //等价于 - (NSString *)name;

    如果是readwrite,告诉编译器,既声明setter⼜又声明getter。
    例如: @property(readwrite)NSString *name;

    //等价于 - (NSString *)name;

    - (void)setName:(NSString *)name; readwrite是读写性控制的默认设置。

    第⼆类:原子性控制(nonatomic、atomic)

    如果原子性控制的关键字是atomic。setter、getter⽅法在多线程访 问下是绝对安全的,即setter、getter内部做了多线程访问处理。原⼦ 性控制的默认设置是atomic

    如果原子性控制的关键字是nonatomic。setter、getter⽅法内部不会 做多线程访问处理,仅是普通的setter、getter方法

    程序开发过程中,setter、getter处都在用,如果使用atomic,

    需要不断的对setter、getter加锁解锁以保证线程访问安全,会很占 ⽤系统资源,降低系统性能。

    通常设置为nonatomic,某些属性需要线程安全的时候,才定义为 atomic。

    例如:@property (readwrite,nonatomic)NSString *name;
    //等价于 – (NSString *)name;

    - (void)setName:(NSString *)name;

    第三类:语义设置(assign、retain、copy)

    如果语义设置的关键字是assign。setter、getter内部实现是直接赋值。

    例如:@property(nonatomic,assign)NSString *name;
    - (void)setName:(NSString *)name{
        

        _name = name;
    }

    - (NSString *)name{
        return _name;
        

    }

    //assign修饰下,setter是直接为实例变量赋值

    //assign修饰下,getter是直接获取实例变量

    在如果语义设置的关键字是retain。setter、getter的内部实现会做内存优化。

    //retain关键字下,setter 是企业必考的笔试题

    例如:@property(nonatomic,retain)NSString *name;

    - (void)setName:(NSString *)name{
        if(_name != name){
            

            [_name release];
            

            _name = [name retain];
        }
        

    }

    }

    - (NSString *)name{
        

        return [[_name retain]autorelease];

    }

    如果语义设置的关键字是copy。setter、getter的内部实现也会做内存优化。

    例如:@property(nonatomic,copy)NSString *name;

    - (void)setName:(NSString *)name{
        if(_name != name){
            

            [_name release];
            

            _name = [name copy];
        }
        

    }

    }

    - (NSString *)name{
        

        return [[_name retain]autorelease];

    }

    如果属性是⾮对象类型(⽐比如int,float等)属性的语义设置使用assign。

    如果属性是对象类型(⽐如NSStrng、NSArray等)属性的语义设置使用retain。

    如果属性是对象类型并且想得到参数的copy,使⽤用copy关键字。

    -(instancetype)initWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age
    {
        self = [super init];
        if (self) {
            //给实例变量赋值,使用setter ,不再单独赋值,因为setter内部做了内存优化
            [self setName:name];
            [self setAge:age];
            [self setSex:sex];
            
           
        }
        return self;
    }
    //初始化以后就这样写

    点语法

    凡是符合系统默认setter、getter书写格式的⽅法都可以使⽤用点语 法。

    例如:[person1 setName:@”zhangsan”];可以等价写成 person1.name = @”zhangsan”;。

    NSString *name = [person1 name];可以等价写成
    NSString *name = person1.name;

    属性是⼀对getter、setter⽅法,点语法是属性的另一种调用格式

    kvc

    KVC(Key-Value-Coding),键值编码,是⼀种间接访问实例变量的方法.

    key:键,⽤于标识实例变量

    vlaue:实例变量对应的值

    修改值

    setValue:forKey:

    setValue:forKeyPath:

    setValue:forUndefinedKey:

    setValuesForKeysWithDictionary:

    获取值

    valueForKey:

    valueForKeyPath:

    valueFoeUndefineKey:

    注意事项

    当key不存在的时候,会执⾏setValue:forUndefinedKey:

    系统默认实现是抛出一个异常

    一个kvc例子,一个Person类,一个A类

    //A.h中代码
    #import <Foundation/Foundation.h>
    
    @interface A : NSObject
    {
        NSString *_name;
    }
    
    - (void)printName;
    @end
    //A.m中代码
    #import "A.h"
    
    @implementation A
    -(void)printName
    {
        NSLog(@"%@ ",_name);
    }
    @end
    //Person.h中代码
    #import <Foundation/Foundation.h>
    #import "A.h"
    @interface Person : NSObject
    
    {
        NSString *_name;
    //    NSString *_sex;
        NSInteger _age;
        A *_a;
    }
    - (void)sayHi;
    - (id)init;
    @end
    //Person.m中代码
    #import "Person.h"
    @implementation Person
    -(void)sayHi
    {
        NSLog(@"hello,this is %@ %ld years old   ",_name,_age);
        [_a printName];
    }
    //重写方法   当key不存在的时候会调用这个方法,系统的默认实现是抛出一个异常,我们可以重写这个方法.解决key不存在产生崩溃的问题
    - (void)setValue:(id)value forUndefinedKey:(NSString *)key
    {
    
    }
    //当key为非对象类型,且value设置为nil的时候.会调用这个方法,系统默认实现是抛出一个异常,我们可以重写这个方法,解决value为nil的问题
    - (void)setNilValueForKey:(NSString *)key
    {
    
    }
    -(id)init
    {
        self = [super init];
        if (self) {
            _a = [[A alloc] init];
        }
        return self;
    }
    @end
    //main.m中代码
    #import <Foundation/Foundation.h>
    #import "Person.h"
    int main(int argc, const char * argv[])
    {
    
        Person *p1 = [[Person alloc] init];
        [p1 setValue:@"张三" forKey:@"name"];//kvc赋值
        [p1 setValue:@18 forKey:@"age"];
        [p1 sayHi];
        [p1 setValuesForKeysWithDictionary:@{@"name": @"张三",@"age": @18,@"sex": @""}];//比较好用
        [p1 sayHi];
        [p1 setValue:@"哇哈哈" forKeyPath:@"a.name"];
        [p1 sayHi];
        return 0;
    }
  • 相关阅读:
    WIN10修改桌面路径到(其他盘)教程
    C#通过IMessageFilter捕获鼠标消息
    C# ICON和Image互转
    由于找不到 opencv_world320.dll,无法继续执行代
    HttpWebRequest.Connection的问题
    远程服务器环境调用本地JS启动摄像头功能遇见的问题
    nginx反向代理配置
    获取开源天气信息的API
    Java实现八种排序算法(代码详细解释)
    Java面试之前复习总结(二)
  • 原文地址:https://www.cnblogs.com/limicheng/p/3821706.html
Copyright © 2011-2022 走看看