This repository has been archived by the owner on Jan 27, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbook.html
1842 lines (1406 loc) · 110 KB
/
book.html
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<!-- seems to be needed -->
<meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'">
<title>De Re NSObject</title>
<meta name="keywords" content="">
<!-- Twitter Cards -->
<meta name="twitter:title" content="De Re NSObject">
<meta name="twitter:site" content="@mulle_nat">
<meta name="twitter:creator" content="@mulle_nat">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://www.mulle-kybernetik.com/de-re-nsobject/images/features/book.png">
<!-- Open Graph -->
<meta property="og:locale" content="en_US">
<meta property="og:type" content="article">
<meta property="og:title" content="De Re NSObject">
<meta property="og:url" content="https://www.mulle-kybernetik.com/book.html">
<meta property="og:site_name" content="De Re NSObject">
<meta property="og:image" content="https://www.mulle-kybernetik.com/de-re-nsobject/images/features/book.png">
<meta property="og:logo" content="https://www.mulle-kybernetik.com/de-re-nsobject/images/logo.png">
<link href="/de-re-nsobject/atom.xml" type="application/atom+xml" rel="alternate" title="De Re NSObject Feed">
<link href="/de-re-nsobject/index.rdf" type="application/rss+xml" rel="alternate" title="De Re NSObject Feed">
<link rel="canonical" href="https://www.mulle-kybernetik.com/book.html">
<!-- Mobile Specific Metas
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSS
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/skeleton.css">
<!-- Code Color
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
<link rel="stylesheet" href="css/monokai.css">
<!-- Site custom css -->
<link rel="stylesheet" href="css/custom.css">
<!-- local FONT
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
<link rel="stylesheet" href="css/junction.css">
<link rel="stylesheet" href="css/poppins.css">
<!-- Favicon
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
<link rel="icon" type="image/svg" href="images/favicon.svg">
<!-- This tag allows for activation of ClearType in Mobile IE for smoothing fonts.-->
<meta http-equiv="cleartype" content="on">
<!-- http://t.co/dKP3o1e -->
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- For all browsers -->
</head>
<body class="post">
<div class="container">
<div class="row">
<div id="post-first" class="twelve columns">
<div class="title">
<div>
<h2>De Re NSObject <div style="font-size:10px; display: inline-block;">0.0.1</div> <a href="feed.xml"><img class="inline-img" src='images/feed-icon-28x28.png'></a></h2>
</div>
<h6>© 2025 by Nat!, Mulle kybernetiK. All rights reserved.</h6>
<p>
</div> <!-- title -->
<div id="main" role="main">
<h1>Intro</h1>
<p><img src="images/image-4.jpg" alt="Gratuitous banner" class="banner-image" /></p>
<p>This guide is all about the proper management of objects, how they are created
how they are destroyed and all things inbetween. Your <a href="//mulle-objc.github.io">mulle-objc</a> coding will be much more fruitful after you have read this guide.
The absolute minimum to take out of this guide is the <a href="always-autoreleased.html">AAO</a> chapter. The rest of the guide will serve to deepen your understanding of
the mulle-objc runtime. For even more information visit <a href="https://www.mulle-kybernetik.com/objc-runtime-in-pictures/">The Objective-C runtime in pictures</a> or the
developer guide <a href="https://mulle-objc.github.io/De-Re-mulle-objc/">De Re mulle-objc</a>.</p>
<h2 id="nsobject">NSObject</h2>
<p><code class="language-plaintext highlighter-rouge">NSObject</code> serves as the primary root class in <a href="//mulle-objc.github.io">mulle-objc</a>, implementing a
sophisticated object model that forms the bedrock of the entire framework. It
defines a universal interface for how objects interact with the runtime system
and with each other, encompassing crucial aspects such as message passing,
memory management, and type information handling.</p>
<p>Virtually every class you’ll work with in <a href="//mulle-objc.github.io">mulle-objc</a>
will be a subclass of <code class="language-plaintext highlighter-rouge">NSObject</code>. In fact, only a handful of highly specialized
classes deviate from this norm, to the extent that you can safely assume any
object you’re dealing with in your day to day code is an NSObject descendant.</p>
<h2 id="nsobject-in-more-detail">NSObject in more detail</h2>
<p>Let’s break down the core mechanisms that <code class="language-plaintext highlighter-rouge">NSObject</code> provides:</p>
<p>Here’s a markdown table of <code class="language-plaintext highlighter-rouge">NSObject</code> facilities, organized by topic:</p>
<table>
<thead>
<tr>
<th>Topic</th>
<th>Facilities</th>
</tr>
</thead>
<tbody>
<tr>
<td>Memory Management</td>
<td>- Manual reference counting methods (retain, release, autorelease)<br />- Deallocation method (dealloc)</td>
</tr>
<tr>
<td>Runtime Interaction</td>
<td>- Class introspection (e.g., isKindOfClass:, isMemberOfClass:)<br />- Method invocation and forwarding<br />- Selector handling (e.g., respondsToSelector:)</td>
</tr>
<tr>
<td>Object Comparison and Equality</td>
<td>- Equality checking (isEqual: method)<br />- Hashing support (hash method)</td>
</tr>
<tr>
<td>Serialization and Copying</td>
<td>- Support for object copying (copy and mutableCopy methods)<br />- Encoding and decoding for object serialization</td>
</tr>
<tr>
<td>Threading and Concurrency</td>
<td>- Thread-safety mechanisms<br />- Main thread execution methods (e.g., performSelectorOnMainThread:)</td>
</tr>
</tbody>
</table>
<p><code class="language-plaintext highlighter-rouge">NSObject</code> has a minimal memory footprint, it contains no instance variables.
Each instance is prefixed by an object header, that carries only the essential
overhead: an <a href="alloc.html#extrabytes-and-metaextrabytes">isa</a> pointer that ties
the instance to its class, the <a href="retaincount">retainCount</a> and sometimes
additional meta data required by the runtime for debugging operations.</p>
<blockquote>
<p>NOTE: This guide was partly written by AI (specifically cody) and then
mostly rewritten by Nat! Therefore the writing style of this pamphlet
is all over the place 😩</p>
</blockquote>
<div class="pagebreak"></div>
<h1>NSObject: +alloc / -dealloc</h1>
<p>Lets start with the absolute basics of creating and disposing of
objects. We are talking about objects that are either of the class
<code class="language-plaintext highlighter-rouge">NSObject</code> or any of its subclasses.</p>
<p>e.g.</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@interface</span> <span class="nc">Document</span> <span class="p">:</span> <span class="nc">NSObject</span>
<span class="k">@end</span>
</code></pre></div></div>
<h2 id="creation-and-destruction">Creation and destruction</h2>
<p>These are the most basic methods provided by <code class="language-plaintext highlighter-rouge">NSObject</code>. A user of a
<code class="language-plaintext highlighter-rouge">NSObject</code> derived class, would not actually need to call any of these methods
directly, as they are too low level. But we are building from the ground up:</p>
<table>
<thead>
<tr>
<th>Method</th>
<th>Override</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">+alloc</code></td>
<td>NO</td>
<td>Creates an object</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">-init</code></td>
<td>MAYBE</td>
<td>Initializes the object</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">-finalize</code></td>
<td>MAYBE</td>
<td>Release resources and owned objects</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">-dealloc</code></td>
<td>MAYBE</td>
<td>Deallocates the object</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">+new</code></td>
<td>NO</td>
<td>Convenience combining alloc with init</td>
</tr>
</tbody>
</table>
<p><br />
Let’s declare a class <code class="language-plaintext highlighter-rouge">Document</code> based on <code class="language-plaintext highlighter-rouge">NSObject</code> and write the most simple
demo:</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#import <MulleObjC/MulleObjC.h>
</span>
<span class="k">@interface</span> <span class="nc">Document</span> <span class="p">:</span> <span class="nc">NSObject</span>
<span class="k">@end</span>
<span class="k">@implementation</span> <span class="nc">Document</span>
<span class="k">@end</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span> <span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Document</span> <span class="o">*</span><span class="n">document</span><span class="p">;</span>
<span class="n">document</span> <span class="o">=</span> <span class="p">[</span><span class="n">Document</span> <span class="nf">alloc</span><span class="p">];</span>
<span class="n">document</span> <span class="o">=</span> <span class="p">[</span><span class="n">document</span> <span class="nf">init</span><span class="p">];</span>
<span class="c1">// calling -finalize manually, just for demo purposes</span>
<span class="p">[</span><span class="n">document</span> <span class="nf">finalize</span><span class="p">];</span>
<span class="c1">// calling -dealloc manually, just for demo purposes</span>
<span class="p">[</span><span class="n">document</span> <span class="nf">dealloc</span><span class="p">];</span>
<span class="c1">// DO NOT MESSAGE document ANYMORE!</span>
<span class="k">return</span><span class="p">(</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>An instance of Document is created with the class method <code class="language-plaintext highlighter-rouge">+alloc</code>.
<code class="language-plaintext highlighter-rouge">+alloc</code> will unfailingly return an object pointer to an instance, whose
content has been zeroed out. You can rely on both facts. If the system runs
out of memory, <code class="language-plaintext highlighter-rouge">+alloc</code> will throw an exception.</p>
<p><img src="images/document-alloc.svg" alt="Alloc" height="200" /></p>
<p>The next step is the initialization of the instance with <code class="language-plaintext highlighter-rouge">-init</code>. <code class="language-plaintext highlighter-rouge">-init</code> is
free to return <code class="language-plaintext highlighter-rouge">nil</code> though. It’s an indicator that initialization was not
possible. If this can be the case should be noted in the documentation of
a class header file.</p>
<p>The default <code class="language-plaintext highlighter-rouge">-init</code> method does nothing but return <code class="language-plaintext highlighter-rouge">self</code>:</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">-</span> <span class="p">(</span><span class="n">instancetype</span><span class="p">)</span> <span class="n">init</span>
<span class="p">{</span>
<span class="k">return</span><span class="p">(</span> <span class="n">self</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>For illustrative purposes, the code does now, what you <em>never</em> should do,
that is, it calls <code class="language-plaintext highlighter-rouge">-finalize</code> and <code class="language-plaintext highlighter-rouge">-dealloc</code> manually.</p>
<p>With <code class="language-plaintext highlighter-rouge">-finalize</code> you can lop off any references to any other objects that are
kept in properties (more on this later):</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">finalize</span>
<span class="p">{</span>
<span class="n">_MulleObjCInstanceClearProperties</span><span class="p">(</span> <span class="n">self</span><span class="p">,</span> <span class="nb">NO</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<blockquote>
<p><strong>LAW</strong> A NSObject based instance has the guarantee, that it will get an
initializing call before autorelease. That being <code class="language-plaintext highlighter-rouge">-init</code> or a <a href="init.html">variant</a>
of init. It is guaranteed that its <code class="language-plaintext highlighter-rouge">-finalize</code> method will be called once and
only once before the object receives a <code class="language-plaintext highlighter-rouge">-dealloc</code>.</p>
<p>The <code class="language-plaintext highlighter-rouge">-finalize</code> can happen at any time after <code class="language-plaintext highlighter-rouge">-init</code> though.</p>
</blockquote>
<p>Finally <code class="language-plaintext highlighter-rouge">-dealloc</code> is called to free the instances memory.</p>
<blockquote>
<p><strong>LAW</strong>: Once an instance has gone through <code class="language-plaintext highlighter-rouge">dealloc</code>, it must not be messaged
again.</p>
<p>Doing so is called messaging a zombie and it can crash your program.
It will definitely crash, when you set the <code class="language-plaintext highlighter-rouge">NSZombieEnabled</code> environment
variable to <code class="language-plaintext highlighter-rouge">YES</code>, which is recommended during development.</p>
</blockquote>
<h2 id="new">+new</h2>
<p>The <code class="language-plaintext highlighter-rouge">+new</code> method is essentially a combination of <code class="language-plaintext highlighter-rouge">+alloc</code> and <code class="language-plaintext highlighter-rouge">-init</code>, which
simplifies the creation of instances a bit. In general you will not use it very
often either, when we introduce <code class="language-plaintext highlighter-rouge">+object</code> in one of the next chapters.</p>
<h2 id="lifetime">Lifetime</h2>
<p>The time between the call to <code class="language-plaintext highlighter-rouge">+alloc</code> and the final <code class="language-plaintext highlighter-rouge">-dealloc</code> of an object is
called the object’s <strong>lifetime</strong>. We will use this concept later on quite a bit.</p>
<div class="pagebreak"></div>
<h1>NSObject: -retain / -release</h1>
<p>Let’s dive into the fascinating world of memory management in <a href="//mulle-objc.github.io">mulle-objc</a>, a
system that sets itself apart with its unique approach to object lifecycle
management. As you’ll soon discover, mulle-objc employs a highly efficient
Manual Memory Management (MMR) system, eschewing Automatic Reference Counting (
ARC) in favor of a more predictable and controllable approach.</p>
<p>Have you ever wondered how objects in a programming language know when they’re
no longer needed? In mulle-objc, this is handled through a sophisticated retain
counting mechanism. Unlike some contemporary systems that abstract away memory
management, mulle-objc gives you, the developer, direct control over an object’s
lifecycle.</p>
<p>At the heart of mulle-objc’s memory management are six core operations. It is
important to know these operations, but in a well designed system, you will
rarely use them directly. And there are only two methods you will encounter
overriding with your own implementations:</p>
<table>
<thead>
<tr>
<th>Operation</th>
<th>Override</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">+alloc</code> / <code class="language-plaintext highlighter-rouge">+new</code></td>
<td>NO</td>
<td>Creates an object with an initial reference count of 1</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">-retain</code></td>
<td>NO</td>
<td>Increments the reference count</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">-release</code></td>
<td>NO</td>
<td>Decrements the reference count</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">-retainCount</code></td>
<td>NO</td>
<td>Returns the current reference count</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">-finalize</code></td>
<td>YES</td>
<td>Called from -release when the reference count reaches zero. Can also be triggered by <code class="language-plaintext highlighter-rouge">-mullePerformFinalize</code>. Allows the object to free resources and untie itself from other objects. Runs only once in an object’s lifetime.</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">-dealloc</code></td>
<td>YES</td>
<td>Performs final cleanup when the reference count reaches zero</td>
</tr>
</tbody>
</table>
<p>Anyway, let’s break this down with an example:</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Document</span> <span class="o">*</span><span class="n">document</span><span class="p">;</span>
<span class="n">document</span> <span class="o">=</span> <span class="p">[</span><span class="n">Document</span> <span class="nf">new</span><span class="p">];</span> <span class="c1">// count = 1</span>
<span class="p">[</span><span class="n">document</span> <span class="nf">retain</span><span class="p">];</span> <span class="c1">// count = 2</span>
<span class="p">[</span><span class="n">document</span> <span class="nf">release</span><span class="p">];</span> <span class="c1">// count = 1</span>
<span class="p">[</span><span class="n">document</span> <span class="nf">release</span><span class="p">];</span> <span class="c1">// count = 0, triggers finalize and then dealloc</span>
<span class="c1">// DO NOT MESSAGE document AGAIN</span>
</code></pre></div></div>
<p>In this sequence, we create a <code class="language-plaintext highlighter-rouge">Document</code> object, increase its retain count, then
decrease it twice.</p>
<p>When <code class="language-plaintext highlighter-rouge">-retainCount</code> reaches zero, the <code class="language-plaintext highlighter-rouge">-release</code> method automatically
calls <code class="language-plaintext highlighter-rouge">-finalize</code> and then <code class="language-plaintext highlighter-rouge">-dealloc</code> in sequence, ultimately leading to the
objects destruction.</p>
<p><img src="images/object-lifetime-2.svg" alt="Lifetime" /></p>
<blockquote>
<p><strong>LAW</strong>: Once the number of <code class="language-plaintext highlighter-rouge">-release</code> calls to an object exceeds the
number of <code class="language-plaintext highlighter-rouge">-retain</code> calls, the object becomes deallocated and invalid.</p>
</blockquote>
<h2 id="when-to-call--retain-and--release">When to call -retain and -release</h2>
<p>When you create another object or receive one as a method or function argument,
you may want to keep it around with your object. Effectively you
are keeping a <em>reference</em> to it. Now when you do that, you increase the
reference count of that object with <code class="language-plaintext highlighter-rouge">-retain</code>. Conversely, when you are done
with it, you use <code class="language-plaintext highlighter-rouge">-release</code> to relinquish ownership.</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@class</span> <span class="nc">Person</span><span class="p">;</span>
<span class="k">@interface</span> <span class="nc">Document</span> <span class="p">:</span> <span class="nc">NSObject</span>
<span class="p">{</span>
<span class="n">Person</span> <span class="o">*</span><span class="n">_author</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@end</span>
<span class="k">@implementation</span> <span class="nc">Document</span>
<span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="nf">setAuthor</span><span class="p">:(</span><span class="n">Person</span> <span class="o">*</span><span class="p">)</span> <span class="n">person</span>
<span class="p">{</span>
<span class="c1">// THIS CODE IS JUST FOR ILLUSTRATION PURPOSES</span>
<span class="c1">// DO NOT WRITE ACCESSORS THAT CALL -release INSTEAD OF -autorelease</span>
<span class="k">if</span><span class="p">(</span> <span class="n">_author</span> <span class="o">!=</span> <span class="n">person</span><span class="p">)</span>
<span class="p">{</span>
<span class="p">[</span><span class="n">_author</span> <span class="nf">release</span><span class="p">];</span> <span class="c1">// remove old author</span>
<span class="n">_author</span> <span class="o">=</span> <span class="p">[</span><span class="n">person</span> <span class="nf">retain</span><span class="p">];</span> <span class="c1">// keep new author</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>In general though in mulle-objc you use a <a href="//mulle-kybernetik.com/de-re-property/">@property</a> to keep an object reference, which simplifies the proceedings.</p>
<h2 id="caveats">Caveats</h2>
<p>But what about the challenges of this system? While it offers great control, it
does require careful management from the developer. You must ensure that every
<code class="language-plaintext highlighter-rouge">-retain</code> is balanced by a <code class="language-plaintext highlighter-rouge">-release</code>, that <code class="language-plaintext highlighter-rouge">-dealloc</code> releases all retained
objects, and that you never access released objects.</p>
<p>These requirements can potentially lead to memory leaks or crashes, if not
handled correctly. The next chapter discusses how mulle-objc mitigates many of
these challenges through its autorelease pools.</p>
<div class="pagebreak"></div>
<h1>NSObject: -autorelease</h1>
<p>Welcome to the world of <a href="//mulle-objc.github.io">mulle-objc</a>’s memory management, where <strong>NSAutoreleasePool</strong> reigns supreme.</p>
<p>You learned about the retain counting and the lifetime of objects in a previous
chapter, and now comes the chapter that will try to sell you, that you don’t
need to worry about retain counting. As now, the <code class="language-plaintext highlighter-rouge">NSAutoreleasePool</code> makes its
appearance on the scene.</p>
<h2 id="the-nsautoreleasepool-class">The NSAutoreleasePool class</h2>
<p>Basically a <code class="language-plaintext highlighter-rouge">NSAutoreleasePool</code> just manages an array of pointers to objects.
You can add objects to the pool by using the <code class="language-plaintext highlighter-rouge">-autorelease</code> convenience
method on <code class="language-plaintext highlighter-rouge">NSObject</code>. This method locates the current pool for the running
thread and adds the object to the array.</p>
<p>The autorelease pool has one operational method <code class="language-plaintext highlighter-rouge">-drain</code>, which iterates
through this array, sending a <code class="language-plaintext highlighter-rouge">-release</code> message to each object. You usually
call <code class="language-plaintext highlighter-rouge">-drain</code> only indirectly, once a NSAutoreleasePool expires.</p>
<p>Creating an pool in your code is never necessary, but it can be
a useful optimization, when you create lots of short lived objects. But you
can if you want with the <code class="language-plaintext highlighter-rouge">@autoreleasepool</code> directive. More on this later.</p>
<h3 id="thread-specific-pool-stacks">Thread-Specific Pool Stacks</h3>
<p>Each thread in mulle-objc maintains its own stack of autorelease pools. This
design ensures thread safety without the need for expensive locking mechanisms.</p>
<p><img src="images/thread_2-pool_1-obj_0.svg" alt="Pools And Threads" height="300" /></p>
<p>As shown above, Thread #1 and Thread #2 each manage their own pools
independently, preventing any cross-thread interference.
Each thread under mulle-objc control, even the main thread creates an
autorelease pool when it starts up.</p>
<blockquote>
<p>RULE: An object can only be messaged by a thread, if the object resides
in the autoreleasepool stack of that thread.</p>
</blockquote>
<p>This ensures that autoreleased objects always have a pool to be added to, even
in the absence of explicit <code class="language-plaintext highlighter-rouge">@autoreleasepool</code> directives.</p>
<h2 id="nested-pool-management">Nested Pool Management</h2>
<table>
<tbody>
<tr>
<td><img src="images/thread_1-pool_2-obj_0.svg" alt="Single Nested Pool" width="250" /></td>
<td><img src="images/thread_1-pool_2-obj_1.svg" alt="One Object Added" width="250" /></td>
</tr>
<tr>
<td>Pools can be nested within each other, creating a hierarchical structure for fine-grained memory management</td>
<td>Objects are always added to the innermost pool in the current thread’s stack.</td>
</tr>
</tbody>
</table>
<p>The next code snippet and the accompanying drwawing visualize how nested
autorelease pools collect and dispose of objects during program execution.</p>
<blockquote>
<p>NOTE: The <code class="language-plaintext highlighter-rouge">+object</code> method creates an instance and then calls <code class="language-plaintext highlighter-rouge">-autorelease</code>
on it.</p>
</blockquote>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@autoreleasepool</span>
<span class="p">{</span> <span class="c1">// pool 1 starts</span>
<span class="n">Document</span> <span class="o">*</span><span class="n">a</span><span class="p">;</span>
<span class="n">Document</span> <span class="o">*</span><span class="n">b</span><span class="p">;</span>
<span class="n">Document</span> <span class="o">*</span><span class="n">c</span><span class="p">;</span>
<span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="n">Document</span> <span class="nf">object</span><span class="p">];</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">[</span><span class="n">Document</span> <span class="nf">object</span><span class="p">];</span> <span class="c1">// #1#</span>
<span class="k">@autoreleasepool</span>
<span class="p">{</span> <span class="c1">// pool 2 starts</span>
<span class="n">c</span> <span class="o">=</span> <span class="p">[</span><span class="n">Document</span> <span class="nf">object</span><span class="p">];</span> <span class="c1">// #2</span>
<span class="c1">// c added to pool 2</span>
<span class="p">}</span> <span class="c1">// pool 2 drains, c released // #3</span>
<span class="c1">// #4</span>
<span class="n">mulle_printf</span><span class="p">(</span> <span class="s">"a %@ and b %@ are still alive</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">a</span><span class="p">);</span>
<span class="c1">// this would crash likely</span>
<span class="c1">// mulle_printf( "c %@ is dead\n", c);</span>
<span class="p">}</span> <span class="c1">// pool 1 drains</span>
</code></pre></div></div>
<p>When an autorelease pool is drained, it releases all the objects it contains.
This happens automatically at the end of an @autoreleasepool scope.</p>
<table>
<tbody>
<tr>
<td><img src="images/nested-pools-2.svg" alt="1" width="120" /> <code class="language-plaintext highlighter-rouge">#1</code></td>
<td><img src="images/nested-pools-3.svg" alt="2" width="120" /> <code class="language-plaintext highlighter-rouge">#2</code></td>
<td><img src="images/nested-pools-4.svg" alt="3" width="120" /> <code class="language-plaintext highlighter-rouge">#3</code></td>
<td><img src="images/nested-pools-2.svg" alt="4" width="120" /> <code class="language-plaintext highlighter-rouge">#4</code></td>
</tr>
</tbody>
</table>
<h3 id="creating-autoreleased-and-zeroed-c-memory">Creating autoreleased and zeroed C memory</h3>
<p>An autoreleasepool can also facilitate C coding. You can use
<code class="language-plaintext highlighter-rouge">MulleObjCCallocAutoreleased</code> to create an autoreleased and zeroed
block of memory:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">p</span> <span class="o">=</span> <span class="n">MulleObjCCallocAutoreleased</span><span class="p">(</span> <span class="mi">1</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span> <span class="k">struct</span> <span class="n">whatever</span><span class="p">));</span>
</code></pre></div></div>
<p>This is like a <code class="language-plaintext highlighter-rouge">calloc</code> you don’t have to free. Remember though, you can’
retain an allocation like this.</p>
<h3 id="caveat">Caveat</h3>
<p>While mulle-objc’s autorelease system offers great convenience, it’s important
to be aware of potential pitfalls. For instance, creating and keeping
to many autoreleased objects and never getting to a pool drain will lead to
increased memory usage.</p>
<p>This can happen for example in long-running operations, like a database import
from JSON for example. The remedy is to use <code class="language-plaintext highlighter-rouge">@autoreleasepool</code> blocks or
to manually drain pools once in a while.</p>
<h3 id="discussion-on-nsautoreleasepool-vs-garbage-collection">Discussion on NSAutoreleasePool vs Garbage Collection</h3>
<p>NSAutoreleasePool offers several advantages over garbage collection,
particularly in terms of performance and predictability.</p>
<ul>
<li><strong>Deterministic Memory Management</strong>: With NSAutoreleasePool, developers have
control over when memory is released, allowing for more predictable memory
usage patterns. In contrast, garbage collection can introduce latency as it
runs in the background, potentially leading to unpredictable pauses in
application performance.</li>
<li><strong>Lower Overhead</strong>: NSAutoreleasePool has a lower runtime overhead compared to
garbage collection. It does not require the additional resources needed to
track object references and manage cycles, which can be particularly
beneficial in resource-constrained environments.</li>
<li><strong>Fine-Grained Control</strong>: Developers can create and drain autorelease pools at
specific points in their code, allowing for fine-tuned memory management
strategies. This is especially useful in applications with varying memory
demands, where developers can optimize memory usage based on the current
workload.</li>
<li><strong>Control over Resource</strong>: Developers can release resources (like file
handles) when they want with <code class="language-plaintext highlighter-rouge">-mullePerformFinalize</code>, compared to garbage
collection which is unpredictable.</li>
</ul>
<div class="pagebreak"></div>
<h1>AAO: Always autoreleased objects</h1>
<p>In mulle-objc the <em>expectation</em> is that all objects are created autoreleased.</p>
<blockquote>
<p>RULE: Objects are passed autoreleased to functions and methods and objects
are also returned autoreleased from functions and methods.</p>
</blockquote>
<p>When you <code class="language-plaintext highlighter-rouge">-autorelease</code> an object, typically during creation, you are tieing
the lifetime of your object to the lifetime of the current autorelease pool.
This is an <strong>explicitly</strong> autoreleased object, as the autorelease
pool contains a pointer to it.</p>
<p>Your object is now guaranteed to live at least as long as the autorelease pool.
It will live longer, if it is directly or indirectly part of another autorelease
pool.</p>
<p>In a method, you know the incoming objects are autoreleased. So you don’t
<code class="language-plaintext highlighter-rouge">-release</code> or <code class="language-plaintext highlighter-rouge">-autorelease</code> them. If you want to return a new object,
you return an autoreleased object only.</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@implementation</span> <span class="nc">Document</span>
<span class="k">+</span> <span class="p">(</span><span class="n">Document</span> <span class="o">*</span><span class="p">)</span> <span class="nf">improvedDocument</span><span class="p">:(</span><span class="n">Document</span> <span class="o">*</span><span class="p">)</span> <span class="n">document</span>
<span class="p">{</span>
<span class="n">Document</span> <span class="o">*</span><span class="n">improved</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span> <span class="p">[</span><span class="n">document</span> <span class="nf">isPerfect</span><span class="p">])</span>
<span class="k">return</span><span class="p">(</span> <span class="n">document</span><span class="p">);</span> <span class="c1">// incoming is autoreleased, outgoing therefore too</span>
<span class="n">improved</span> <span class="o">=</span> <span class="p">[</span><span class="n">Document</span> <span class="nf">object</span><span class="p">];</span>
<span class="c1">// do something smart ...</span>
<span class="p">[</span><span class="n">improved</span> <span class="nf">setPerfect</span><span class="p">:</span><span class="nb">YES</span><span class="p">];</span>
<span class="k">return</span><span class="p">(</span> <span class="n">document</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">...</span>
</code></pre></div></div>
<p>To keep an object alive longer, another objects needs to <code class="language-plaintext highlighter-rouge">-retain</code> it,
to obtain ownership. As the owning object is oblidged to <code class="language-plaintext highlighter-rouge">-autorelease</code> it
before the death of the owner, it will need to keep a reference to this object
for as long as it needs to hold unto it.</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@interface</span> <span class="nc">Person</span> <span class="p">:</span> <span class="nc">NSObject</span>
<span class="k">@end</span>
<span class="k">@interface</span> <span class="nc">Document</span> <span class="p">:</span> <span class="nc">NSObject</span>
<span class="p">{</span>
<span class="k">@public</span>
<span class="n">Person</span> <span class="o">*</span><span class="n">_author</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@end</span>
<span class="k">@implementation</span> <span class="nc">Document</span>
<span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="nf">setAuthor</span><span class="p">:(</span><span class="n">Person</span> <span class="o">*</span><span class="p">)</span> <span class="n">author</span>
<span class="p">{</span>
<span class="p">[</span><span class="n">_author</span> <span class="nf">autorelease</span><span class="p">];</span>
<span class="n">_author</span> <span class="o">=</span> <span class="p">[</span><span class="n">author</span> <span class="nf">retain</span><span class="p">];</span>
<span class="p">}</span>
<span class="k">@end</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span> <span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Document</span> <span class="o">*</span><span class="n">document</span><span class="p">;</span>
<span class="n">Person</span> <span class="o">*</span><span class="n">person</span><span class="p">;</span>
<span class="n">document</span> <span class="o">=</span> <span class="p">[</span><span class="n">document</span> <span class="nf">object</span><span class="p">];</span>
<span class="k">@autoreleasepool</span>
<span class="p">{</span>
<span class="n">person</span> <span class="o">=</span> <span class="p">[</span><span class="n">Person</span> <span class="nf">object</span><span class="p">];</span>
<span class="p">[</span><span class="n">document</span> <span class="nf">setPerson</span><span class="p">:</span><span class="n">person</span><span class="p">];</span>
<span class="c1">// #1</span>
<span class="p">}</span>
<span class="c1">// #2</span>
<span class="n">mulle_printf</span><span class="p">(</span> <span class="s">"%@</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">document</span><span class="o">-></span><span class="n">_author</span><span class="p">);</span>
<span class="p">[</span><span class="n">document</span> <span class="nf">setPerson</span><span class="p">:</span><span class="nb">nil</span><span class="p">];</span>
<span class="c1">// #3</span>
<span class="k">return</span><span class="p">(</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The drawings show the fate of the <em>person</em> object:</p>
<table>
<tbody>
<tr>
<td><img src="images/pool-object-ownership-3.svg" alt="1" width="120" /> <code class="language-plaintext highlighter-rouge">#1</code> <strong>explicit</strong></td>
<td><img src="images/pool-object-ownership-7.svg" alt="2" width="120" /> <code class="language-plaintext highlighter-rouge">#2</code> <strong>implicit</strong></td>
<td><img src="images/pool-object-ownership-8.svg" alt="6" width="120" /> <code class="language-plaintext highlighter-rouge">#3</code> <strong>explicit</strong></td>
</tr>
<tr>
<td><em>person</em> is created in an inferior pool and referenced by <em>document</em></td>
<td>The inferior pool is gone, <em>person</em> is still alive through a <code class="language-plaintext highlighter-rouge">-retain</code> by <em>document</em></td>
<td><em>document</em> relinquishes ownership with <code class="language-plaintext highlighter-rouge">-autorelease</code> of <em>person</em></td>
</tr>
</tbody>
</table>
<p>Your retained object is now an <strong>implicitly</strong> autoreleased object. When the
owner cuts the reference, it will <code class="language-plaintext highlighter-rouge">-autorelease</code> your object, therefore turning
it back into an <strong>expliticly</strong> autoreleased object.</p>
<p>These basic relationships form the foundation of mulle-objc’s object ownership
convention.</p>
<blockquote>
<p>RULE: The only times that <code class="language-plaintext highlighter-rouge">-release</code> calls are made on an object</p>
<ol>
<li>if it is not part of any autorelease pool either explicitly or implicitly</li>
<li>during the death of an autorelease pool (including <code class="language-plaintext highlighter-rouge">-dealloc</code>)</li>
<li>in the scope of a function or method, if each <code class="language-plaintext highlighter-rouge">release</code> undoes a preceeding <code class="language-plaintext highlighter-rouge">-retain</code> in the same function and the object is no longer accessed or returned after the last <code class="language-plaintext highlighter-rouge">release</code>.</li>
</ol>
</blockquote>
<h3 id="not-all-objects-are-autoreleased-in-mulle-objc">Not all objects are autoreleased in mulle-objc</h3>
<p>The <code class="language-plaintext highlighter-rouge">NSThread</code> objects typically do not reside in autorelease pools. Very short
lived objects may never enter an autorelease pool. Static <code class="language-plaintext highlighter-rouge">NSString</code> objects
are never placed in an autorelease pool. Doing a <code class="language-plaintext highlighter-rouge">-autorelease</code> on a class or a
<a href="//www.mulle-kybernetik.com/weblog/2016/mulle_objc_boon_or_bane.html">TPS object</a>
does nothing and there can be more special cases.</p>
<p>Nevertheless as long as these objects are “static” or permanent, they count
as “implicitly” autoreleased, belonging to a virtual universe autoreleasepool.
If at any time they would lose their permanence, they would need to be placed
into a true autorelease pool.</p>
<blockquote>
<p>This was probably the most important chapter of this guide. Always autoreleased
objects are the philosophical foundation of <a href="//mulle-objc.github.io">mulle-objc</a>.</p>
</blockquote>
<div class="pagebreak"></div>
<h1>NSObject: -init</h1>
<p>Coming back to object initialization. In Objective-C, the <code class="language-plaintext highlighter-rouge">-init</code> method is
crucial for initializing an object after
it has been allocated. It is important to write an <code class="language-plaintext highlighter-rouge">init</code> routine properly to
ensure that the object is in a valid state before it is used.</p>
<p>For example:</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">-</span> <span class="p">(</span><span class="n">instancetype</span><span class="p">)</span> <span class="n">init</span>
<span class="p">{</span>
<span class="n">id</span> <span class="n">object</span><span class="p">;</span>
<span class="n">self</span> <span class="o">=</span> <span class="p">[</span><span class="n">super</span> <span class="nf">init</span><span class="p">];</span>
<span class="k">if</span><span class="p">(</span> <span class="n">self</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">_counter</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span><span class="p">(</span> <span class="n">self</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="multiple-initializers">Multiple initializers</h2>
<p>It is not uncommon to have multiple <code class="language-plaintext highlighter-rouge">init</code> methods with varying
arguments. All these initializers should funnel into a designated initializer to
ensure that there is one place to override in subclasses. This approach promotes
code reuse and maintains a clear initialization flow. By following this pattern,
you can ensure that all properties are set correctly and that your
initialization logic remains consistent across different initializers.</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">+</span> <span class="p">(</span><span class="n">instancetype</span><span class="p">)</span> <span class="nf">objectWithValue</span><span class="p">:(</span><span class="n">NSInteger</span><span class="p">)</span> <span class="n">value</span>
<span class="p">{</span>
<span class="n">id</span> <span class="n">obj</span><span class="p">;</span>
<span class="n">obj</span> <span class="o">=</span> <span class="p">[</span><span class="n">self</span> <span class="nf">alloc</span><span class="p">];</span>
<span class="n">obj</span> <span class="o">=</span> <span class="p">[</span><span class="n">obj</span> <span class="nf">init</span><span class="p">];</span>
<span class="n">obj</span> <span class="o">=</span> <span class="p">[</span><span class="n">obj</span> <span class="nf">autorelease</span><span class="p">];</span>
<span class="k">return</span><span class="p">(</span> <span class="n">obj</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">-</span> <span class="p">(</span><span class="n">instancetype</span><span class="p">)</span> <span class="nf">initWithValue</span><span class="p">:(</span><span class="n">NSInteger</span><span class="p">)</span> <span class="n">value</span>
<span class="p">{</span>
<span class="n">MyClass</span> <span class="o">*</span><span class="n">instance</span><span class="p">;</span>
<span class="n">instance</span> <span class="o">=</span> <span class="p">[</span><span class="n">super</span> <span class="nf">init</span><span class="p">];</span> <span class="c1">// call super not self</span>
<span class="k">if</span><span class="p">(</span> <span class="n">instance</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">_counter</span> <span class="o">=</span> <span class="n">value</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span><span class="p">(</span> <span class="n">instance</span> <span class="p">);</span>
<span class="p">}</span>
<span class="k">-</span> <span class="p">(</span><span class="n">instancetype</span><span class="p">)</span> <span class="n">init</span>
<span class="p">{</span>
<span class="k">return</span><span class="p">(</span> <span class="p">[</span><span class="n">self</span> <span class="nf">initWithValue</span><span class="p">:</span><span class="mi">0</span><span class="p">]);</span> <span class="c1">// call self not super!</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Here <code class="language-plaintext highlighter-rouge">-initWithValue:</code> is the designated initializer. You would document this in
the header file of your class.</p>
<h2 id="important--init-conventions">Important -init conventions</h2>
<p>Here are some rules to follow when writing <code class="language-plaintext highlighter-rouge">init</code> methods:</p>
<ol>
<li>If you cannot initialize the object, do a <code class="language-plaintext highlighter-rouge">[self release]</code> and then return
<code class="language-plaintext highlighter-rouge">nil</code>.</li>
<li>Do not throw exceptions in your <code class="language-plaintext highlighter-rouge">-init</code> method</li>
<li>Do not pass <code class="language-plaintext highlighter-rouge">self</code> to other objects during initialization.</li>
<li>Avoid using property setters for initialization of instance variables.</li>
<li>Always call <code class="language-plaintext highlighter-rouge">[super init]</code> (or any other initialize of the superclass) unless
your base class is <code class="language-plaintext highlighter-rouge">NSObject</code>, in which case you can skip it. You must call
<code class="language-plaintext highlighter-rouge">[super init] on </code>MulleDynamicObject<code class="language-plaintext highlighter-rouge"> and </code>MulleObject<code class="language-plaintext highlighter-rouge">. This exception is
only valid for </code>NSObject`.</li>
<li>For immutable objects, the -init method is really the only time, where you
cann set the instance variables.</li>
</ol>
<h2 id="important--dealloc-conventions">Important -dealloc conventions</h2>
<p>The setup code in <code class="language-plaintext highlighter-rouge">-init</code> is mirrored by the teardown code in<code class="language-plaintext highlighter-rouge">-dealloc</code>. The
rules for similar to <code class="language-plaintext highlighter-rouge">-init</code>:</p>
<ol>
<li>Use <code class="language-plaintext highlighter-rouge">-release</code> to release instance variables. Avoid <code class="language-plaintext highlighter-rouge">-autorelease</code>.</li>
<li>Do not throw exceptions</li>
<li>Avoid passing <code class="language-plaintext highlighter-rouge">self</code> to other objects</li>
<li>Avoid using property setters for release of instance variables.</li>
<li>Avoid locking of <code class="language-plaintext highlighter-rouge">self</code> during the scope of <code class="language-plaintext highlighter-rouge">-dealloc</code></li>
<li>Always call <code class="language-plaintext highlighter-rouge">[super dealloc]</code> last</li>
</ol>
<div class="pagebreak"></div>
<h1>NSObject: +object</h1>
<p>In the world of <a href="//mulle-objc.github.io">mulle-objc</a>, creating object instances is a fundamental
operation. The user of a class should not be burdened with the details of
how to create an instance and the memory management with <a href="autorelease.html">autorelease pools</a>.</p>
<p>That’s why factory methods are an important part of a well written
mulle-objc class. It is bad class design to not provide a factory method for
all published init methods.</p>
<h2 id="the-power-of-factory-methods">The Power of Factory Methods</h2>
<p>When it comes to creating objects in mulle-objc, factory methods reign supreme.</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">id</span> <span class="n">obj</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSObject</span> <span class="nf">object</span><span class="p">];</span>
</code></pre></div></div>
<p>This simple line of code creates an autoreleased object, initialized with
<code class="language-plaintext highlighter-rouge">init</code>.</p>
<h2 id="crafting-sophisticated-factory-methods">Crafting Sophisticated Factory Methods</h2>
<p>In mulle-objc, factory methods are designed with a two-part structure. This
design pattern enhances readability and maintainability. Let’s examine a more
complex example:</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// factory method</span>
<span class="k">+</span> <span class="p">(</span><span class="n">instancetype</span><span class="p">)</span> <span class="nf">personWithName</span><span class="p">:(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span> <span class="n">name</span>
<span class="n">age</span><span class="o">:</span><span class="p">(</span><span class="n">NSInteger</span><span class="p">)</span> <span class="n">age</span>
<span class="p">{</span>
<span class="k">return</span><span class="p">([[[</span><span class="n">self</span> <span class="nf">alloc</span><span class="p">]</span> <span class="nf">initWithName</span><span class="p">:</span><span class="n">name</span>
<span class="nl">age:</span><span class="n">age</span><span class="p">]</span> <span class="nf">autorelease</span><span class="p">]);</span>
<span class="p">}</span>
<span class="c1">// worker method</span>
<span class="k">-</span> <span class="p">(</span><span class="n">instancetype</span><span class="p">)</span> <span class="nf">initWithName</span><span class="p">:(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span> <span class="n">name</span>
<span class="n">age</span><span class="o">:</span><span class="p">(</span><span class="n">NSInteger</span><span class="p">)</span> <span class="n">age</span>
<span class="p">{</span>
<span class="n">self</span> <span class="o">=</span><span class="p">[</span><span class="n">self</span> <span class="nf">init</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">self</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">_name</span> <span class="o">=</span><span class="p">[</span><span class="n">name</span> <span class="nf">copy</span><span class="p">];</span>
<span class="n">_age</span> <span class="o">=</span> <span class="n">age</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span><span class="p">(</span> <span class="n">self</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="the-elegance-of-literals">The Elegance of Literals</h2>
<p>mulle-objc takes object creation a step further with literals, a powerful
compiler feature. Consider the following examples:</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">NSString</span> <span class="o">*</span><span class="n">s</span> <span class="o">=</span> <span class="s">@"literal"</span><span class="p">;</span>
<span class="n">NSString</span> <span class="o">*</span><span class="n">t</span> <span class="o">=</span> <span class="err">@</span><span class="p">(</span> <span class="n">a_char_pointer_variable</span><span class="p">);</span>
<span class="n">NSNumber</span> <span class="o">*</span><span class="n">n</span> <span class="o">=</span> <span class="mi">@42</span><span class="p">;</span>
<span class="n">NSNumber</span> <span class="o">*</span><span class="n">x</span> <span class="o">=</span> <span class="err">@</span><span class="p">(</span> <span class="n">some_numeric_variable</span><span class="p">);</span>
<span class="n">NSArray</span> <span class="o">*</span><span class="n">a</span> <span class="o">=</span> <span class="p">@[</span> <span class="mi">@1</span><span class="p">,</span> <span class="mi">@2</span><span class="p">,</span> <span class="mi">@3</span> <span class="p">];</span>
<span class="n">NSDictionary</span> <span class="o">*</span><span class="n">d</span> <span class="o">=</span> <span class="p">@{</span> <span class="s">@"key1"</span><span class="o">:</span> <span class="s">@"value1"</span><span class="p">,</span>
<span class="s">@"key2"</span><span class="o">:</span> <span class="s">@"value2"</span> <span class="p">};</span>
</code></pre></div></div>
<p>These literals provide a concise and readable way to create objects.</p>
<div class="pagebreak"></div>
<h1>NSObject: -finalize</h1>
<p>One of the most intriguing aspects of <a href="//mulle-objc.github.io">mulle-objc</a>’s memory management is the
<code class="language-plaintext highlighter-rouge">-finalize</code> method. This method serves a crucial role in resource management,
particularly for cleaning up external resources like file handles. It’s
guaranteed to run only once in an object’s lifetime, either through <code class="language-plaintext highlighter-rouge">-release</code>
or <code class="language-plaintext highlighter-rouge">-mullePerformFinalize</code>. Here’s how you might implement it:</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@implementation</span> <span class="nc">Person</span>
<span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">finalize</span>
<span class="p">{</span>
<span class="k">if</span><span class="p">(</span> <span class="n">_fileHandle</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">close</span><span class="p">(</span> <span class="n">_fileHandle</span><span class="p">);</span>
<span class="n">_fileHandle</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">[</span><span class="n">super</span> <span class="nf">finalize</span><span class="p">];</span> <span class="c1">// release properties</span>
<span class="p">}</span>
<span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">dealloc</span>
<span class="p">{</span>
<span class="p">[</span><span class="n">_address</span> <span class="nf">release</span><span class="p">];</span>
<span class="p">[</span><span class="n">super</span> <span class="nf">dealloc</span><span class="p">];</span> <span class="c1">// always call super last</span>
<span class="p">}</span>
<span class="k">@end</span>
</code></pre></div></div>
<p>Notice how <code class="language-plaintext highlighter-rouge">-finalize</code> handles resource cleanup, while <code class="language-plaintext highlighter-rouge">-dealloc</code> focuses on
releasing retained objects. This separation of concerns allows for more robust
and predictable cleanup processes.</p>
<h2 id="-mulleperformfinalize-runs--finalize-on-demand">-mullePerformFinalize runs -finalize on demand</h2>
<p>You can use <code class="language-plaintext highlighter-rouge">-mullePerformFinalize</code> to finalize an object “manually”:</p>
<p><img src="images/object-finalize.svg" alt="" /></p>
<p>The finalization can happen in the “middle of the lifetime” of the object.
And it is guaranteed that <code class="language-plaintext highlighter-rouge">-finalize</code> is only called once.</p>
<blockquote>
<p>LAW: Never call <code class="language-plaintext highlighter-rouge">-finalize</code> directly, always use <code class="language-plaintext highlighter-rouge">-mullePerformFinalize</code></p>
</blockquote>
<p>A finalized object is still useable in the object hierarchy,
but it is not active anymore. An example, where this is useful, is a window
controller, where the window close button has been clicked. It may still
redraw, but it doesn’t react to any event actions any more.</p>
<h2 id="-finalize-runs-automatically-before--dealloc">-finalize runs automatically before -dealloc</h2>
<p>When the <code class="language-plaintext highlighter-rouge">-retainCount</code> is decremented to zero via <code class="language-plaintext highlighter-rouge">-release</code>, an object gets
the <code class="language-plaintext highlighter-rouge">-finalize</code> message, unless <code class="language-plaintext highlighter-rouge">-mullePerformFinalize</code> has been called on it
already:</p>
<p><img src="images/object-lifetime.svg" alt="" /></p>
<p>If the <code class="language-plaintext highlighter-rouge">-retainCount</code> remains unchanged throughout <code class="language-plaintext highlighter-rouge">-finalize</code>, then <code class="language-plaintext highlighter-rouge">-dealloc</code>
is called afterwards.</p>
<p>During <code class="language-plaintext highlighter-rouge">-finalize</code> all <a href="//www.mulle-kybernetik.com/de-re-property/">@properties</a> will be cleared. So <code class="language-plaintext highlighter-rouge">-finalize</code> is used to free resources and cut links to other objects. Objects that are cleared by <code class="language-plaintext highlighter-rouge">-finalize</code> will be released with <code class="language-plaintext highlighter-rouge">-autorelease</code> and not with <code class="language-plaintext highlighter-rouge">-release</code>. <code class="language-plaintext highlighter-rouge">-dealloc</code> will ideally at most contain <code class="language-plaintext highlighter-rouge">-release</code> calls and <code class="language-plaintext highlighter-rouge">[super dealloc]</code>. Anything else can be done in <code class="language-plaintext highlighter-rouge">-finalize</code>.</p>
<h2 id="important--finalize-considerations">Important -finalize considerations</h2>
<p><code class="language-plaintext highlighter-rouge">-finalize</code> can happen at any time, so the rules differ from those of <code class="language-plaintext highlighter-rouge">-dealloc</code>
which is guaranteed to run only single-threaded with a retainCount of 1. In
contrast to <code class="language-plaintext highlighter-rouge">-dealloc</code>:</p>
<ol>
<li>Use <code class="language-plaintext highlighter-rouge">-autorelease</code> to release instance variables and <code class="language-plaintext highlighter-rouge">nil</code> them</li>
<li>You can use using property setters for the release of instance variables.</li>
<li>Call <code class="language-plaintext highlighter-rouge">[super finalize]</code> when convenient, or omit if you handle all properties
yourself</li>
</ol>
<h2 id="you-can-write--finalize-dealloc-portably">You can write -finalize/-dealloc portably</h2>
<p>If you use <code class="language-plaintext highlighter-rouge">-finalize</code>, you will be incompatible with non-ARC Apple. This can be
remedied, by structuring your <code class="language-plaintext highlighter-rouge">-finalize/-dealloc</code> code like this:</p>