Changeset 11975


Ignore:
Timestamp:
Apr 27, 2009, 6:34:22 PM (10 years ago)
Author:
rme
Message:

Update nib-loading example by getting rid of @class and correcting
some memory manangement errors.

Location:
trunk/source/examples/cocoa/nib-loading
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/examples/cocoa/nib-loading/HOWTO.html

    r8503 r11975  
    134134
    135135      <p>Before we can ask the application anything, we need a
    136         reference to it. We'll ask the class NSApplication to give us a
    137         reference to the running application.</p>
     136        reference to it.  When the Clozure CL application starts up,
     137        it stores a reference to the Cocoa application object into
     138        the special variable *NSApp*.</p>
    138139
    139140      <p>Start by changing to the CCL package; most of the utility
     
    145146      </pre>
    146147
    147       <p>Next, get a reference to the NSApplication class:</p>
    148 
    149       <pre>
    150         ? (setf  *my-app*
    151         (let* ((class-name (%make-nsstring "NSApplication"))
    152         (appclass (#_NSClassFromString class-name)))
    153         (#/release class-name)
    154         (#/sharedApplication appclass)))
    155         #&lt;LISP-APPLICATION &lt;LispApplication: 0x1b8de0&gt; (#x1B8DE0)&gt;
    156       </pre>
    157 
    158       <p>Let's review this form step-by-step.</p>
    159 
    160       <p>First of all, it's going to store the returned application
    161         object in the variable <code>*my-app*</code>, so that we have it
    162         convenient for later use.</p>
    163 
    164       <p>We need an <code>NSString</code> object that contains the
    165         name of the application class, so the code allocates one by
    166         calling <code>%make-nsstring</code>. The <code>NSString</code>
    167         object is a dynamically-allocated foreign object, not managed by
    168         Lisp's garbage-collector, so we'll have to be sure to release it
    169         later.</p>
    170 
    171       <p>The code next uses the class-name to get the
    172         actual <code>NSApplication</code> class object, by
    173         calling <code>#_NSClassFromString</code>.</p>
    174 
    175       <p>Finally, after first releasing the <code>NSString</code>
    176         object, it calls <code>#/sharedApplication</code> to get the
    177         running application object, which turns out to be an instance
    178         of <code>LispApplication</code>.</p>
    179 
    180       <p>Voilà! We have a reference to the running Clozure CL
    181         application object! Now we can ask it for its zone, where it
    182         allocates objects in memory:</p>
    183 
    184       <pre>
    185         ? (setf *my-zone* (#/zone *my-app*))
     148      <p>We have a reference to the running Clozure CL application
     149        object in the special variable *NSApp*.  We can ask it for its
     150        zone, where it allocates objects in memory:</p>
     151
     152      <pre>
     153        ? (setf *my-zone* (#/zone *NSApp*))
    186154        #&lt;A Foreign Pointer #x8B000&gt;
    187155      </pre>
     
    220188      <pre>
    221189        ? (setf *my-dict*
    222         (#/dictionaryWithObject:forKey: (@class ns-mutable-dictionary)
     190        (#/dictionaryWithObject:forKey: ns:ns-mutable-dictionary
    223191        *my-app*
    224192        #@"NSNibOwner"))
     
    249217      <pre>
    250218        ? (#/loadNibFile:externalNameTable:withZone:
    251         (@class ns-bundle)
     219        ns:ns-bundle
    252220        *nib-path*
    253221        *my-dict*
     
    264232
    265233      <p>At this point we no longer need the pathname and
    266         dictionary objects, and we can release them:</p>
     234        dictionary objects.  The *nib-path* we must release:</p>
    267235
    268236      <pre>
    269237        ? (setf *nib-path* (#/release *nib-path*))
    270238        NIL
    271         ? (setf *my-dict* (#/release *my-dict*))
    272         NIL
    273       </pre>
     239      </pre>
     240
     241      <p>The *my-dict* instance was not created with #/alloc (or with
     242      MAKE-INSTANCE), so it is already autoreleased, and we don't need
     243      to release it again.
    274244
    275245      <div class="section-head">
     
    289259      <pre>
    290260(defun load-nibfile (nib-path)
    291   (let* ((app-class-name (%make-nsstring "NSApplication"))
    292          (app-class (#_NSClassFromString class-name))
    293          (app (#/sharedApplication appclass))
    294          (app-zone (#/zone app))
     261  (let* ((app-zone (#/zone *NSApp*))
    295262         (nib-name (%make-nsstring (namestring nib-path)))
    296263         (dict (#/dictionaryWithObject:forKey:
    297                 (@class ns-mutable-dictionary) app #@"NSNibOwner")))
    298     (#/loadNibFile:externalNameTable:withZone: (@class ns-bundle)
     264                 ns-mutable-dictionary app #@"NSNibOwner")))
     265    (#/loadNibFile:externalNameTable:withZone: ns:ns-bundle
    299266                                               nib-name
    300267                                               dict
    301                                                app-zone)))
    302       </pre>
    303 
    304       <p>The trouble with this function is that it leaks two strings
    305       and a dictionary every time we call it. We need to release the
    306       variables <code>app-class-name</code>, <code>nib-name</code>,
    307       and <code>dict</code> before returning. So how about this
     268                                               app-zone
     269                                             )))
     270      </pre>
     271
     272      <p>The trouble with this function is that it leaks a string
     273      every time we call it. We need to release the
     274      <code>nib-name</code> before returning. So how about this
    308275      version instead?</p>
    309276
    310277      <pre>
    311278(defun load-nibfile (nib-path)
    312   (let* ((app-class-name (%make-nsstring "NSApplication"))
    313          (app-class (#_NSClassFromString class-name))
    314          (app (#/sharedApplication appclass))
    315          (app-zone (#/zone app))
     279  (let* ((app-zone (#/zone *NSApp*))
    316280         (nib-name (%make-nsstring (namestring nib-path)))
    317281         (dict (#/dictionaryWithObject:forKey:
    318                 (@class ns-mutable-dictionary) app #@"NSNibOwner"))
    319          (result (#/loadNibFile:externalNameTable:withZone: (@class ns-bundle)
     282                ns-mutable-dictionary app #@"NSNibOwner"))
     283         (result (#/loadNibFile:externalNameTable:withZone: ns:ns-bundle
    320284                                                            nib-name
    321285                                                            dict
    322286                                                            app-zone)))
    323     (#/release app-class-name)
    324287    (#/release nib-name)
    325     (#/release dict)
    326288    result))
    327289      </pre>
     
    329291      <p>This version solves the leaking problem by binding the result
    330292      of the load call to <code>result</code>, then releasing the
    331       variables in question before returning the result of the
     293      <code>nib-name</code> before returning the result of the
    332294      load.</p>
    333295
     
    344306      <pre>
    345307(let* (...
    346        (objects-array (#/arrayWithCapacity: (@class ns-mutable-array) 16))
     308       (objects-array (#/arrayWithCapacity: ns:ns-mutable-array 16))
    347309       ...)
    348310  ...)
     
    356318      <pre>
    357319  (let* (...
    358          (dict (#/dictionaryWithObjectsAndKeys: (@class ns-mutable-dictionary)
     320         (dict (#/dictionaryWithObjectsAndKeys: ns:ns-mutable-dictionary
    359321                    app #@"NSNibOwner"
    360                     objects-array #&amp;NSToplevelObjects))
     322                    objects-array #&amp;NSToplevelObjects
     323                    +null-ptr+))
    361324         ...)
    362325    ...)
     
    364327      </pre>
    365328
    366       <p>We'll want to release the <code>NSMutableArray</code>
    367       object before returning, but first we need to collect the
    368       objects in it. We'll do that by making a local variable to
    369       store them, then iterating over the array object to get them all.</p>
     329      <p>We now want to collect the objects in it. We'll do that by
     330      making a local variable to store them, then iterating over the
     331      array object to get them all.  (Normally, when we want to keep
     332      an object from an array, we have to retain it.  Top-level nib
     333      objects are a special case: they are created by the nib loading
     334      process with a retain count of 1, and we are responsible for releasing
     335      them when we're through with them.)</p>
    370336
    371337      <pre>
     
    391357      <pre>
    392358(defun load-nibfile (nib-path)
    393   (let* ((app-class-name (%make-nsstring "NSApplication"))
    394          (app-class (#_NSClassFromString app-class-name))
    395          (app (#/sharedApplication app-class))
    396          (app-zone (#/zone app))
     359  (let* ((app-zone (#/zone *NSApp*))
    397360         (nib-name (%make-nsstring (namestring nib-path)))
    398          (objects-array (#/arrayWithCapacity: (@class ns-mutable-array) 16))
    399          (dict (#/dictionaryWithObjectsAndKeys: (@class ns-mutable-dictionary)
    400                     app #@"NSNibOwner"
    401                     objects-array #&amp;NSNibToplevelObjects))
     361         (objects-array (#/arrayWithCapacity: ns:ns-mutable-array 16))
     362         (dict (#/dictionaryWithObjectsAndKeys: ns:ns-mutable-dictionary
     363                    *NSApp* #@"NSNibOwner"
     364                    objects-array #&NSNibTopLevelObjects
     365                    +null-ptr+))
    402366         (toplevel-objects (list))
    403          (result (#/loadNibFile:externalNameTable:withZone: (@class ns-bundle)
     367         (result (#/loadNibFile:externalNameTable:withZone: ns:ns-bundle
    404368                                                            nib-name
    405369                                                            dict
     
    409373            (cons (#/objectAtIndex: objects-array i)
    410374                  toplevel-objects)))
    411     (#/release app-class-name)
    412375    (#/release nib-name)
    413     (#/release dict)
    414     (#/release objects-array)
    415376    (values toplevel-objects result)))
    416377      </pre>
  • trunk/source/examples/cocoa/nib-loading/nib-loading.lisp

    r8503 r11975  
    1313
    1414(defun load-nibfile (nib-path)
    15   (let* ((app-class-name (%make-nsstring "NSApplication"))
    16          (app-class (#_NSClassFromString app-class-name))
    17          (app (#/sharedApplication app-class))
    18          (app-zone (#/zone app))
     15  (let* ((app-zone (#/zone *NSApp*))
    1916         (nib-name (%make-nsstring (namestring nib-path)))
    20          (objects-array (#/arrayWithCapacity: (@class ns-mutable-array) 16))
    21          (dict (#/dictionaryWithObjectsAndKeys: (@class ns-mutable-dictionary)
    22                     app #@"NSNibOwner"
    23                     objects-array #&NSNibTopLevelObjects))
     17         (objects-array (#/arrayWithCapacity: ns:ns-mutable-array 16))
     18         (dict (#/dictionaryWithObjectsAndKeys: ns:ns-mutable-dictionary
     19                    *NSApp* #@"NSNibOwner"
     20                    objects-array #&NSNibTopLevelObjects
     21                    +null-ptr+))
    2422         (toplevel-objects (list))
    25          (result (#/loadNibFile:externalNameTable:withZone: (@class ns-bundle)
     23         (result (#/loadNibFile:externalNameTable:withZone: ns:ns-bundle
    2624                                                            nib-name
    2725                                                            dict
     
    3129            (cons (#/objectAtIndex: objects-array i)
    3230                  toplevel-objects)))
    33     (#/release app-class-name)
    3431    (#/release nib-name)
    35     (#/release dict)
    36     (#/release objects-array)
    3732    (values toplevel-objects result)))
    3833
Note: See TracChangeset for help on using the changeset viewer.