NSOpenPanel problem
-
Hello,
Suppose I want to display a modeless choose file dialog with the
beginWithCompletionHandler method.
How can I pass some context info to the handler?
The beginForDirectory method has a contextInfo parameter but I want to
use the newer method.
TIA,
Jan E. -
On Jan 22, 2012, at 1:24 PM, Jan E. Schotsman wrote:
> Suppose I want to display a modeless choose file dialog with the beginWithCompletionHandler method.
> How can I pass some context info to the handler?
Blocks capture whatever local variables you reference within them. If you reference instance variables, they capture "self" and then access the ivars from that. Just use whatever value you want, directly. That's the great thing about blocks.
Cheers,
Ken -
On Jan 23, 2012, at 5:17 AM, Ken Thomases wrote:
> On Jan 22, 2012, at 1:24 PM, Jan E. Schotsman wrote:
>
>> Suppose I want to display a modeless choose file dialog with the
>> beginWithCompletionHandler method.
>> How can I pass some context info to the handler?
>
> Blocks capture whatever local variables you reference within them.
> If you reference instance variables, they capture "self" and then
> access the ivars from that. Just use whatever value you want,
> directly. That's the great thing about blocks.
That's great indeed, but I need the block to work with a method
parameter (an NSString object). Do I need to copy the NSString to an
ivar?
-method:(NSString *)someString
{
(void)(^handler)(NSInteger result) = { <uses someString > };
[openPanel beginWithCompletionHandler: handler];
}
I have a related question for the old beginForDirectory method:
if I try to pass on someString in a C struct (contextInfo) then the
compiler complains that ARC doesn't like object pointers in C structs.
I could serialize and unserialize the string. Or is there a better way?
Jan E. -
(Re-post on list.)
On 1/23/12 1:41 AM, Jan E. Schotsman wrote:
> That's great indeed, but I need the block to work with a method
> parameter (an NSString object). Do I need to copy the NSString to an ivar?
No, you just use it directly. As Ken mentioned, any variable you
reference in a block is automatically captured by the block and remains
available for the duration of its existence - even outside the scope of
the original variable declaration.
(If you need to *write* to an outside variable inside a block, the
variable's declaration must include a __block modifier; this and other
quirks are noted in the documentation.)
You *really* need to read the docs on blocks and GCD since they are the
"modern" way of writing threaded code, implementing callbacks, etc. I'd
start with the "Short Practical Guide to Blocks" -
http://developer.apple.com/library/ios/#featuredarticles/Short_Practical_Gu
ide_Blocks/_index.html.
There are a plethora of WWDC videos from beginning to advanced on these
topics, too.
> if I try to pass on someString in a C struct (contextInfo) then the
> compiler complains that ARC doesn't like object pointers in C structs.
> I could serialize and unserialize the string. Or is there a better way?
Just use the NSString * right in the block - no need for structs,
serialization, or anything. That's why blocks are so useful.
--
Conrad Shultz
Synthetiq Solutions
www.synthetiqsolutions.com -
On Jan 23, 2012, at 11:37 AM, Conrad Shultz wrote:
> You *really* need to read the docs on blocks and GCD since they are
> the
> "modern" way of writing threaded code, implementing callbacks, etc.
> I'd
> start with the "Short Practical Guide to Blocks" -
> http://developer.apple.com/library/ios/#featuredarticles/
> Short_Practical_Guide_Blocks/_index.html.
OK, will do that.
>> if I try to pass on someString in a C struct (contextInfo) then the
>> compiler complains that ARC doesn't like object pointers in C
>> structs.
>> I could serialize and unserialize the string. Or is there a better
>> way?
>
> Just use the NSString * right in the block - no need for structs,
> serialization, or anything. That's why blocks are so useful.
I still need an alternative because I want to support Leopard where
blocks aren't available. I've written some code using
NSPropertyListSerialization which should do the trick.
Jan E. -
On Jan 23, 2012, at 9:16 AM, Jan E. Schotsman wrote:
> On Jan 23, 2012, at 11:37 AM, Conrad Shultz wrote:
>
>>> if I try to pass on someString in a C struct (contextInfo) then the
>>> compiler complains that ARC doesn't like object pointers in C structs.
>>> I could serialize and unserialize the string. Or is there a better way?
>>
>> Just use the NSString * right in the block - no need for structs,
>> serialization, or anything. That's why blocks are so useful.
>
>
> I still need an alternative because I want to support Leopard where blocks aren't available. I've written some code using NSPropertyListSerialization which should do the trick.
If you're supporting Leopard, then you can't use ARC and the original problem goes away. Also, serializing a string doesn't help because you still have a Cocoa object -- an NSData now instead of an NSString -- and you have to manage its memory just the same.
Regards,
Ken -
On Jan 23, 2012, at 5:08 PM, Ken Thomases wrote:
> If you're supporting Leopard, then you can't use ARC and the
> original problem goes away.
??? I have set development target = 10.7 SDK, deployment target 10.5 and ARC is on.
The compiler doesn't complain. I have clicked the "validate settings"
button and no problems are reported. Latest Mac OS, latest Xcode.
> Also, serializing a string doesn't help because you still have a
> Cocoa object -- an NSData now instead of an NSString -- and you have
> to manage its memory just the same.
That's what [data getBytes:length:] is for.
Jan E. -
On Jan 23, 2012, at 12:22 PM, Jan E. Schotsman wrote:
> On Jan 23, 2012, at 5:08 PM, Ken Thomases wrote:
>
>> If you're supporting Leopard, then you can't use ARC and the original problem goes away.
>
> ??? I have set development target = 10.7 SDK, deployment target = 10.5 and ARC is on.
> The compiler doesn't complain. I have clicked the "validate settings" button and no problems are reported. Latest Mac OS, latest Xcode.
I don't know about complaints from the compiler, but I'm certain that ARC can't be used with code deployed to Leopard. ARC requires support from the runtime libraries and that support was never released for Leopard.
For example, the Transitioning to ARC Release Notes say, "ARC is supported in Xcode 4.2 for Mac OS X v10.6 and v10.7 (64-bit applications)".
http://developer.apple.com/library/mac/#releasenotes/ObjectiveC/RN-Transiti
oningToARC/_index.html
>> Also, serializing a string doesn't help because you still have a Cocoa object -- an NSData now instead of an NSString -- and you have to manage its memory just the same.
>
> That's what [data getBytes:length:] is for.
I can't imagine that allocating a heap buffer for a serialized string is the best way to get data into the handler. If you are using ARC (which I believe you can't), then try CFBridgingRetain() balanced later with a CFRelease() or CFBridgingRelease().
Regards,
Ken -
On Jan 23, 2012, at 11:15 PM, Ken Thomases wrote:
> I don't know about complaints from the compiler, but I'm certain
> that ARC can't be used with code deployed to Leopard. ARC requires
> support from the runtime libraries and that support was never
> released for Leopard.
Thanks for your help. I didn't realize the runtime needs to support
ARC too.
Looks like I have to rethink my strategy. I am converting my apps to
Cocoa and I intended to keep supporting Leopard, but if this means I
cannot use ARC or have to use two different memory management schemes
then I'll probably go for Lion only.
> I can't imagine that allocating a heap buffer for a serialized
> string is the best way to get data into the handler. If you are
> using ARC (which I believe you can't), then try CFBridgingRetain()
> balanced later with a CFRelease() or CFBridgingRelease().
Ah, bridging to CoreFoundation is indeed much simpler.
Jan E.


