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.
previous month january 2012 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Go to today