i have this:
//Node.h
#interface Node: CCSprite{
BOOL wasTouched;
}
-(BOOL)getTouched;
// some other methods
//Node.m
-(BOOL)getTouched{
return wasTouched;
}
-(id)init{
wasTouched=NO;
}
//wasTouched changes in the other methods..when they are called (no problem here)
//Game.m
//i make an array of nodes and do some stuff
-(void)someMethod{
for (Node *node in arrayOfNodes){
if ([node getTouched]) { //here it crashes
//code
}}}
it crashes with message -[CCSprite getTouched]: unrecognized selector sent to instance 0x236dd0
the question is: WHY?!
You probably inserted a plain CCSprite in your Nodes array.
-(id)init{
wasTouched=NO;
}
This hurts. :(
You always have to call the super implementation of an init method. You also have to return self here. Did the compiler not complain about a missing return value? Word of advice: do not ignore compiler warnings.
Both of this can lead to very weird behavior, including crashes I guess. Here's the fix:
-(id) init
{
self = [super init];
if (self)
{
wasTouched = NO;
}
return self;
}
Related
I have come some way with mixing C++ and Objective-C (actually Objective-C++), but now I am stuck.
My current problem is that the Objective-C 'self' variable seems to not be correct and throws an exception in my code:
Exception: Invalid parameter not satisfying: target
Which I assume refers to that selfRef is not a valid target:
addTarget:selfRef
What is the correct way to initialize 'self' and make it available for a C++ function.
This is my first day ever touching objective-c/objective-c++ so excuse me if this might be elementary ;)
Code:
#import "ios_objc.h"
#import <Foundation/Foundation.h>
#import <AVFoundation/AVAudioSession.h>
#import <MediaPlayer/MediaPlayer.h>
#import <MediaPlayer/MPRemoteCommandCenter.h>
id selfRef;
//static Ios_objc *selfRef; //I tried this as well.
#implementation Ios_objc
IosImpl::IosImpl(void) //: self( NULL )
{
}
IosImpl::~IosImpl(void)
{
[Ios_objc dealloc];
}
void IosImpl::init(void)
{
selfRef = [[Ios_objc alloc] init];
}
void IosImpl::enable(void)
{
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
commandCenter.playCommand.enabled = YES;
#try {
[commandCenter.playCommand addTarget:selfRef action:#selector(playSounds)];
}
#catch (NSException *exception) {
NSLog(#"Exception: %#", exception.reason);
}
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
}
void IosImpl::playSounds()
{
NSLog(#"Play");
}
//I also tried 'Objective-C' style function signature.
//- (void) playSounds
//{
//
//}
#end
I believe the exception is coming from a statement within the implementation of -[MPRemoteCommand addTarget:action:] that looks something like:
NSParameterAssert(target);
That is, it's validating that the target parameter it has received is non-nil. That's why the odd phrasing "… parameter not satisfying: target". "target" is the actual condition being tested and which the parameter does not satisfy. If the statement had been written NSParameterAssert(target != nil); then the exception reason would have read "… parameter not satisfying: target != nil", which would have been clearer.
Anyway, you write a (presumably non-nil) value to selfRef in IosImpl::init(), but what calls that? The constructor does not as currently written. Either call init() from the constructor or just put that code directly into the constructor.
Also, your destructor isn't correct. As currently written, it's calling -dealloc on the Ios_objc class object, which is unlikely to do anything (and, if it does, it's nothing good). You probably meant [selfRef release] (note: release, not dealloc). In general, you should never call -dealloc except to call through to super in an implementation of your own -dealloc method.
I am making a MFC like class build on the WinAPI as an exersise.
Now am i running into the problem that i am getting a runtime error while i execute the code.
In My Main the following lines are present:
void MyApp::Init(int nCmd)
{
main.Create(L"This is the MainFrame Window");
main.ActivateFrame(nCmd);
GWnd* p= main.GetActiveView();//Get pointer to the first view of the FrameWnd
//p->GetID();
}
The commented out line causes the error.
The GWnd class constructors:
//Standard classname
GWnd::GWnd() :m_ClassName(L"Wnd"), BaseWnd(), m_pOwnerWnd(NULL)
{
GWnd::Init();
}
//Userdefined Classname
GWnd::GWnd(LPCWSTR ClassName) : m_ClassName(ClassName), BaseWnd(), m_pOwnerWnd(NULL)
{
GWnd::Init();
}
//Copy constructor
GWnd::GWnd(const GWnd& Wnd) : BaseWnd(GetHwnd()), m_pOwnerWnd(NULL)
{
m_ClassName = L"Wnd";
}
The assignment function:
//Operators
operator HWND() { return BaseWnd<GWnd>::GetHwnd(); }
GWnd operator=(GWnd Wnd)
{
GWnd tmp(Wnd);
}
I hope the lines of code are sufficient for your answers. Does someone understands the issue i am running into? And could give me a hint where to look further?
try to add this:
GWnd* p= (GWnd*)main.GetActiveView();
instead of this:
GWnd* p= main.GetActiveView();
and then use this
p->GetDlgCtrlID()
This question already has answers here:
What is the meaning of id?
(5 answers)
Closed 9 years ago.
To begin, i'm not very comfortable with Objective c, i'm trying to convert a C++ class into an Objective C and i'm having trouble with the implementation on my class this is what i got for c++
UniqueWord::UniqueWord(const string word, const int line)
{
wordCatalog=word;
count = 0;
addLine(line);
}
//Deconstructor.
UniqueWord::~UniqueWord(void)
{
}
and this is what i got for Objective C
#implementation UniqueWord
-(id)initWithString:(NSString*)str andline:(NSInteger)line{
_wordCatalog=str;
count=0;
addline(line);
return ?//return what? it states (Control reaches end of non-void function)
}
I'm really new to classes in objective c, so i'm also asking for a dumbed down answer to,What in the world is an "id" and how do you use it?
Objective C constructors a little bit different. You should create something like following:
-(instancetype)initWithString:(NSString*)str andline:(NSInteger)line{
self = [super init];
if(self == nil) return nil;
_wordCatalog=str;
count=0;
addline(line);
return self;
}
id is a generic class in Objective-C. This is somewhat similar to void* of C++, but with a lot more support from the execution environment so as to not require much typecasting.
There is no parallel concept in C++: an untyped object reference lets you use objects dynamically, with the specifics of the call checked at runtime, rather than at compile time.
Also note that Objective-C uses initializers instead of constructors. The two serve similar purposes, but are not the same: constructors can operate either together with operator new or separately from it, while initializers can operate only with the method that does allocation. Additionally, an initializer can return a different object in place of the one provided by alloc; constructors cannot do that.
An id is a point to any object in Objective-C. An init method returns an allocated and instantiated object. I would refer you to the Apple docs regarding initializers at https://developer.apple.com/library/ios/documentation/general/conceptual/CocoaEncyclopedia/Initialization/Initialization.html
In using what the article above says you'll want to write something like.
- (instancetype)initWithString:(NSString *)str andLine:(NSInteger)line {
self = [super init];
if (self) {
_wordCatalog = str;
}
return self;
The typical form (which you should use) for init methods is like this:
- (id)init
{
if ( (self = [super init] ) )
{
[other code you want in the constructor]
}
return self;
}
So for the method you have, it should look something like this:
-(id)initWithString:(NSString*)str andline:(NSInteger)line{
if ( (self = [super init]) )
{
_wordCatalog=str;
count=0;
addline(line);
}
return self;
}
That is, unless the super class has an initWithString:andline: constructor, in which case you would use
if ( (self = [super initWithString:string andline:line) )
as the if statement.
I'm having a debug only crash. I'm using Eclipse's gdb.
If I'm not failing reading it, the crash seems to occur when passing an object (not by reference nor pointer) to an interface method, precisely when copying a "many" (typedef std::list<boost::any> many;) member during it's copy constructor called to send a copy to the method.
I'm not using debug builds for boost, nor other external builds, just for the code I'm compiling, so, could this be the cause?
Any other ideas at what may be the cause?
class Message {
public:
static const int MAX_LEVEL=5;
Message(int type=0, int destination=0);
virtual ~Message();
int type;
int destination[MAX_LEVEL];
int level;
many message;
};
And the crashing sector, inside init() on Game3DWin: (Even though I'm building in Debug mode, there's no _DEBUG define since I didn't build the Debug binaries for the libs)
bool Game3DWin::init(){
#ifdef _DEBUG
pluginsCfg = "lib/plugins_d.cfg";
resourcesCfg = "res/resources_d.cfg";
#elif OGRE_PLATFORM == OGRE_PLATFORM_WIN32
pluginsCfg = "lib/pluginsWin.cfg";
resourcesCfg = "res/resources.cfg";
#else
pluginsCfg = "lib/plugins.cfg";
resourcesCfg = "res/resources.cfg";
#endif
ogreRoot=boost::make_shared<Ogre::Root>(pluginsCfg, "config.cfg");
if(!(ogreRoot->restoreConfig() || ogreRoot->showConfigDialog())){
return false;
}
window = ogreRoot->initialise(true, "Crewon CLASH!");
loadResourceCfgFile();
guiRenderer = &CEGUI::OgreRenderer::bootstrapSystem();
CEGUI::SchemeManager::getSingleton().create( "TaharezLook.scheme" );
CEGUI::System::getSingleton().setDefaultFont( "DejaVuSans-10" );
CEGUI::System::getSingleton().setDefaultMouseCursor( "TaharezLook", "MouseArrow" );
CEGUI::Window* myRoot = CEGUI::WindowManager::getSingleton().createWindow( "DefaultWindow", "_MasterRoot" );
CEGUI::System::getSingleton().setGUISheet( myRoot );
CRengine::Message msg=CRengine::Message( (int)CRengine::MESSAGE_TYPE::INPUT_INIT );
msg.message.push_front(window);
this->broadcaster.lock()->receiveMessage( msg ); //Crash here
//Unreached code due to crash
}
broadcaster is a pointer to Messageable, an interface.
class Messageable {
public:
virtual ~Messageable() {};
virtual bool receiveMessage(CRengine::Message) = 0;
};
broadcaster initialization (factory method to be able to store a "this" smart pointer):
Game3DWin* Game3DWin::create(boost::shared_ptr<CRengine::Messageable> caster, int processType, int order){
Game3DWin* temp= new Game3DWin(processType, order);
temp->broadcaster=caster;
bool success=temp->init();
if(!success){
delete temp;
temp=NULL;
}else{
temp->checkRoom(); }
return temp;
}
The above is called here:
bool MainManager::start( boost::shared_ptr<MainManager> thisMM ){
//Some code
boost::shared_ptr<Game3DWin> win;
win.reset( Game3DWin::create(thisMM, CRengine::MAIN_PROCESS_TYPES::PROCESS_GUI) );
//Some code
}
start() called from the main, which passes the pointer to MainManager
boost::shared_ptr<CRengine::MainManager> app =boost::make_shared<CRengine::MainManager>();
app->start(app);
Message implementation:
Message::Message(int type, int destination): type(type), level(0){
for(int ii=0;ii<MAX_LEVEL;ii++){
this->destination[ii]=-1;
}
this->destination[0]=destination;
}
Message::~Message() { }
window is Ogre::RenderWindow* from OGRE 3D open source rendering engine. I tried to cast it to (int) before pushing it into many in case it tried to call a destructor or something, but, still, same crash.
This is an extended comment, too long to fit in a comment.
Message lacks an implemented constructor and destructor. Either simplfy the class while confirming the problem still occurs, or expose that implementation to us.
window is a variable of unknown type. As the list of boost::any that you are reporting as crashing contains the window type, knowing what it is may just be somewhat useful.
this->broadcaster.lock() will be a null shared_ptr if the weak_ptr has gone away. Always, always, always do shared_ptr<foo> pFoo = this->broadcaster.lock(); then use pFoo (or whatever name) after checking that it is valid (evaluating it in a boolean context).
boost::weak_ptr<CRengine::Messageable> caster -- do you not know if this exists? You probably want a boost::shared_ptr here, so that the caster is at least known to exist during creation of the Game3DWin.
Same here: boost::weak_ptr<MainManager> thisMM -- probably should be a shared_ptr.
The issue was none of the aforementioned. It was caused by Eclipse being unable to clean. This was caused due to using "External Builder", mingw32-make.exe, which in the makefile ran a del <Filelist> and Windows7 seems to have some issue with this and it's parameters, so the clean did nothing.
Since I was working with Debug as active build, I got the crash due to lack of clean, but when I switched to Release it was unaffected since it had to mostly rebuild everything.
Manual delete of the contents of <project>/Debug and <project>/Release fixed the problem.
I got a lot of false positives when running the code analysis for C++ in VS11. For example i have a few dozen switch and it says my pointer may be null. All the cases in the switch (at least in one case) the pointer is set and the default calls my function which throws an assert(0) and exception. I guess since the assert and exception is in a method it doesn't realize its impossible for the pointer to be null. How do i hint or fix it so a false positive like this doesn't show up?
try using _Analysis_assume_(FALSE) in the switch, it hints unreachable code to the compiler.
You can also decorate functions that throw and don't return with _Analysis_noreturn_.
If the method invoked by the default case doesn't return anything, you can try making it return a "fake" null value that will be assigned to the pointer in the default case.
Type* MyClass::methodCalledInDefaultCase()
{
pointer = 0;
assert(0);
throw Exception;
return 0; // Hope this doesn't cause unreachable code warning
}
void MyClass::myMethod()
{
pointer = 0;
switch(whatever)
{
case foo:
...
case bar:
....
default:
pointer = methodCalledInDefaultCase();
break;
}
}
Hope this helps.