IOS中实例的权限控制

时间:2023-03-08 20:55:18
  • @public、@protected、@private的使用

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

    

#import <Foundation/Foundation.h>

@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 = @"";
}
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 + ); char *keyname = __builtin_alloca(keyCStringLength + );
    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[] = toupper(keyname[]);
    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;
    }