The app crashing with signal SIGABRT (the debugger output is child already added. It can't be added again) in the simulator and on the device. Runs fine when I profile the app in Xcode while running it on the simulator or the device. Why is this?
Update: I've figured out that this line of code is causing the problem:
Mover *moverObject = [[[Mover alloc] init] autorelease];
NSMutableArray * array = [moverObject moveToward:startPoint :finalPoint]//<-- This is the problem
moveToward is method that returns a NSMutableArray containing the points from the startPoint to the finalPoint. This worked fine early today but after I started testing something new I guess I broke it. I made no changes in the actual Mover.h/.m just in the GameLayer.m (where I was adding code). I'm not sure what I added to cause the problem.
Update 2: I did some more digging using breakpoints and I found that
GameLayer *gameLayerObject = [[GameLayer alloc] init];<-- This causes the crash
Inside mover.m where the method moveToward:: is, this is the furthest it will go without crashing. Again the error is child already added. It can't be added again. Why does this happen?
This may just be coincidence. Hard to say because you didn't post any code.
The error message is clear though: you're trying to addChild the same node more than once, either to the same parent or to a different parent. Check your code for situations where this can occur.
Related
I am using an NSCollectionView where each NSCollectionViewItem uses a QLPreviewView to get a rendering of a file's content.
(This is an attempt at a file browser for images and other previewable files.)
Initially, this works fine.
However, once collection items are getting re-used, I get an assertion error (both in 10.13 and 10.14):
[QL] Assertion failure (unreachable code) - [… MyPreviewView activated … doc:[QLPreviewDocument …]] is already activated
Apparently, before I can re-use a NSCollectionViewItem, the previously used QLPreviewItem needs to be set to inactive state somehow. How do I do that?
I've tried to send the close message to the QLPreviewView instance but that doesn't make a difference.
I also do not get a dealloc call on my QLPreviewView subclass, which suggests that the object is still referenced by something else, possibly the QLPreviewDocument, which then gets confused about the change of state.
I have made a demo project available on github: https://github.com/tempelmann/NSCollectionViewWithQLPreview
To test: Run it, then scroll down. When reaching items 50 to 60, the assertion will be triggered.
The fix is to set QLPrewiewView's shouldCloseWithWindow property to NO.
This, I suspect, tells the controller behind the scenes not to attach itself to higher level structures, i.e. tells it to remain self-sufficient.
So, adding this line to the code that sets up a new MyPrewiewView object in the sample code's ViewController.m file prevents the error:
qlView.shouldCloseWithWindow = NO;
My MacOS Cocoa application displays a window of static text, meaning it should not be changed by the user, should not be first responder, etcetera. The only thing that happens to the text is that each word of it changes color (from "idleColor" to "highlightColor", and then back again) at a specific point in time. It is similar to a Karaoke display - individual words change color, and then change back, under program control, based on a list of timed events.
All of this works beautifully under MacOS 10.7 and 10.8. BUT, under 10.9, the text color does NOT change UNLESS I click in the window and continually move the cursor around, so I am manually highlighting (and un-highlighting) some of the text, continuously. If I do this, the regular words behave as intended. Essentially, it feels like the OS is refusing to update the window under program control, unless I am forcing it to update by manually performing something that requires the UI to respond.
The code that performs the color changes is as follows:
if (sEvent.attribute == HIGHLIGHT_ON) {
[sTextView setTextColor:highlightColor range: currentRange];
textIsLitUp = YES;
}
else {
[sTextView setTextColor:idleColor range: currentRange];
textIsLitUp = NO;
}
[sTextView setNeedsDisplay:YES];
(sTextView is a subclass of NSTextView.)
Now, if I comment out that last line, then I get the same, incorrect behavior under 10.7 and 10.8. In other words, under 10.9, the setNeedsDisplay method is not working, or not working the same way.
Does anyone have any ideas about working around this, or have any other light to shed on the problem? Or am I doing something terribly wrong? It is CRITICAL to the application that the changes to the textColor happen without latency!
EDITING MY QUESTION - to answer it:
Found the answer elsewhere here! I needed to call setNeedsDisplay on the main thread - it was in a secondary thread. The weird thing is that it always seemed to work fine under 10.7 and 10.8. It only broke under 10.9. So I just changed this:
[myTextField setNeedsDisplay:YES];
To this:
dispatch_async(dispatch_get_main_queue(), ^{[myTextField setNeedsDisplay:YES];});
…and it seem to have worked. Hope this helps someone else…
You don’t want to do any of the changing of AppKit objects in non-main threads—it’ll work sometimes, maybe even often, but then every once in a while it’ll crash, and you’ll wonder why. So:
[sTextView setTextColor:idleColor range: currentRange];
needs to be on the main thread, too.
I am working on a cross platform application that is over a decade old. The UI is by Qt and backend rendering is done with OpenGL. OpenGL contexts are managed in the back end, not by Qt.
I have recently added error checking and reporting for all OpenGL code in our app. Occasionally a situation arises where the first render initiated by Qt causes an "invalid drawable" error message in the terminal and all subsequent OpenGl calls fail with an "invalid framebuffer" error reported. These invalid drawable error messages have been treated as innocuous in the past, since before the user sees it the drawable eventually becomes valid and the scene is rendered correctly. However, with the new OpenGL error check/report it's not possible since there are large numbers of errors reported.
I would like to test if the drawable is valid. If it is not, it should return before the render starts. How can I verify that the drawable is valid?
MacBook Pro, OS X Mountain Lion (10.8.3), ati graphics card
I don't know at what API level you're working. I'm not sure it's possible to detect the problem after the fact. That is, if all you have is a context (perhaps implicit as the thread's current context) that failed to connect to its drawable.
I presume that Qt is using Cocoa under the hood. I further assume it has created an NSOpenGLContext and is invoking -setView: on it. You get that "invalid drawable" error if, at the time of that call, the view's window doesn't have a window device.
One common technique is to defer setting the context's view until the view has -drawRect: called on it, since at that point you're sure that the view has a window and the window has a device. (Although that ignores the possibility of forced drawing outside of the normal window display mechanism. For example, -cacheDisplayInRect:toBitmapImageRep:.)
If you just want to know at the point of the call to -setView: whether it's safe or not, I think you can rely on checking the value of [[view window] windowNumber]. The docs for -windowNumber say:
If the window doesn’t have a window device, the value returned will be equal to or less than 0.
Another approach is to prevent the problem rather than detect it. The strategy for that is basically to make sure the window has been shown and drawn before the call to -setView:. You may be able to force that by ordering it on-screen and invoking -display on it.
Ken Thomases post gave me the basic info I needed to find a workable solution. An additional conditional was needed. Here's what worked
//----------------------------------------------------------------------------
bool vtkCocoaRenderWindow::IsDrawable()
{
// you must initialize it first
// else it always evaluates false
this->Initialize();
// first check that window is valid
NSView *theView = (NSView*)this->GetWindowId();
bool win =[[theView window] windowNumber]>0;
// then check that the drawable is valid
NSOpenGLContext *context = (NSOpenGLContext *)this->GetContextId();
bool ok = [context view] != nil;
return win && ok;
}
Lately something weird has been happening to my projects in xcode: I've been trying to learn a lot of new stuff, and doing so by testing things out in different simple cocoa apps (written by me, from scratch). sometimes I will get a code that doesn't have any error messages, but when i run it, i will stop at some break-point. I then conclude that I have probably done something wrong, and restores the code back to the form it was before the error, but from then on out it is impossible to get the code to run. even if i restore the code to a state that i am 100 % sure that has worked before, it just stops at the same break-point. in order to fix this problem, i have to copy my code from the class this has happened to, delete the class, make a new one with the exact same name, paste the exact same code back in the class, and voila, it works again. what on earth is happening? my newest problem code goes like this:
-(IBAction)openFile:(id)sender {
NSOpenPanel *openPanel = [[NSOpenPanel alloc] init];
NSURL *fileURL;
[openPanel setCanChooseFiles:YES];
[openPanel setCanChooseDirectories:NO];
[openPanel setAllowsMultipleSelection:NO];
[openPanel setAllowedFileTypes:[NSArray arrayWithObject:#"txt"]];
if ( [openPanel runModal] == NSOKButton ) {
fileURL = [openPanel URL];
}
[openPanel release];
}
I know this code has worked before. It is currently my only method, and it activates when i press open in the menu. If I delete everything inside the method, so that pressing open should do nothing it stops at a break-point inside the method anyway. I have had exactly the same kind of problem before with openGL codes, and with a method that used c syntax to do file reading. Does anybody know what kind of horrible mistake I'm making over and over again?
A Breakpoint is something you yourself set explicitly to tell Xcode to pause the program at this exact line. Superficially it might look like the program crashed, but in reality it's just waiting for you to tell it to go on.
This page looks like it has a nice explanation of the breakpoint interface in Xcode. (This is from a framework called Cocos2D, but ignore that. You should stick to ordinary Cocoa until you know what you're doing.)
I am developing a cocoa application which downloads firmware to the device. The progress of downloading is showed using NSProgressIndicator. I call the -incrementBy: method of NSProgressIndicator after DeviceRequestTO method in a while loop. But the progress indicator gets updated only after the entire firmware is written to the device. It shows 100% completion at one go itself. So I added the -displayIfNeeded method of NSView class. Now it shows progress smoothly but this too occurs after the firmware download is complete. How can I achieve the progress indication and write operation simultaneously?
Following is the code:
while(1)
{
int result = (*dev)->DeviceRequestTO(dev, &request);
printf("\nBlocks Written Successfully: %d",DfuBlockCnt);
[refToSelf performSelectorOnMainThread:#selector(notifyContent)
withObject:nil
waitUntilDone:NO];
}
//In main thread
- (void)notifyContent{
[dnldIndicator incrementBy:1];
[self displayIfNeeded];
}
The method you need to call is setNeedsDisplay:, not displayIfNeeded. The latter means “send yourself display if somebody has sent you setNeedsDisplay:YES”. If you don't do that last part, the view doesn't know it should display, and displayIfNeeded will do nothing.
And once you add the setNeedsDisplay: message, you may be able to cut out the displayIfNeeded message, as the framework sends that message to the window (and, hence, to all its views) periodically anyway.
Your code looks exactly like some that I use for updating UIProgressIndicators and NSProgressIndicators on the Mac and iPhone, code that works perfectly for me. I'm assuming, like menumachine, that your while loop exists on a background thread (created using performSelectorInBackground:withObject: or NSThread's detachNewThreadSelector:toTarget:withObject:).
Are the minValue and maxValue of the progress indicator set correctly (0 and 100 or whatever your scale is)?
How frequently do updates occur? Maybe you're sending too many events too quickly and the UI is not having a chance to update properly.
This code should work, as far as I can tell.