2014-10-28 58 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