【问题标题】:Private methods in objective-c not privateObjective-c 中的私有方法不是私有的
【发布时间】:2012-05-06 13:22:25
【问题描述】:

我创建了两个具有相同名称的方法的类。其中一个是私人的,另一个是公共的。 然后在代码的某个地方我写了这个:

-(void) doMagic:(id) object {
    [(ClassA*)object doSmth];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application
    ClassB * objB = [[ClassB alloc] init];
    [self doMagic:objB];
}

在控制台我看到这个: 2012-04-25 23:41:28.183 testmagic[558:403] classB - doSmth

这里是课程的来源:

//.h
@interface ClassA : NSObject
-(void) doSmth;
@end
//.m
@implementation ClassA
-(void)doSmth {
    NSLog(@"classA - doSmth");
}
@end

//.h
@interface ClassB : NSObject


@end
//.m
@interface ClassB ()
-(void) doSmth;

@end;

@implementation ClassB
- (void)doSmth {
    NSLog(@"classB - doSmth");
}
@end

我知道,这是因为 Obj-C 中方法的“消息”性质,并且在运行时类可能不知道它的哪些方法是私有的或公共的,但问题是:

我怎样才能制作真正私有的方法?我听说通过反编译可以看到方法名称,所以有人可以使用我的私有 API。如何预防?

【问题讨论】:

  • 没有办法创建一个真正的私有方法。如果您的对象响应消息,那么它就会响应。请参阅:stackoverflow.com/questions/172598/…stackoverflow.com/questions/2158660/…
  • 所以我应该如何检查,该消息是从这个对象发送的?也许我应该在使用方法之前创建一些布尔变量并将其设置为 YES?我又发现了一件事。您还可以成为 keypath 的观察者,其中 key path 是一些私有属性。这是令人惊叹的不安全语言。但无论如何,很酷。

标签: objective-c private encapsulation


【解决方案1】:

如果您在 .h 文件中声明该方法是公共的。如果您想要私有可见性,则必须在 .m 中声明该方法,例如:

@interface ClassB (Private_Methods)
- (void)doSmth;
@end

@implementation ClassB

//Rest of .m

【讨论】:

  • 这个问题完全是错误的。他知道这一点,但是您可以发送一个从未在 .m 消息中声明或声明的方法。看看这个问题,他做到了。如果 .m 被导入,您的方法只会隐藏声明。
【解决方案2】:

运行时不能调用它永远不知道的东西。我通常采用的方法是使用static 函数:

MONObject.h

@interface MONObject : NSObject
// ...
@end

MONObject.m

// 'private' methods and ivars are also visible here
@interface MONObject()
// ...
@end

// typically here:
static void fn(MONObject * const self) {
    NSLog(@"%@", [self description]);
}

@implementation MONObject
// ...

// sometimes here:
static void fn2(MONObject * const self) {
    NSLog(@"%@", [self description]);
}

@end

【讨论】:

  • 为什么应该是静态的?我的意思是它是一个 c 风格的函数。如果它不是静态的,是否可以从外部调用它?
  • 它是static,因为它是私有的,并且您不希望在链接时发生冲突。如果它不是静态的,它将具有默认可见性,因此如果有人知道原型,就可以调用它。
  • 谢谢。看起来这是唯一的解决方案。
  • 不客气。这是我所知道的唯一一个简单的方法,除了一个专有的私有方法前缀方案:- [MONObject doSmth_PRIVATE_MONObject——它可以用来保留一个私有方法,但它不会阻止其他人通过自省/运行时访问/调用该方法/nm 偷看。
【解决方案3】:

现在你不能拥有真正的私有方法。当您在 .m 文件的类扩展中声明方法时,您只是将其隐藏在公共头文件中。你现在所做的被认为是好的设计,因为你从头文件中隐藏了方法,这意味着人们必须花费一些时间才能找到那些隐藏的方法,但他们仍然可以找到它们。

基本上我遵循的规则是尽可能少地放入公共标头中,并将其他所有内容放入类扩展中。这就是你现在真正能做的。

【讨论】:

    【解决方案4】:

    解决您的问题的方法可能是使用代理/外观类,该类在内部聚合您的私有类的实例。例如:

    // .h
    @interface FoobarFacade: NSObject
    - (void)publicMethod;
    @end
    
    // .m
    @interface FoobarFacade ()
    {
        Foobar* impl;
    }
    @end
    
    @interface Foobar: NSObject
    - (void)secretMethod;
    @end
    
    @implementation Foobar
    - (void)secretMethod { NSLog(@"foobar secret method"); }
    @end
    
    @implementation FoobarFacade
    - (void)publicMethod {
         NSLog(@"façade public method");
         [impl secretMethod];    // calling into the secret method
    }
    @end
    

    当然,这也不是 100% 安全的,运行时不会像其他人所说的那样设置任何障碍。

    【讨论】:

    • Foobar* impl;应该在门面? FoobarFacade 看不到 impl。
    猜你喜欢
    • 1970-01-01
    • 2011-12-12
    • 2011-06-14
    • 2011-12-02
    • 2010-12-07
    • 2015-08-19
    • 1970-01-01
    • 2011-08-04
    • 1970-01-01
    相关资源
    最近更新 更多