NSOpenPanel runModal on a dispatch

2012-12-16 Thread Tamas Nagy
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

2012-12-16 Thread Tom Davie

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

2012-12-16 Thread Tamas Nagy
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

2012-12-16 Thread Andreas Grosam

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

2012-12-16 Thread Mike Abdullah

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

2012-12-16 Thread Tamas Nagy
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

2012-12-16 Thread Kyle Sluder
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

2012-12-16 Thread Mike Abdullah

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

2012-12-16 Thread Mike Abdullah

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

2012-12-16 Thread Kyle Sluder

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

2012-12-16 Thread Kyle Sluder
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

2012-12-16 Thread Kyle Sluder
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

2012-12-16 Thread Tamas Nagy
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

2012-12-16 Thread Tom Davie
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

2012-12-16 Thread Tamas Nagy
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

2012-12-16 Thread Kyle Sluder
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

2012-12-16 Thread Kyle Sluder
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

2012-12-16 Thread Mike Abdullah

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

2012-12-16 Thread Rob Petrovec
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

2012-12-16 Thread Tamas Nagy
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

2012-12-16 Thread Kyle Sluder
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

2012-12-16 Thread Tamas Nagy
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