NSOpenPanel runModal on a dispatch
Hey, I'm trying to display an NSOpenPanel on a dispatch, with half-luck. The panel displays, but no files going to be displayed - the circle just spinning on the bottom-left corner. Anyone have an idea what going wrong? Thanks, Tamas dispatch_async(dispatch_get_main_queue(), ^{ NSOpenPanel *oPanel = [NSOpenPanel openPanel]; NSMutableArray *filetype = [NSMutableArray arrayWithCapacity:0]; [filetype insertObject:@txt atIndex:0]; [oPanel setAllowedFileTypes:filetype]; [oPanel setDirectoryURL:[NSURL URLWithString:NSHomeDirectory()]]; NSInteger returnCode = [oPanel runModal]; if (returnCode == NSOKButton) { NSLog(@OK!); } else { NSLog(@Cancel!); } }); ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
On 16 Dec 2012, at 10:45, Tamas Nagy tamas.lov.n...@gmail.com wrote: Hey, I'm trying to display an NSOpenPanel on a dispatch, with half-luck. The panel displays, but no files going to be displayed - the circle just spinning on the bottom-left corner. Anyone have an idea what going wrong? Thanks, Tamas dispatch_async(dispatch_get_main_queue(), ^{ NSOpenPanel *oPanel = [NSOpenPanel openPanel]; NSMutableArray *filetype = [NSMutableArray arrayWithCapacity:0]; [filetype insertObject:@txt atIndex:0]; [oPanel setAllowedFileTypes:filetype]; [oPanel setDirectoryURL:[NSURL URLWithString:NSHomeDirectory()]]; NSInteger returnCode = [oPanel runModal]; if (returnCode == NSOKButton) { NSLog(@OK!); } else { NSLog(@Cancel!); } }); I can't see off the top of my head what's going wrong here, but I just thought I'd comment that that looks like a pretty bizarre way of creating a constant array. 1) You know exactly how big the array's going to be – 1 object, so why hint that it's going to contain 0 objects? 2) Why use insertObject: atIndex:0 rather than addObject: 3) Why use a mutable array at all? You could just use a constant array – NSArray *filetype = [NSArray arrayWithObject:@txt]; 4) The above can then be further condensed with the new syntactic sugar for arrays: NSArray *filetype = @[ @txt ]; Thanks Tom Davie ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
Thanks for the suggestions Tom. I know about that things, but the original code was a bit bigger, where I need a mutable array and other stuff, and just trimmed out for the example. But to back to on-topic: the code works fine on 10.6.8, the issue happens only on 10.7.5 and 10.8.2. If I call the method with performSelectorOnMainThread… instead of dispatching, everything works fine. Maybe I found a bug. On Dec 16, 2012, at 4:32 PM, Tom Davie tom.da...@gmail.com wrote: On 16 Dec 2012, at 10:45, Tamas Nagy tamas.lov.n...@gmail.com wrote: Hey, I'm trying to display an NSOpenPanel on a dispatch, with half-luck. The panel displays, but no files going to be displayed - the circle just spinning on the bottom-left corner. Anyone have an idea what going wrong? Thanks, Tamas dispatch_async(dispatch_get_main_queue(), ^{ NSOpenPanel *oPanel = [NSOpenPanel openPanel]; NSMutableArray *filetype = [NSMutableArray arrayWithCapacity:0]; [filetype insertObject:@txt atIndex:0]; [oPanel setAllowedFileTypes:filetype]; [oPanel setDirectoryURL:[NSURL URLWithString:NSHomeDirectory()]]; NSInteger returnCode = [oPanel runModal]; if (returnCode == NSOKButton) { NSLog(@OK!); } else { NSLog(@Cancel!); } }); I can't see off the top of my head what's going wrong here, but I just thought I'd comment that that looks like a pretty bizarre way of creating a constant array. 1) You know exactly how big the array's going to be – 1 object, so why hint that it's going to contain 0 objects? 2) Why use insertObject: atIndex:0 rather than addObject: 3) Why use a mutable array at all? You could just use a constant array – NSArray *filetype = [NSArray arrayWithObject:@txt]; 4) The above can then be further condensed with the new syntactic sugar for arrays: NSArray *filetype = @[ @txt ]; Thanks Tom Davie ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: blocks and id
On 15.12.2012, at 01:44, Uli Kusterer wrote: On 15.12.2012, at 01:38, Uli Kusterer witness.of.teacht...@gmx.net wrote: On 12.12.2012, at 10:03, Andreas Grosam agro...@onlinehome.de wrote: How can I check at runtime whether an object (id) is actually a block, and not another kind of object? Not a good idea. What are you really trying to do? (I explained this in more detail in later posts, see also below) Here's a few common cases and suggestions on how to do it better, and why: 1) Serializing objects. Generally, the object (or a category on it if it's an object you didn't create) should implement a method that knows how to serialize/unserialize it, like -initWithCoder: and -encodeWithCoder:. This allows any class to be added, and allows for overriding a the method in a subclass. If you use -isKindOfClass: , all subclasses will also return YES, and that one method will have to know about all the different types (from different layers of your app that might be serialized), and you'll have one file with thousands of dependencies, that get dragged into any other app that wants to be able to use the same serialization mechanism. 2) Implementing special behaviour on some objects, while falling back on some default behaviour for all others. Call respondsToSelector: in this case. It has the advantage that it doesn't break duck typing. Even if you get an NSProxy for the actual object, it will respond to the selector and still work as expected. Same for any other kind of method forwarding or dynamic method implementation like Key-Value-Observing. I agree, and I understand the point. However, this won't help in *my* case. I cannot easily implement a category method for a class, since these objects don't know how to perform those actions required by the client. The kind of action performed depends on the traits (say, whether it is an associative container, an array of objects, a character representation, or a sequence of bytes, etc.) of the objects **and** the context: RXTraits* traits = [obj rx_traits]; // same as [[obj class] rx_traits]; if (traits.isAssociativeContainer) { [obj enumerateKeysAndObjectsUsingBLock: /* do something depending on context */ ]; } else if (traits.isOrderedSequence) { [obj enumerateObjectsAtIndexesUsingBlock: /* do something depending on context */ ]; } ... Passing the context through a category method would be possible, but this would result in many duplications of code - which is also a code smell ;) Using the traits concept, isn't for free as well, though. Asking for an object's class using isKindOfClass: is a definite code smell. I wouldn't say that this is always the case. But most often I don't want to know the kind of class, but some more abstract concept. So, asking the class is probably not what I want. Rather I want to know whether the object fulfills some promises or exhibits some behavior (the duck, you know). Then I agree, it is likely something that smells. Andreas ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
On 16 Dec 2012, at 10:45, Tamas Nagy wrote: Hey, I'm trying to display an NSOpenPanel on a dispatch, with half-luck. The panel displays, but no files going to be displayed - the circle just spinning on the bottom-left corner. Anyone have an idea what going wrong? Thanks, Tamas dispatch_async(dispatch_get_main_queue(), ^{ NSOpenPanel *oPanel = [NSOpenPanel openPanel]; NSMutableArray *filetype = [NSMutableArray arrayWithCapacity:0]; [filetype insertObject:@txt atIndex:0]; [oPanel setAllowedFileTypes:filetype]; [oPanel setDirectoryURL:[NSURL URLWithString:NSHomeDirectory()]]; This line of code is your problem. +URLWithString: is not an appropriate way to create a URL from a path. +fileURLWithPath:isDirectory: is what you want instead. +[NSSavePanel setDirectoryURL:] behaves oddly with non-existing paths, as covered at http://www.mikeabdullah.net/pre-populating-nssavepanel.html ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
Unfortunately that doesn't help. I think the issue should be related to dispatches, because it won't happen if I just call performSelectorOnMainThread... On Dec 16, 2012, at 6:05 PM, Mike Abdullah cocoa...@mikeabdullah.net wrote: On 16 Dec 2012, at 10:45, Tamas Nagy wrote: Hey, I'm trying to display an NSOpenPanel on a dispatch, with half-luck. The panel displays, but no files going to be displayed - the circle just spinning on the bottom-left corner. Anyone have an idea what going wrong? Thanks, Tamas dispatch_async(dispatch_get_main_queue(), ^{ NSOpenPanel *oPanel = [NSOpenPanel openPanel]; NSMutableArray *filetype = [NSMutableArray arrayWithCapacity:0]; [filetype insertObject:@txt atIndex:0]; [oPanel setAllowedFileTypes:filetype]; [oPanel setDirectoryURL:[NSURL URLWithString:NSHomeDirectory()]]; This line of code is your problem. +URLWithString: is not an appropriate way to create a URL from a path. +fileURLWithPath:isDirectory: is what you want instead. +[NSSavePanel setDirectoryURL:] behaves oddly with non-existing paths, as covered at http://www.mikeabdullah.net/pre-populating-nssavepanel.html ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
On Dec 16, 2012, at 2:45 AM, Tamas Nagy tamas.lov.n...@gmail.com wrote: dispatch_async(dispatch_get_main_queue(), ^{ NSOpenPanel *oPanel = [NSOpenPanel openPanel]; *Bzzt!* Thou shalt not do UI work on a background thread. You cannot use dispatch_async here. --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
On 16 Dec 2012, at 18:32, Kyle Sluder wrote: On Dec 16, 2012, at 2:45 AM, Tamas Nagy tamas.lov.n...@gmail.com wrote: dispatch_async(dispatch_get_main_queue(), ^{ NSOpenPanel *oPanel = [NSOpenPanel openPanel]; *Bzzt!* Thou shalt not do UI work on a background thread. You cannot use dispatch_async here. *Bzzt* he's not doing UI work on a background thread. In any normal app, this is running the code on the main thread. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
On 16 Dec 2012, at 17:20, Tamas Nagy wrote: Unfortunately that doesn't help. I think the issue should be related to dispatches, because it won't happen if I just call performSelectorOnMainThread... Can you post that variant of your code then, please? ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
On Dec 16, 2012, at 10:39 AM, Mike Abdullah cocoa...@mikeabdullah.net wrote: On 16 Dec 2012, at 18:32, Kyle Sluder wrote: On Dec 16, 2012, at 2:45 AM, Tamas Nagy tamas.lov.n...@gmail.com wrote: dispatch_async(dispatch_get_main_queue(), ^{ NSOpenPanel *oPanel = [NSOpenPanel openPanel]; *Bzzt!* Thou shalt not do UI work on a background thread. You cannot use dispatch_async here. *Bzzt* he's not doing UI work on a background thread. In any normal app, this is running the code on the main thread. Yeah. Um. Oops. My apologies. --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
On Sun, Dec 16, 2012, at 10:40 AM, Mike Abdullah wrote: On 16 Dec 2012, at 17:20, Tamas Nagy wrote: Unfortunately that doesn't help. I think the issue should be related to dispatches, because it won't happen if I just call performSelectorOnMainThread... Can you post that variant of your code then, please? Now that I'm actually awake, I'm able to reproduce Tamas's issue with a bare-bones Cocoa App on 10.7.5. Here's my app delegate: @implementation AppDelegate - (NSInteger)doOpenPanel:(id)unused; { return [[NSOpenPanel openPanel] runModal]; } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { #if 0 dispatch_async(dispatch_get_main_queue(), ^{ [self doOpenPanel:nil]; }); #else [self performSelector:@selector(doOpenPanel:) withObject:nil afterDelay:0]; #endif } @end If you go with the dispatch approach, you get the eternal spinner, and files never show up—or if they do, their QuickLook previews never show up. Notably, you can still interact with the open panel. If you go with -performSelector:::, it works fine. My guess is that NSOpenPanel is doing some work on a background thread, and that work is trying to use the main queue to inform the open panel of its completion. By using the dispatch_async approach, the main queue is blocked, and the background thread can't inform the open panel. The -performSelector::: approach uses a timer, so the nested invocation of the runloop that -runModal performs is still able to dequeue the background task completion's block off the main queue. --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
On Sun, Dec 16, 2012, at 11:28 AM, Kyle Sluder wrote: My guess is that NSOpenPanel is doing some work on a background thread, and that work is trying to use the main queue to inform the open panel of its completion. By using the dispatch_async approach, the main queue is blocked, and the background thread can't inform the open panel. The -performSelector::: approach uses a timer, so the nested invocation of the runloop that -runModal performs is still able to dequeue the background task completion's block off the main queue. To follow up: In general, it's just a bad idea to block the main queue. It so happens that currently CFRunLoop is responsible for draining the main queue in a runloop-based app, so your app is able to hobble along firing timers and doing delayed-performs. But one can envision that dependency being inverted in a future release of OS X such that it's the main queue that's responsible for driving the runloop. At that point, blocking the main queue would cause deadlock when you tried to reentrantly run the runloop. In 10.6, NSOpenPanel and NSSavePanel gained a -beginWtihCompletionHandler: method that lets you run the panel as a non-modal window. Consider using that instead of -runModal. --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
Thanks for the approach Kyle, but dispatch_async performs asynchronously, so it should not block the main thread. I fallback to performSelectorOnMainThread: method in my app, but the dispatch way is a bit straightforward in my opinion. I'll fill a rdar on this. On Dec 16, 2012, at 8:39 PM, Kyle Sluder k...@ksluder.com wrote: On Sun, Dec 16, 2012, at 11:28 AM, Kyle Sluder wrote: My guess is that NSOpenPanel is doing some work on a background thread, and that work is trying to use the main queue to inform the open panel of its completion. By using the dispatch_async approach, the main queue is blocked, and the background thread can't inform the open panel. The -performSelector::: approach uses a timer, so the nested invocation of the runloop that -runModal performs is still able to dequeue the background task completion's block off the main queue. To follow up: In general, it's just a bad idea to block the main queue. It so happens that currently CFRunLoop is responsible for draining the main queue in a runloop-based app, so your app is able to hobble along firing timers and doing delayed-performs. But one can envision that dependency being inverted in a future release of OS X such that it's the main queue that's responsible for driving the runloop. At that point, blocking the main queue would cause deadlock when you tried to reentrantly run the runloop. In 10.6, NSOpenPanel and NSSavePanel gained a -beginWtihCompletionHandler: method that lets you run the panel as a non-modal window. Consider using that instead of -runModal. --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
Performing asynchronously and blocking the main *queue* are not related things. The main queue is a serial queue, it only executes one block at a time. At the moment, it's executing your block, stuck in your runModal call. That runModal call will not come off the stack, and the block finish executing until the open dialog is closed. If the openDialog methods dispatch to the main queue, their dispatches will not occur until the main queue is able to run another block, which won't happen until your block finishes. You are very much blocking the main queue. Thanks Tom Davie On 16 Dec 2012, at 20:04, Tamas Nagy tamas.lov.n...@gmail.com wrote: Thanks for the approach Kyle, but dispatch_async performs asynchronously, so it should not block the main thread. I fallback to performSelectorOnMainThread: method in my app, but the dispatch way is a bit straightforward in my opinion. I'll fill a rdar on this. On Dec 16, 2012, at 8:39 PM, Kyle Sluder k...@ksluder.com wrote: On Sun, Dec 16, 2012, at 11:28 AM, Kyle Sluder wrote: My guess is that NSOpenPanel is doing some work on a background thread, and that work is trying to use the main queue to inform the open panel of its completion. By using the dispatch_async approach, the main queue is blocked, and the background thread can't inform the open panel. The -performSelector::: approach uses a timer, so the nested invocation of the runloop that -runModal performs is still able to dequeue the background task completion's block off the main queue. To follow up: In general, it's just a bad idea to block the main queue. It so happens that currently CFRunLoop is responsible for draining the main queue in a runloop-based app, so your app is able to hobble along firing timers and doing delayed-performs. But one can envision that dependency being inverted in a future release of OS X such that it's the main queue that's responsible for driving the runloop. At that point, blocking the main queue would cause deadlock when you tried to reentrantly run the runloop. In 10.6, NSOpenPanel and NSSavePanel gained a -beginWtihCompletionHandler: method that lets you run the panel as a non-modal window. Consider using that instead of -runModal. --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/tom.davie%40gmail.com This email sent to tom.da...@gmail.com ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
Ahh, okay, thanks for the explanation Tom, now I got it. On Dec 16, 2012, at 9:21 PM, Tom Davie tom.da...@gmail.com wrote: Performing asynchronously and blocking the main *queue* are not related things. The main queue is a serial queue, it only executes one block at a time. At the moment, it's executing your block, stuck in your runModal call. That runModal call will not come off the stack, and the block finish executing until the open dialog is closed. If the openDialog methods dispatch to the main queue, their dispatches will not occur until the main queue is able to run another block, which won't happen until your block finishes. You are very much blocking the main queue. Thanks Tom Davie On 16 Dec 2012, at 20:04, Tamas Nagy tamas.lov.n...@gmail.com wrote: Thanks for the approach Kyle, but dispatch_async performs asynchronously, so it should not block the main thread. I fallback to performSelectorOnMainThread: method in my app, but the dispatch way is a bit straightforward in my opinion. I'll fill a rdar on this. On Dec 16, 2012, at 8:39 PM, Kyle Sluder k...@ksluder.com wrote: On Sun, Dec 16, 2012, at 11:28 AM, Kyle Sluder wrote: My guess is that NSOpenPanel is doing some work on a background thread, and that work is trying to use the main queue to inform the open panel of its completion. By using the dispatch_async approach, the main queue is blocked, and the background thread can't inform the open panel. The -performSelector::: approach uses a timer, so the nested invocation of the runloop that -runModal performs is still able to dequeue the background task completion's block off the main queue. To follow up: In general, it's just a bad idea to block the main queue. It so happens that currently CFRunLoop is responsible for draining the main queue in a runloop-based app, so your app is able to hobble along firing timers and doing delayed-performs. But one can envision that dependency being inverted in a future release of OS X such that it's the main queue that's responsible for driving the runloop. At that point, blocking the main queue would cause deadlock when you tried to reentrantly run the runloop. In 10.6, NSOpenPanel and NSSavePanel gained a -beginWtihCompletionHandler: method that lets you run the panel as a non-modal window. Consider using that instead of -runModal. --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/tom.davie%40gmail.com This email sent to tom.da...@gmail.com ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
On Sun, Dec 16, 2012, at 12:04 PM, Tamas Nagy wrote: Thanks for the approach Kyle, but dispatch_async performs asynchronously, so it should not block the main thread. I fallback to performSelectorOnMainThread: method in my app, but the dispatch way is a bit straightforward in my opinion. I'll fill a rdar on this. It's not the dispatch_async() call that's blocking the main thread. It's the block you've enqueued. Imagine that instead of -runModal, we had this: void DoTheThing() { dispatch_async(dispatch_get_main_queue(), ^{ /* Let's call this POINT A. */ int result = GetTheResult(); /* Let's call this POINT C. */ NSLog(@Result: %ld, result); }); } int GetTheResult() { /* We've got to do some prep work which will take a long time. Let's show a spinner. */ ShowTheSpinner(); /* But we want to let the user interact with the dialog while we're doing the prep work, so let's do it on a background queue. */ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{ DoABunchOfWork(); /* We're done! We need to hide the spinner from the main thread */ dispatch_async(dispatch_get_main_queue(), ^{ /* Let's call this POINT B. */ HideTheSpinner(); }); } /* While the work is being done in the background, run the main thread's runloop reentrantly until the user dismisses the dialog. We don't return from this function until the user chooses one of those buttons. */ while (TheUserHasntHitCancelOrOk) [[NSRunLoop currentRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate distantFuture]]; return UserCanceled ? 0 : 1; } As you can see, POINT B needs to happen on the main thread, so it is wrapped inside a block that's enqueued on the main queue. But because GetTheResult() doesn't return until the user clicks Cancel or OK, POINT B can't execute because POINT A is still executing! The very nature of queues says we need to get to POINT C before POINT B can execute. --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
On Sun, Dec 16, 2012, at 12:04 PM, Tamas Nagy wrote: Thanks for the approach Kyle, but dispatch_async performs asynchronously, so it should not block the main thread. I fallback to performSelectorOnMainThread: method in my app, but the dispatch way is a bit straightforward in my opinion. I'll fill a rdar on this. By the way, I've just filed a radar asking for -[NSOpenPanel runModal] to be deprecated: rdar://problem/12889956 -beginWithCompletionHandler: is a far better user experience, and it's immune to this problem. Use that. --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
On 16 Dec 2012, at 20:04, Tamas Nagy wrote: Thanks for the approach Kyle, but dispatch_async performs asynchronously, so it should not block the main thread. I fallback to performSelectorOnMainThread: method in my app, but the dispatch way is a bit straightforward in my opinion. I'll fill a rdar on this. Possibly you could still use a block-based API but that uses -performSelector… under the hood, such as https://github.com/karelia/KSThreadProxy ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
On Dec 16, 2012, at 9:05 AM, Mike Abdullah cocoa...@mikeabdullah.net wrote: On 16 Dec 2012, at 10:45, Tamas Nagy wrote: Hey, I'm trying to display an NSOpenPanel on a dispatch, with half-luck. The panel displays, but no files going to be displayed - the circle just spinning on the bottom-left corner. Anyone have an idea what going wrong? Thanks, Tamas dispatch_async(dispatch_get_main_queue(), ^{ NSOpenPanel *oPanel = [NSOpenPanel openPanel]; NSMutableArray *filetype = [NSMutableArray arrayWithCapacity:0]; [filetype insertObject:@txt atIndex:0]; [oPanel setAllowedFileTypes:filetype]; [oPanel setDirectoryURL:[NSURL URLWithString:NSHomeDirectory()]]; This line of code is your problem. +URLWithString: is not an appropriate way to create a URL from a path. +fileURLWithPath:isDirectory: is what you want instead. +[NSSavePanel setDirectoryURL:] behaves oddly with non-existing paths, as covered at http://www.mikeabdullah.net/pre-populating-nssavepanel.html On 10.7.4 (or there abouts) and up -setDirectoryURL will spew in the console if you pass it a non-file URL or a nonexistent URL. It must have the “file://“ scheme. It will also spew out the directory it will use instead, which is usually the directory the user last visited with the app, the last valid directory passed to -setDirectoryURL:, or ~/Documents.. The spew would be something like this: Invalid URL passed to an open/save panel: '/Users/rob/Desktop'. Using 'file:///Users/rob/Documents/' instead —Rob ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
Thanks Kyle. I know about beginWithCompletionHandler: , but I really need a modal window at that point my application opens the open panel. On Dec 16, 2012, at 9:39 PM, Kyle Sluder k...@ksluder.com wrote: On Sun, Dec 16, 2012, at 12:04 PM, Tamas Nagy wrote: Thanks for the approach Kyle, but dispatch_async performs asynchronously, so it should not block the main thread. I fallback to performSelectorOnMainThread: method in my app, but the dispatch way is a bit straightforward in my opinion. I'll fill a rdar on this. By the way, I've just filed a radar asking for -[NSOpenPanel runModal] to be deprecated: rdar://problem/12889956 -beginWithCompletionHandler: is a far better user experience, and it's immune to this problem. Use that. --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
On Sun, Dec 16, 2012, at 09:43 PM, Tamas Nagy wrote: Thanks Kyle. I know about beginWithCompletionHandler: , but I really need a modal window at that point my application opens the open panel. I have to ask, why? If you want to block interaction with a document, you can use -beginSheetModalForWindow:completionHandler:. What circumstances could arise that would require you to block access to the entire app? --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSOpenPanel runModal on a dispatch
It's a live video app, where rendering happening on a CVDisplayLink thread, so the app still running and do its job while an OpenPanel (or SavePanel) displaying. I just need to block the UI to make sure the users can't interact the app while an open panel displaying. On Dec 17, 2012, at 6:46 AM, Kyle Sluder k...@ksluder.com wrote: On Sun, Dec 16, 2012, at 09:43 PM, Tamas Nagy wrote: Thanks Kyle. I know about beginWithCompletionHandler: , but I really need a modal window at that point my application opens the open panel. I have to ask, why? If you want to block interaction with a document, you can use -beginSheetModalForWindow:completionHandler:. What circumstances could arise that would require you to block access to the entire app? --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com