2014-10-28 55 views
0

現在我的OS X 10.9項目在Objective-C中用GUI設置,而在C++類中進行所有處理。這看起來並不是最好的方式,但這是給我的,我必須處理這些限制。我目前在Cocoa GUI中有NSSlider。我希望能夠在C++類中控制變量x如何使用Objective-C++從Objective-C Cocoa接口調用C++方法

當我運行該程序時,容差條正在工作(工作意味着它不斷更新其滑動值)。

報頭爲:NSSliderSlider.h):

@interface Slider : NSObject { 
@private 
    __weak IBOutlet NSTextField *sliderValue; 
    __weak IBOutlet NSSlider *slider; 
} 

- (IBAction)updateSliderValue:(id)sender; 

@end 

執行情況的NSSliderSlider.mm):

#import "Slider.h"  // The NSSlider object 
#import "CMain.h"  // The C++ class that does all the processing (not sure if this is the way to include a C++ interface in an Objective-C++ class or if this will allow me to call its methods) 

@implementation Slider 

-(void) awakeFromNib { 
    [slider setIntValue:40]; 
    [sliderValue setIntValue:[slider intValue]]; 
} 

- (IBAction)updateSliderValue:(id)sender { 
    [sliderValue setIntValue:[slider intValue]]; 
    // Here is where I'd think that if I have a setValueofX(int number) method in the C++ class 
    // I could call this somehow using objective-C++. I don't know if I can or how to call this method here 
} 

這裏是Main.h相關片段:

class CMain(){ 
    public: 
     CMain(); 
     void setValueofX(int number); 
     int getValueofX(); 

    private: 
     int x; 
}; 

怎麼辦我包括CMain.hObjective-C++(其中,.h文件或.mm文件?以及如何?),這樣可以讓我調用CMain.h中的方法?如何在Objective-C中使用setValueofX(sliderValue)來短語方法調用x的值?

如果需要更多信息,請讓我知道!任何幫助或想法表示讚賞!

謝謝!

回答

1

我發現一個解決方案,注意到有一個現有的包裝類CWrapper.h,它是一個客觀的C++實現類CWrapper.mm。有一個CMain變量實例化爲cmain。我爲x做了一個getter方法,我只是在滑動類中調用的包裝類+ (void) passX:(int) number;中創建了一個靜態方法。我選擇了一個靜態方法,因爲對於這個應用程序來說,這個值永遠不會在對象之間有所不同。我希望我在這裏做出了正確的選擇!下面

見代碼更改:

我已將此添加到Slider.h文件。

- (int)X; 

我加入吸氣劑,並[CWrapper passX:[self getX]];在Slider.mm文件updateSliderValue方法。

- (int)X { 
    return [slider intValue]; 
} 

- (IBAction)updateSliderValue:(id)sender { 
    [sliderValue setIntValue:[slider intValue]]; 
    [CWrapper passX:[self getX]]; 
} 

這是我添加到CWrapper.h中的代碼。

+ (void) passX:(int) number; 

這是我加入CWrapper.mm代碼。

+ (void) passX:(int)num 
{ 
    cmain.setValueofX(num); 
} 
+0

只需要注意一點:不要在Objective-C中用「get」啓動getter的名字。這是保留給參數副作用的方法。把它稱爲 - 寬容。這樣,您就可以使用KVO或其他依賴於您遵守此類命名標準的機制。 – uliwitness 2014-10-31 15:50:21

+0

@uliwitness感謝您的提示! – 2014-11-01 20:41:10

3

調用setter的代碼與C++中的代碼相同。但是,您需要一個指向CMain對象的指針才能調用它的方法。我不知道該對象當前所在的位置。如果在另一個對象中沒有對象,則可能需要創建一個對象,只需聲明一個實例變量CMain myCMain;,然後在updateSliderValue:中調用myCMain.setValueOfX([slider intValue]);即可。

至於在哪裏包括C++類,它真的是你的選擇。但是,如果您在頭文件中使用任何C++,則需要花費大量精心的額外工作才能將其包含在普通的.m文件中。所以通常我會試着在頭文件中使用純C和ObjC,並且只能在.mm文件中使用C++。您可以使用類擴展(有時也稱爲「類繼續」)在.mm文件中聲明其他ivars,以使其不在標題中。

如果您想了解ObjC++更多的信息,我詳細回答了另一篇文章:Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link?並且還鏈接到一個播客我當時就在那裏我談了很多的細節和技巧整合ObjC和C++的客人。另外:我希望這些不是你使用的實際名稱和評論。從來沒有一個沒有前綴的ObjC類(3個字母,Apple表示他們保留所有用於自己用途的雙字母前綴,並且他們在過去使用了未加前綴的內部類名,這打破了一些人的程序)。另外,「滑塊」是一個壞名字,因爲NSSlider是實際的滑塊,這聽起來像它應該是一個子類。你真的想把這稱爲ISTSliderController或其他什麼。

+0

/@ uliwitness謝謝您的建議!我更改了變量名稱,因爲它們專用於我正在做的事情 - 我希望能夠像這樣引入它更合理。因此,'CMain'對象在不同的​​類中實例化 - 一個包裝類,諷刺地叫做'CWrapper.mm'。我不想創建這個變量的另一個實例,我該如何指向這個變量? 我正在考慮的另一條路線是使set方法的靜態方法(實例不可知(我認爲?))並保持不同對象的值相同。使它相同將適用於我的應用程序。 – 2014-10-28 20:21:40

+1

不要讓你的設計變得靜止,因爲它看起來更簡單。它只會在後面咬你,如果你後來發現你需要這種類型的兩個對象。真的,C++在這方面與Objective-C沒有什麼不同。你只需要找到一個知道這兩個對象的對象,並讓它把'ISTSliderController'作爲另一個人擁有的'CMain'實例的指針。你通常有一個對象層次結構,其中靠近根的對象在它們「下面」創建對象。此時你通常會連接類似的連接。 – uliwitness 2014-10-29 07:38:32

-2

這裏有一個所有的客觀c和客觀C++的答案:

CMain。H:

#ifndef Testing_CMain_h 
#define Testing_CMain_h 

@interface CCMain : NSObject 
-(CCMain*) init; 
-(void) dealloc; 

-(void)setValueofX:(int)number; 
-(int)getValueofX; 
@end 

#endif 

CMain.mm:

#import <Foundation/Foundation.h> 
#import "CMain.h" 

class CMain { 
private: 
    int x; 

public: 
    CMain() : x(0) {} 

    void setValueofX(int number) {x = number;} 
    int getValueofX() const {return x;} 
}; 


@interface CCMain() 
@property (nonatomic, assign) CMain* inst; 
@end 

@implementation CCMain 

-(CCMain*) init 
{ 
    if (!_inst) 
    { 
     _inst = new CMain(); 
    } 
    return self; 
} 

-(void) dealloc 
{ 
    delete _inst; 
    _inst = nil; 
} 

-(void)setValueofX:(int)number 
{ 
    _inst->setValueofX(number); 
} 

-(int)getValueofX 
{ 
    return _inst->getValueofX(); 
} 

@end 

,如果你想使用C風格的函數,則:

setValueofX(cmain_instance, value); 
int val = getValueofX(cmain_instance); 

而這個工程,因爲在C C++類功能相同:

void CMain::MyFunc(int X); 
//vs.. 
void MyFunc(CMain* inst, int X); 

兩者是完全相同的事情。

+0

Objective-C++是比這種方法更好的選擇。 ObjC++意味着你可以在你的ObjC代碼中使用C++語句。上面的代碼使得代碼更不易讀,並且依賴於ABI的細節,我想。 – uliwitness 2014-10-28 19:37:36

+0

你真的認爲你可以在Objective-C中使用Objective-C++代碼嗎?這是個玩笑。讓我們看看你用'std :: cout'來做到這一點..無論如何,他必須編寫包裝器。他的頭文件必須完全是C或Objective-C。從Objective-C++中沒有任何東西。Objective-C++並不意味着你可以在Objective-C中使用C++。你仍然用C風格的代碼包裝C++代碼。根據情況,使用Objective-C++會更容易。在Objective-C中使用Objective-C++代碼與使用'extern「C」'同義。 – Brandon 2014-10-28 19:40:51

+2

我已經在大型混合C++/ObjC項目上工作了大約10年。 OP沒有詢問在ObjC中使用C++。 OP詢問在ObjC++(.mm)文件中使用C++。 (請參閱我的答案瞭解更多信息) – uliwitness 2014-10-28 19:44:32