IOS中实例的权限控制


  • @public、@protected、@private的使用

    在OC中声明一个类的时候,可以使用上面 @public、@protected、@private三个关键字声明实例的权限,例如下面的代码:

#import 

@interface Person : NSObject
{
@public
    NSString *_height;
@protected
    NSString *_weight;
@private
    NSString *_wife;
}

@end



@interface Person ()
{
    @public
    NSString *_name;
    @protected
    NSString *_sex;
    @private
    NSString *_phoneNO;
}

- (void)publicMethod;

@end

@implementation Person


- (instancetype)init
{
    if(self = [super init])
    {
        _height = @"1.8m";
        _weight = @"65Kg";
        _wife = @"none";
        _name = @"zhangSan";
        _sex  = @"man";
        _phoneNO = @"1122334455";
    }
    return self;
}

- (void)publicMethod
{
    
}

@end

  在.h文件中定义了三个实例,这三个实例的权限和public、protected、private相对应,对于一个Person类型的对象p,_name在任何地方都是可以访问的,_sex只能在Person

的子类中访问,_wife只能自己内部访问。在.m文件中定义的三个实例也与public、protected、private相对应,需要注意的是,在其它文件中定义的Person类型的对象p,都不能访问到这三个实例,只有在.m文件内部,public、protected、private才会起到对应的作用。实际上OC中实例的权限控制只是编译时的一种权限限制,在OC runtime的类结构中,实例变量是不存在权限控制的,同样类方法、实例方法也不存在权限控制。

  • 对于KVC来说,无论实例是哪种权限都是可以轻松访问到的,如下面的代码:
  •  @interface Student : Person
    
    @end
    
    
    @implementation Student
    
    
    + (void)testProtected
    {
        Person *p = [Person new];
        NSLog(@"%@",p->_height);
        NSLog(@"%@",p->_weight);
    }
    
    - (NSString *)description
    {
        Person *p = [Person new];
        NSLog(@"%@",p->_height);
        NSLog(@"%@",p->_weight);
    //    NSLog(@"%@",p->_wife);
    //    [p publicMethod];
    //    [self publicMethod];
        //return [NSString stringWithFormat:@"name == %@\nsex == %@\nphone == %@",_name, _sex,_phoneNO]
    //    return [NSString stringWithFormat:@"name == %@\nsex == %@",_name, _sex];
    //    return [NSString stringWithFormat:@"%@ , %@ , %@",_height , _weight ,_wife];
        return [NSString stringWithFormat:@"%@ , %@",_height , _weight];
        
    }
    
    @end

    KVC访问:

  • #import "Other.h"
    #import "Person.h"
    
    @interface Other : NSObject
    
    - (void)testProtected;
    
    - (void)testKVC;
    
    @end
    
    
    @implementation Other
    
    - (void)testProtected
    {
        Person *p = [Person new];
        NSLog(@"%@",p->_height);
    //    NSLog(@"%@",p->_weight);
    }
    
    - (void)testKVC
    {
        Person *p = [Person new];
        NSLog(@"%@",[p valueForKey:@"_name"]);
        NSLog(@"%@",[p valueForKey:@"_sex"]);
        NSLog(@"%@",[p valueForKey:@"_phoneNO"]);
    
        NSLog(@"%@",[p valueForKey:@"_wife"]);
    
    }
    
    @end

    实际KVC读取一个实例变量:

  • - (id)valueForKey: (NSString*)key
    {
        if (!key) {
            id value = [self valueForUndefinedKey:nil];
            return value;
        }
    
        const char *keyCString = [key UTF8String];
        SEL sel = sel_getUid(keyCString);
    
        // FIXME: getKey, _getKey, isKey, _isKey are missing
    
        if ([self respondsToSelector:sel]) {
            id value = [self _wrapReturnValueForSelector:sel];
            return value;
        }
    
        size_t keyCStringLength = strlen(keyCString);
        char *selBuffer = __builtin_alloca(keyCStringLength + 5);
    
        char *keyname = __builtin_alloca(keyCStringLength + 1);
        strcpy(keyname, keyCString);
    
        #define TRY_FORMAT(format)\
                sprintf(selBuffer, format, keyname);\
                sel = sel_getUid(selBuffer);\
                if ([self respondsToSelector:sel]) {\
                    id value = [self _wrapReturnValueForSelector:sel];\
                    return value;\
                }
        TRY_FORMAT("_%s");
        keyname[0] = toupper(keyname[0]);
        TRY_FORMAT("is%s");
        TRY_FORMAT("_is%s");
    //    TRY_FORMAT("get%s");
    //    TRY_FORMAT("_get%s");
        #undef TRY_FORMAT
    
        if ([isa accessInstanceVariablesDirectly]) {
            sprintf(selBuffer, "_%s", keyCString);
            sel = sel_getUid(selBuffer);
    
            if ([self respondsToSelector:sel]) {
                id value = [self _wrapReturnValueForSelector:sel];
                return value;
            }
    
    
            Ivar ivar = class_getInstanceVariable(isa, selBuffer);
            if (!ivar) {
                ivar = class_getInstanceVariable(isa, keyCString);
            }
    
            if (ivar) {
                id value = [self _wrapValue:(void*)self + ivar_getOffset(ivar) ofType:ivar_getTypeEncoding(ivar)];
                return value;
            }
    
        }
    
        id value = [self valueForUndefinedKey:key];
        return value;
    }

相关