I am doing drag and drop with NSView.
In the object to be dragged, which is subclass of NSView, I implemented mouseDown: method as follows:
#try {
NSPoint location;
NSSize size ;
NSPasteboard *pb = [NSPasteboard pasteboardWithName:#"CameraIconContainer"];
location.x = ([self bounds].size.width - size.width)/2 - 21.0;
location.y = ([self bounds].size.height - size.height)/2 - 7.0;
NSLog(#"mouseDown: location- (%f, %f)",location.x,location.y);
NSDictionary *iconViewDict = [[NSDictionary alloc] initWithObjectsAndKeys:[cameraNo stringValue],#"cameraNo",nil];
NSLog(#"iconViewDict - %#",iconViewDict);
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:iconViewDict];
[pb declareTypes:[NSArray arrayWithObject:IconDragDataType] owner:self];
[pb setData:data forType:IconDragDataType];
[self dragImage:[NSImage imageNamed:#"camera_icon.png"] at:location offset:NSZeroSize event:e pasteboard:pb source:self slideBack:YES];
}
#catch (NSException * e) {
NSLog(#"CameraIconView (-mouseDown:), error - %#",e);
}
Most of the time it is working fine but problem is- sometimes it is raising this
exception:Invalid parameter not
satisfying: theWriteStream != NULL
in the mouseDown: method, because of it the dragged image continuously appears over screen, which does not disappear even if some other window is selected.
Can anyone suggest me why is it occurring and how can I resolve it?
Thanks,
Miraaj
exception:Invalid parameter not satisfying: theWriteStream != NULL
That sort of exception comes from an assertion. Something is about to try to write to a stream, and asserted that it has a stream to write to. When the assertion fails, that means that the condition was untrue; in this case, it means that it did not have a stream to write to.
I don't see any stream-related code in the sample you provided, so it's either somewhere else in your app or somewhere within a framework you're using. You should turn on “Stop on Objective-C exceptions” in Xcode, then run your app under the debugger until the exception occurs, then look at the stack trace in the debugger to see exactly what threw the exception.
Related
I am trying to customize an NSImageCell for NSTableView using NSArrayController and bindings to change the background of the cell which is selected. So, I created two NSImage images and retain them as normalImage and activeImage in the cell instance, which means I should release these two images when the cell calls its dealloc method. And I override
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
and
- (void) setObjectValue:(id) inObject
But I find that when I click any cell in the tableview, the cell's dealloc method is called.
So I put NSLog(#"%#", self); in the dealloc method and - (void)drawInteriorWithFrame:inView: and I find that these two instance are not same.
Can anyone tell me why dealloc is called every time I click any cell? Why are these two instances not the same? What does OS X do when I customize the cell in NSTableView?
BTW: I found that the -init is called only once. Why?
EDIT:
My cell code
#implementation SETableCell {
NSImage *_bgNormal;
NSImage *_bgActive;
NSString *_currentString;
}
- (id)init {
if (self = [super init]) {
NSLog(#"setup: %#", self);
_bgNormal = [[NSImage imageNamed:#"bg_normal"] retain];
_bgActive = [[NSImage imageNamed:#"bg_active"] retain];
}
return self;
}
- (void)dealloc {
// [_bgActive release]; _bgActive = nil;
// [_bgNormal release]; _bgNormal = nil;
// [_currentString release]; _currentString = nil;
NSLog(#"dealloc: %#", self);
[super dealloc];
}
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
NSLog(#"draw: %#", self);
NSPoint point = cellFrame.origin;
NSImage *bgImg = self.isHighlighted ? _bgActive : _bgNormal;
[bgImg drawAtPoint:p fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
NSPoint strPoint = cellFrame.origin;
strPoint.x += 30;
strPoint.y += 30;
[_currentString drawAtPoint:strPoint withAttributes:nil];
}
- (void) setObjectValue:(id) inObject {
if (inObject != nil && ![inObject isEqualTo:_currentString]) {
[self setCurrentInfo:inObject];
}
}
- (void)setCurrentInfo:(NSString *)info {
if (_currentString != info) {
[_currentString release];
_currentString = [info copy];
}
}
#end
As a normal recommendation, you should move to ARC as it takes cares of most of the memory management tasks that you do manually, like retain, releases. My answers will assume that you are using manual memory management:
Can anyone tell me why dealloc is called every time I click any cell ?
The only way for this to happen, is if you are releasing or auto-releasing your cell. If you are re-using cells, they shouldn't be deallocated.
Why these tow instance are not same ?
If you are re-using them, the cell that you clicked, and the cell that has been deallocated, they should be different. Pay close attention to both your questions, in one you assume that you are releasing the same cell when you click on it, on the second you are seeing that they are different.
What does Apple do when I custom the cell in NSTableView ?
Apple as a company? Or Apple as in the native frameworks you are using? I am assuming you are going for the second one: a custom cell is just a subclass of something that the NSTableView is expecting, it should behave the same as a normal one plus your custom implementation.
BTW: I found that the init is called only once, and why ?
Based on this, you are probably re-using cells, and only in the beginning they are actually being initialised.
It would be very useful to see some parts of your code:
Your Cell's code
Your NSTableView cell's creation code.
I'm trying to make a free music app and i am trying to put in mp4 video of the music. But the second button just makes it crash with return UIApplicationMain(argc, argv, nil,
NSStringFromClass([AppDelegate class] The code i'm using is
- (IBAction)playButton:(id)sender {
NSString *stringPath = [[NSBundle mainBundle]pathForResource:#"Under_Control" ofType:#"mp3"];
NSURL *url = [NSURL fileURLWithPath:stringPath];
mpc = [[MPMoviePlayerController alloc]initWithContentURL:url];
[mpc setMovieSourceType:MPMovieSourceTypeFile];
[[self view]addSubview:mpc.view];
[mpc setFullscreen:YES];
[mpc play];
And also put
{
MPMoviePlayerController *mpc;
}
Under #interface ViewController;
A crash in that location simply means there was an uncaught exception somewhere in your code. Adding an exception breakpoint in Xcode (Exception breakpoints) will make the program crash on the line that is throwing the exception.
Edit: another thought, are you getting a valid URL variable back? I'm guessing that passing nil to the MPMoviePlayerController is the problem you are having.
If you are using storyboards, check to make sure that you don't have duplicate referencing outlets that you hooked up, or referencing outlets that shouldn't be there anymore that don't have matching methods in your code anymore.
I have broken this down into a very small project. Using the following code in the application delegate:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
TestingWindowController * testingWindowController = [[TestingWindowController alloc] initWithWindowNibName: #"TestingWindowController"];
// Begin our sheet
[NSApp beginSheet: testingWindowController.window
modalForWindow: self.window
modalDelegate: self
didEndSelector: #selector(windowDidEnd:returnCode:contextInfo:)
contextInfo: NULL];
}
- (void)windowDidEnd:(id)alert returnCode:(NSInteger)returnCode contextInfo:(id) contextInfo
{
// If the user did not accept, then we really don't care what else they did!
if (returnCode != NSOKButton) return;
// We have had an error. Display it.
[[NSApplication sharedApplication] presentError: nil
modalForWindow: self.window
delegate: nil
didPresentSelector: nil
contextInfo: NULL];
}
And the following action tied to button on the windows nib. (Note that the nib's window is also set to not be visible on launch).
- (IBAction) onClose: (id) sender
{
[[NSApplication sharedApplication] endSheet: self.window
returnCode: NSOKButton];
[self.window orderOut: nil];
} // End of onClose
What ends up happening is, once I the onClose runs, all of the windows disappear and I am left with nothing but the error dialog (the main window has disappeared).
Is there something wrong with my code? Why does my main window go away?
NOTE: I know that I am not passing an error to the presentError method. I purposely left this null as I only had a short time to write the sample code. Passing an actual error results in the same behaviour.
Sample project is available here.
Looks like you are still using the old api, try the new one
(deselect Always visible at launch for the UserLoginWindowController window)
- (IBAction)userButtonPressed:(id)sender {
UserLoginWindowController * wc = [UserLoginWindowController new];
// we keep a reference, so the WC doesn't deallocate
self.modalWindowController = wc;
[[self window] beginSheet:[wc window] completionHandler:^(NSModalResponse returnCode) {
self.modalWindowController = nil;
}];
}
in the UserLoginWindowController
- (IBAction)cancelButtonPressed:(id)sender {
[[[self window] sheetParent] endSheet:[self window] returnCode:NSModalResponseCancel];
}
You are using 2 methods to open your window, beginSheet:....., and runModalForWindow:. You only need one of those. If you want a sheet attached to your window, use the first method, if you want a stand alone window, use the second. Likewise, in your onClose method, you should use endSheet:returnCode: if you're closing a sheet (the argument for that method should be testingWindowController.window not self.window) , and stopModalWithCode: if you're closing a modal window, you shouldn't have both.
i´m using the AVAssetImageGenerator to get images from a movieclip without playing it before. Now i´ve got a question how to set up variables in the loop of a handler?
Is it possible?
I´m getting this error message and have no idea what does that mean. (google> no results).
"Variable is not assignable (missing
__block type specifier)"
So i have to ask the pro´s here.
Here´s the code. I want to save or return my generated imageData, so i can delete the "setImage" message within that following handler.
UIImage* thumbImg = [[UIImage alloc] init];
AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error)
{
if (result != AVAssetImageGeneratorSucceeded)
{
NSLog(#"couldn't generate thumbnail, error:%#", error);
}
[button setImage:[UIImage imageWithCGImage:im] forState:UIControlStateNormal];
thumbImg = [[UIImage imageWithCGImage:im] retain];
[generator release];
};
Would be great to learn about that.
Thanks for your time.
1st of all it seems you don't need to init your thumbImg when its declared - UIImage object created in that line will be overwritten in block and will leak. Just init it with nil value.
Actual problem in your code is that variable you're going to change in block should be declared with __block specifier (as error message says). So your 1s line should be
__block UIImage* thumbImg = nil;
I'd like to adjust the NSApplicationIcon image that gets shown automatically in all alerts to be something different than what is in the app bundle.
I know that it's possible to set the dock icon with [NSApplication setApplicationIconImage:] -- but this only affects the dock, and nothing else.
I'm able to work around this issue some of the time: I have an NSAlert *, I can call setIcon: to display my alternate image.
Unfortunately, I have a lot of nibs that have NSImageView's with NSApplicationIcon, that I would like to affect, and it would be a hassle to create outlets and put in code to change the icon. And for any alerts that I'm bringing up with the BeginAlert... type calls (which don't give an NSAlert object to muck with), I'm completely out of luck.
Can anybody think of a reasonable way to globally (for the life of a running application) override the NSApplicationIcon that is used by AppKit, with my own image, so that I can get 100% of the alerts replaced (and make my code simpler)?
Swizzle the [NSImage imageNamed:] method? This method works at least on Snow Leopard, YMMV.
In an NSImage category:
#implementation NSImage (Magic)
+ (void)load {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// have to call imageNamed: once prior to swizzling to avoid infinite loop
[[NSApplication sharedApplication] applicationIconImage];
// swizzle!
NSError *error = nil;
if (![NSImage jr_swizzleClassMethod:#selector(imageNamed:) withClassMethod:#selector(_sensible_imageNamed:) error:&error])
NSLog(#"couldn't swizzle imageNamed: application icons will not update: %#", error);
[pool release];
}
+ (id)_sensible_imageNamed:(NSString *)name {
if ([name isEqualToString:#"NSApplicationIcon"])
return [[NSApplication sharedApplication] applicationIconImage];
return [self _sensible_imageNamed:name];
}
#end
With this hacked up (untested, just wrote it) jr_swizzleClassMethod:... implementation:
+ (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_ {
#if OBJC_API_VERSION >= 2
Method origMethod = class_getClassMethod(self, origSel_);
if (!origMethod) {
SetNSError(error_, #"original method %# not found for class %#", NSStringFromSelector(origSel_), [self className]);
return NO;
}
Method altMethod = class_getClassMethod(self, altSel_);
if (!altMethod) {
SetNSError(error_, #"alternate method %# not found for class %#", NSStringFromSelector(altSel_), [self className]);
return NO;
}
id metaClass = objc_getMetaClass(class_getName(self));
class_addMethod(metaClass,
origSel_,
class_getMethodImplementation(metaClass, origSel_),
method_getTypeEncoding(origMethod));
class_addMethod(metaClass,
altSel_,
class_getMethodImplementation(metaClass, altSel_),
method_getTypeEncoding(altMethod));
method_exchangeImplementations(class_getClassMethod(self, origSel_), class_getClassMethod(self, altSel_));
return YES;
#else
assert(0);
return NO;
#endif
}
Then, this method to illustrate the point:
- (void)doMagic:(id)sender {
static int i = 0;
i = (i+1) % 2;
if (i)
[[NSApplication sharedApplication] setApplicationIconImage:[NSImage imageNamed:NSImageNameBonjour]];
else
[[NSApplication sharedApplication] setApplicationIconImage:[NSImage imageNamed:NSImageNameDotMac]];
// any pre-populated image views have to be set to nil first, otherwise their icon won't change
// [imageView setImage:nil];
// [imageView setImage:[NSImage imageNamed:NSImageNameApplicationIcon]];
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
[alert setMessageText:#"Shazam!"];
[alert runModal];
}
A couple of caveats:
Any image view already created must have setImage: called twice, as seen above to register the image changing. Don't know why.
There may be a better way to force the initial imageNamed: call with #"NSApplicationIcon" than how I've done it.
Try [myImage setName:#"NSApplicationIcon"] (after setting it as the application icon image in NSApp).
Note: On 10.6 and later, you can and should use NSImageNameApplicationIcon instead of the string literal #"NSApplicationIcon".