2012-04-25 56 views
2

我創建了兩個具有相同名稱的方法的類。其中一個是私人的,另一個是公共的。 然後某處的代碼,我寫這篇文章:Objective-C中的私有方法不是私有的

-(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。我如何防止它?

+3

沒有辦法創建_truly_私有方法。如果你的對象響應一條消息,它就會響應。請參閱:http://stackoverflow.com/questions/172598/best-way-to-define-private-methods-for-a-class-in-objective-c和http://stackoverflow.com/questions/2158660/ why-doesnt-objective-c-support-private-methods – 2012-04-25 20:02:49

+0

因此,我應該如何檢查,該消息是從這個對象發送的?也許我應該做一些布爾變量,並在使用方法之前將其設置爲YES? 我發現了一件事。你也可以成爲keypath的一個觀察者,其中關鍵路徑是一些私有屬性。這是令人驚歎的不安全語言。但很酷,無論如何。 – 2012-04-25 20:10:11

回答

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 
+0

爲什麼它應該是靜態的?我的意思是這是一個c風格的功能。如果它不是靜態的,是否可以從外部調用它? – 2012-04-25 20:27:21

+1

它是'靜態的',因爲它的目的是保密的,而且你不想在鏈接時發生衝突。如果它不是靜態的,它將具有默認可見性,所以如果他們知道原型,有人可以調用它。 – justin 2012-04-25 20:29:06

+0

謝謝。看起來這是唯一的解決方案。 – 2012-04-25 20:32:08

-1

如果您聲明.h文件中的方法是公共的。如果你想要私人可見性,你必須在.m中聲明該方法,例如:

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

@implementation ClassB 

//Rest of .m 
+0

這個問題根本就是錯的。他知道這一點,但你可以發送一個從未在.m消息中聲明或聲明的方法。看看這個問題,他做到了。如果.m被導入,您的方法只隱藏聲明。 – Binarian 2013-08-29 17:09:36

0

現在你不能有真正的私有方法。當您在.m文件中的類擴展中聲明一個方法時,您只是將其隱藏在公共頭文件中。你現在正在做的事情被認爲是很好的設計,因爲你從頭文件中隱藏了這個方法,這意味着人們不得不花費一些時間來找到那些隱藏的方法,但他們仍然可以找到它們。

基本上,我遵循的規則是儘可能少地放入公共標題,並將其他所有內容放入類擴展中。這是你現在可以真正做的一切。

1

解決您的問題的方法可能是使用代理/外觀類,該類在內部彙總您的私有類的實例。例如:

// .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%安全的,運行時並沒有像其他人所說的那樣設置障礙。

+0

Foobar * impl;應該在Facade? FoobarFacade無法看到impl。 – 2012-04-26 14:40:37

+0

確實如此,謝謝指出! – Lvsti 2012-04-27 11:23:44