[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-7938":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":16,"stars30d":16,"stars90d":15,"forks30d":15,"starsTrendScore":17,"compositeScore":18,"rankGlobal":9,"rankLanguage":9,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":9,"pushedAt":9,"updatedAt":24,"readmeContent":25,"aiSummary":26,"trendingCount":15,"starSnapshotCount":15,"syncStatus":27,"lastSyncTime":28,"discoverSource":29},7938,"objc-zen-book","objc-zen\u002Fobjc-zen-book","objc-zen","Zen and the Art of the Objective-C Craftsmanship",null,"Ruby",2646,348,136,7,0,1,3,62.23,"Other",false,"master",true,[],"2026-06-12 04:00:36","# Zen and the Art of the Objective-C Craftsmanship\n\n\n\n![](.\u002Fimages\u002Fzen-logo-thumb.png)\n\n\n\n\n* [Preface](#preface)\n  * [Swift](#swift)\n  * [For the Community](#for-the-community)\n  * [Authors](#authors)\n* [Conditionals](#conditionals)\n  * [Yoda conditions](#yoda-conditions)\n  * [nil and BOOL checks](#nil-and-bool-checks)\n  * [Golden Path](#golden-path)\n  * [Complex Conditions](#complex-conditions)\n  * [Ternary Operator](#ternary-operator)\n  * [Error handling](#error-handling)\n* [Case Statements](#case-statements)\n    * [Enumerated Types](#enumerated-types)\n* [Naming](#naming)\n  * [General conventions](#general-conventions)\n  * [Constants](#constants)\n  * [Methods](#methods)\n  * [Literals](#literals)\n* [Class](#class)\n  * [Class name](#class-name)\n  * [Initializer and dealloc](#initializer-and-dealloc)\n    * [Designated and Secondary Initializers](#designated-and-secondary-initializers)\n      * [Designated Initializer](#designated-initializer)\n      * [Secondary Initializer](#secondary-initializer)\n        * [References](#references)\n    * [instancetype](#instancetype)\n        * [Reference](#reference)\n    * [Initialization Patterns](#initialization-patterns)\n      * [Class cluster](#class-cluster)\n      * [Singleton](#singleton)\n  * [Properties](#properties)\n      * [Init and Dealloc](#init-and-dealloc)\n      * [Dot-Notation](#dot-notation)\n    * [Property Declaration](#property-declaration)\n      * [Private Properties](#private-properties)\n    * [Mutable Object](#mutable-object)\n    * [Lazy Loading](#lazy-loading)\n  * [Methods](#methods)\n    * [Parameter Assert](#parameter-assert)\n    * [Private methods](#private-methods)\n  * [Equality](#equality)\n* [Categories](#categories)\n* [Protocols](#protocols)\n* [NSNotification](#nsnotification)\n* [Beautifying the code](#beautifying-the-code)\n    * [Spacing](#spacing)\n    * [Line Breaks](#line-breaks)\n    * [Brackets](#brackets)\n* [Code Organization](#code-organization)\n  * [Exploit Code Block](#exploit-code-block)\n  * [Pragma](#pragma)\n    * [Pragma Mark](#pragma-mark)\n  * [Explicit warnings and errors](#explicit-warnings-and-errors)\n  * [Docstrings](#docstrings)\n  * [Comments](#comments)\n    * [Header Documentation](#header-documentation)\n* [Inter-Object Communication](#inter-object-communication)\n  * [Blocks](#blocks)\n    * [Under the Hood](#under-the-hood)\n    * [Retain cycles on self](#retain-cycles-on-self)\n  * [Delegate and DataSource](#delegate-and-datasource)\n    * [Inheritance](#inheritance)\n    * [Multiple Delegation](#multiple-delegation)\n* [Aspect Oriented Programming](#aspect-oriented-programming)\n* [References](#references)\n    * [Other Objective-C Style Guides](#other-objective-c-style-guides)\n\n\n\n\n# Preface\n\nWe started writing this book on November 2013. The initial goal was to provide guidelines to write the most clean Objective-C code possible: there are too many guidelines out there and all of them are debatable. We didn't aim introducing hard rules but, instead, a way for writing code to be more uniform as possible across different developers.\nWith time the scope moved to explain how to design and architecture good code.\n\nThe idea underneath is that the code should not only compile, instead it should \"validate\". Good code has several characteristics: should be concise, self-explanatory, well organized, well documented, well named, well designed and stand the test of time.\nThe main goals behind the curtain are that clarity always wins over performance and a rationale for a choice should always be provided.\nSome topics discussed here are general and independent from the language even if everything is tied up to Objective-C.\n\n## Swift\n\nOn June 6th, 2014 Apple announced the new programming language to be used for iOS and Mac development in future: Swift.\nThis new language is a radical departure from Objective-C and, of course, has caused a change in our plan for writing this book. It boiled down to the decision of releasing the current status of this essay without continuing our journey in unfolding the topics we originally planned to include.\nObjective-C is not going anywhere but at the same time continuing to write a book on a language that will not receive the same attention as it used to, is not a wise move.\n\n## For the Community\n\nWe have released this book for free and for the community because we hope to provide value to the reader, if each one of you can learn at least one best practice we have reached our goal.\n\nWe have done our best to polish this text and make it pleasant to the reader but we may have made typos, mistakes or left any part incomplete. We strongly encourage you to give us feedback and suggest improvements, so please get in touch with us if have any. We particularly appreciate pull requests.\n\n## Authors\n\n**Luca Bernardi**\n\n- http:\u002F\u002Flucabernardi.com\n- @luka_bernardi\n- http:\u002F\u002Fgithub.com\u002Flukabernardi\n\n**Alberto De Bortoli**\n\n- http:\u002F\u002Falbertodebortoli.com\n- @albertodebo\n- http:\u002F\u002Fgithub.com\u002Falbertodebortoli\n\n\n# Conditionals\n\nConditional bodies should always use braces even when a conditional body could be written without braces (e.g., it is one line only) to prevent errors. These errors include adding a second line and expecting it to be part of the if-statement. Another, even more dangerous defect, may happen where the line \"inside\" the if-statement is commented out, and the next line unwittingly becomes part of the if-statement.\n\n**Preferred:**\n\n```objective-c\nif (!error) {\n    return success;\n}\n```\n\n**Not preferred:**\n\n```objective-c\nif (!error)\n    return success;\n```\n\nor\n\n```objective-c\nif (!error) return success;\n```\n\nIn February 2014 the well-know [goto fail](https:\u002F\u002Fgotofail.com\u002F) was found in the Apple's SSL\u002FTLS implementation. \nThe bug was due to a repeated `goto` statement after an `if` condition, wrapping the `if` branch in parentheses would have prevented the issue.\n\nThe code extract:\n\n```objective-c\nstatic OSStatus\nSSLVerifySignedServerKeyExchange(SSLContext *ctx, bool isRsa, SSLBuffer signedParams,\n                                 uint8_t *signature, UInt16 signatureLen)\n{\n  OSStatus        err;\n  ...\n\n  if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0)\n    goto fail;\n  if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)\n    goto fail;\n    goto fail;\n  if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)\n    goto fail;\n  ...\n\nfail:\n  SSLFreeBuffer(&signedHashes);\n  SSLFreeBuffer(&hashCtx);\n  return err;\n}\n```\n\nEasy to spot, there are 2 `goto fail;` lines one after the other without parentheses. We definitely don't want to risk creating bugs like the one above right?\n\nIn addition, this style is more consistent with all other conditionals, and therefore more easily scannable.\n\n\n## Yoda conditions\n\nAlways avoid Yoda conditions. A Yoda condition is when comparing a constant to a variable instead of the other way around. It's like saying \"if blue is the sky\" or \"if tall is the man\" instead of \"if the sky is blue\" or \"if the man is tall\".\n\n![Yoda](.\u002Fimages\u002Fyoda.png)\n\n**Preferred:**\n```objective-c\nif ([myValue isEqual:@42]) { ...\n```\n\n**Not preferred:**\n```objective-c\nif ([@42 isEqual:myValue]) { ...\n```\n\n## nil and BOOL checks\n\nOn a similar note of the Yoda conditions, also the nil check has been at the centre of debates. Some notous libraries out there use to check for an object to be or not to be nil as so:\n\n```objective-c\nif (nil == myValue) { ...\n```\n\nOne could argue that this is amiss or similar to a Yoda condition as nil is kind of a constant. The reason why sometimes programmers use this approach to prevent error that are difficult to debug. Consider the following code:\n\n```objective-c\nif (myValue == nil) { ...\n```\n\nIf a typo occurs and the programmer actually types:\n\n```objective-c\nif (myValue = nil) { ...\n```\n\nit would be a valid assignment, indeed hard to debug if you are an experienced programmer (and therefore probably with some kind of visual impairment). That could never occur putting `nil` as argument on the left as it is nor assignable. There is also to be said that if the programmer uses this approach, he or she is perfectly aware of the underlying motivation and therefore the whole thing decades as it would be better to just double check what just typed.\n\nMore on this, to avoid all this fuss the approach that leave no space to doubt is to use the exclamation mark. Since `nil` resolves to `NO` it is unnecessary to compare it in conditions. Also, never compare something directly to `YES`, because `YES` is defined to 1 and a `BOOL` can be up to 8 bits as it is a char underneath.\n\n**Preferred:**\n```objective-c\nif (someObject) { ...\nif (![someObject boolValue]) { ...\nif (!someObject) { ...\n```\n\n**Not Preferred:**\n```objective-c\nif (someObject == YES) { ... \u002F\u002F Wrong\nif (myRawValue == YES) { ... \u002F\u002F Never do this.\nif ([someObject boolValue] == NO) { ...\n```\n\nThis allows also for more consistency across files and greater visual clarity.\n\n## Golden Path\n\nWhen coding with conditionals, the left hand margin of the code should be the \"golden\" or \"happy\" path.  That is, don't nest `if` statements.  Multiple return statements are OK. This will avoid the growth of cyclomatic complexity and make the code easier to read because the important part of your method is not nested inside a branch but you have a visual clue of what is the most relevant code. \n\n**Preferred:**\n\n```objective-c\n- (void)someMethod {\n  if (![someOther boolValue]) {\n      return;\n  }\n\n  \u002F\u002FDo something important\n}\n```\n\n**Not preferred:**\n\n```objective-c\n- (void)someMethod {\n  if ([someOther boolValue]) {\n    \u002F\u002FDo something important\n  }\n}\n```\n## Complex Conditions\n\nWhen you have complex condition in the `if` clause you should always extract them and assign to a `BOOL` variable to make more clear the logic and the meaning of every single conditions.\n\n```objective-c\nBOOL nameContainsSwift  = [sessionName containsString:@\"Swift\"];\nBOOL isCurrentYear      = [sessionDateCompontents year] == 2014;\nBOOL isSwiftSession     = nameContainsSwift && isCurrentYear;\n\nif (isSwiftSession) {\n    \u002F\u002F Do something very cool\n}\n```\n\n## Ternary Operator\n\nThe Ternary operator, `?` , should only be used when it increases clarity or code neatness. A single condition is usually all that should be evaluated. Evaluating multiple conditions is usually more understandable as an if statement, or refactored into instance variables.\n\n**Preferred:**\n```objective-c\nresult = a > b ? x : y;\n```\n\n**Not preferred:**\n```objective-c\nresult = a > b ? x = c > d ? c : d : y;\n```\n\nWhen the second argument of the ternary operator (the if branch) returns the same object that was checked for existence in the condition, the following syntax is neat:\n\n**Preferred:**\n```objective-c\nresult = object ? : [self createObject];\n```\n\n**Not preferred:**\n```objective-c\nresult = object ? object : [self createObject];\n```\n\n## Error handling\n\nWhen methods return an error parameter by reference, check the returned value, not the error variable.\n\n**Preferred:**\n```objective-c\nNSError *error = nil;\nif (![self trySomethingWithError:&error]) {\n    \u002F\u002F Handle Error\n}\n```\n\nMoreover, some of Apple's APIs write garbage values to the error parameter (if non-NULL) in successful cases, so checking the error can cause false negatives (and subsequently crash).\n\n\n# Case Statements\n\nBraces are not required for case statements, unless enforced by the complier.  \nWhen a case contains more than one line, braces should be added.\n\n```objective-c\nswitch (condition) {\n    case 1:\n        \u002F\u002F ...\n        break;\n    case 2: {\n        \u002F\u002F ...\n        \u002F\u002F Multi-line example using braces\n        break;\n       }\n    case 3:\n        \u002F\u002F ...\n        break;\n    default: \n        \u002F\u002F ...\n        break;\n}\n```\n\nThere are times when the same code can be used for multiple cases, and a fall-through should be used.  A fall-through is the removal of the 'break' statement for a case thus allowing the flow of execution to pass to the next case value.\n\n```objective-c\nswitch (condition) {\n    case 1:\n    case 2:\n        \u002F\u002F code executed for values 1 and 2\n        break;\n    default: \n        \u002F\u002F ...\n        break;\n}\n```\n\nWhen using an enumerated type for a switch, `default` is not needed. For example:\n\n```objective-c\nswitch (menuType) {\n    case ZOCEnumNone:\n        \u002F\u002F ...\n        break;\n    case ZOCEnumValue1:\n        \u002F\u002F ...\n        break;\n    case ZOCEnumValue2:\n        \u002F\u002F ...\n        break;\n}\n```\n\nMoreover, avoiding the default case, if new values are added to the enum, the programmer is immediately notified with a warning:\n\n`Enumeration value 'ZOCEnumValue3' not handled in switch.`\n\n### Enumerated Types\n\nWhen using `enum`s, it is recommended to use the new fixed underlying type specification because it has stronger type checking and code completion. The SDK now includes a macro to facilitate and encourage use of fixed underlying types — `NS_ENUM()`\n\n**Example:**\n\n```objective-c\ntypedef NS_ENUM(NSUInteger, ZOCMachineState) {\n    ZOCMachineStateNone,\n    ZOCMachineStateIdle,\n    ZOCMachineStateRunning,\n    ZOCMachineStatePaused\n};\n```\n\n# Naming\n\n## General conventions\n\nApple naming conventions should be adhered to wherever possible, especially those related to [memory management rules](https:\u002F\u002Fdeveloper.apple.com\u002Flibrary\u002Fmac\u002F#documentation\u002FCocoa\u002FConceptual\u002FMemoryMgmt\u002FArticles\u002FMemoryMgmt.html) ([NARC](http:\u002F\u002Fstackoverflow.com\u002Fa\u002F2865194\u002F340508)).\n\nLong, descriptive method and variable names are good.\n\n**Preferred:**\n\n```objective-c\nUIButton *settingsButton;\n```\n\n**Not Preferred:**\n```objective-c\nUIButton *setBut;\n```\n\n## Constants\n\nConstants should be camel-case with all words capitalized and prefixed by the related class name for clarity.\n\n**Preferred:**\n```objective-c\nstatic const NSTimeInterval ZOCSignInViewControllerFadeOutAnimationDuration = 0.4;\n```\n\n**Not Preferred:**\n```objective-c\nstatic const NSTimeInterval fadeOutTime = 0.4;\n```\n\nConstants are preferred over in-line string literals or numbers, as they allow for easy reproduction of commonly used variables and can be quickly changed without the need for find and replace. Constants should be declared as `static` constants and not `#define`s unless explicitly being used as a macro.\n\n**Preferred:**\n```objective-c\nstatic NSString * const ZOCCacheControllerDidClearCacheNotification = @\"ZOCCacheControllerDidClearCacheNotification\";\nstatic const CGFloat ZOCImageThumbnailHeight = 50.0f;\n```\n\n**Not Preferred:**\n\n```objective-c\n#define CompanyName @\"Apple Inc.\"\n#define magicNumber 42\n```\n\nConstants exposed externally should use this pattern in the interface file:\n\n```objective-c\nextern NSString *const ZOCCacheControllerDidClearCacheNotification;\n```\nand the previously defined assignment should be in the implementation file.\n\nYou only need to add the namespace to a constant that is made public. Even though constants used within an implementation could follow a different pattern, there is no need not to be consistent with the rule.\n\n\n## Methods\n\nIn method signatures, there should be a space after the method type (`-`\u002F`+` symbol). There should be a space between the method segments (matching Apple's style).  Always include a keyword and be descriptive with the word before the argument which describes the argument.\n\nThe usage of the word \"and\" is reserved.  It should not be used for multiple parameters as illustrated in the `initWithWidth:height:` example below.\n\n**Preferred:**\n```objective-c\n- (void)setExampleText:(NSString *)text image:(UIImage *)image;\n- (void)sendAction:(SEL)aSelector to:(id)anObject forAllCells:(BOOL)flag;\n- (id)viewWithTag:(NSInteger)tag;\n- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;\n```\n\n**Not Preferred:**\n\n```objective-c\n- (void)setT:(NSString *)text i:(UIImage *)image;\n- (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag;\n- (id)taggedView:(NSInteger)tag;\n- (instancetype)initWithWidth:(CGFloat)width andHeight:(CGFloat)height;\n- (instancetype)initWith:(int)width and:(int)height;  \u002F\u002F Never do this.\n```\n\n## Literals\n\n`NSString`, `NSDictionary`, `NSArray`, and `NSNumber` literals should be used whenever creating immutable instances of those objects. Pay special care that `nil` values not be passed into `NSArray` and `NSDictionary` literals, as this will cause a crash.\n\n**For example:**\n\n```objective-c\nNSArray *names = @[@\"Brian\", @\"Matt\", @\"Chris\", @\"Alex\", @\"Steve\", @\"Paul\"];\nNSDictionary *productManagers = @{@\"iPhone\" : @\"Kate\", @\"iPad\" : @\"Kamal\", @\"Mobile Web\" : @\"Bill\"};\nNSNumber *shouldUseLiterals = @YES;\nNSNumber *buildingZIPCode = @10018;\n```\n\n**Not:**\n\n```objective-c\nNSArray *names = [NSArray arrayWithObjects:@\"Brian\", @\"Matt\", @\"Chris\", @\"Alex\", @\"Steve\", @\"Paul\", nil];\nNSDictionary *productManagers = [NSDictionary dictionaryWithObjectsAndKeys: @\"Kate\", @\"iPhone\", @\"Kamal\", @\"iPad\", @\"Bill\", @\"Mobile Web\", nil];\nNSNumber *shouldUseLiterals = [NSNumber numberWithBool:YES];\nNSNumber *buildingZIPCode = [NSNumber numberWithInteger:10018];\n```\n\nFor the mutable counterparts of these classes we recommend, instead, the use of the explicit classes such as `NSMutableArray`, `NSMutableString`, and so on. \n\nThe following **should be avoided**:\n\n```objective-c\nNSMutableArray *aMutableArray = [@[] mutableCopy];\n```\n\nThe problems with the previous notation are both of efficiency and readability. \nOn the efficiency side, an unnecessarily immutable object is created and immediately thrown away; this unlikely will slow down your app (unless the method here is called frequently) but there is really no reason to do this just to save some characters. \nRegarding the readability, we can see two problems here: the first is that when scanning through the code and seeing `@[]` your mind is immediately connected to and instance of `NSArray`, but in this case you need to stop and check more thoughtfully. Another aspect to take into account is that it would be very likely that someone with less experience will see your code and depending on his background he might not be very comfortable with the dichotomy between mutable and immutable objects. He or she could not be very familiar with the meaning of creating a mutable copy (obviously we are not suggesting that this knowledge is not necessary). Again, this is not something absolutely wrong but is more about code usability (that includes readability).\n\n# Class\n\n## Class name\n\nYou should always prefix your class with **three** capital-case letters (two letters are reserved for Apple classes), this looking-weird practice is done to mitigate the notable absence of namespaces in our favorite language.\nSome developers don't follow this practice for model objects (we observed this practice especially for Core Data objects), we advice to strictly follow this convention also in the case of Core Data objects because you might end up merging your Managed Object Model with other MOMs, maybe coming from third party library. \nAs you may already have noticed, in this book the class (but not only) prefix is `ZOC`.\n\nThere is another good practice that you might want to follow while choosing the name for your classes: when you're creating a subclass, you should put the specifying name part between the class prefix and the superclass name. This is better explained with an example: if you have a class named `ZOCNetworkClient`, example of subclass name will be `ZOCTwitterNetworkClient` (note \"Twitter\" between \"ZOC\" and \"NetworkClient\"); or, following the same rule, a `UIViewController` subclass would `ZOCTimelineViewController`.\n\n\n## Initializer and dealloc\n\nThe recommended way to organize the  code is to  have `dealloc` method placed at the top of the implementation (directly after the `@synthesize` and `@dynamic` statements) and the `init` should be placed directly below the `dealloc` methods of any class. In case of multiple initializer the designated initializer should be placed as first method, because is the one where most likely there is more logic, and the secondary initializers should follow.\nIn these days with ARC, it is less likely that you will need to implement the dealloc method, but still the rationale is that by having the dealloc very close to your init methods, you are visually emphasizing the pairing between the methods. Usually in the dealloc method you will undo things that you have done in the init methods.\n\n`init` methods should be structured like this:\n\n```objective-c\n- (instancetype)init\n{\n    self = [super init]; \u002F\u002F call the designated initializer\n    if (self) {\n        \u002F\u002F Custom initialization\n    }\n    return self;\n}\n```\n\nIt's interesting to understand why do we need to set the value of `self` with the return value of `[super init]` and what happens if we don't do that.\n\nLet's do a step back: we are so used to type expressions like `[[NSObject alloc] init]` that the difference between `alloc` and `init` fades away. A peculiarity of Objective-C  is the so called *two stage creation*. This means that the allocation and the initialization are two separate steps, and therefore two different methods need to be called: `alloc` and `init`.\n- `alloc` is responsible for the object allocation. This process involve the allocation of enough memory to hold the object from the application virtual memory, writing the `isa` pointer, initializes the retain count, and zeroing all the instance variables. \n- `init` is responsible for initializing the object, that means brings the object in an usable state. This typically means set the instance variable of an object to reasonable and useful initial values.\n\nThe `alloc` method will return a valid instance of an uninitialized object. Every message sent to this instance will be translated into an `objc_msgSend()` call where the parameter named `self` will be the pointer returned by `alloc`; in this way `self` is implicitly available in the scope of every methods. \nTo conclude the two step creation the first method sent to a newly allocated instance should, by convention, be an `init` method. Notably the `init` implementation of `NSObject` is not doing more than simply return `self`. \n\nThere is another important part of the contract with `init`: the method can (and should) signal to the caller that it wasn't able to successfully finish the initialization by returning `nil`; the initialization can fail for various reasons such as an input passed in the wrong format or the failure in successfully initialize a needed object.\nThis is lead us to understand why you should always call `self = [super init]`, if your superclass is stating that it wasn't able to successfully initialize itself, you must assume that you are in an inconsistent state and therefore do not proceed with your own initialization and return `nil` as well in your implementation. If you fail to do so you might end up dealing with an object that is not usable, that will not behave as expected and that might eventually lead to crash your app.\n\nThe ability to re-assign `self` can also be exploited by the `init` methods to return a different instance than the one they have been called on. Examples of this behavior are [Class cluster](#class-cluster) or some Cocoa classes that returns the same instance for identical (immutable) objects.\n\n### Designated and Secondary Initializers\n\nObjective-C have the concept of designated and secondary initializers. \nThe designated initializer is the initializer that takes the full complement of initialization parameters, the secondary initializers are one or more initializer methods that calls the designated initializer providing one or more default values for the initialization parameter.\n\n```objective-c\n@implementation ZOCEvent\n\n- (instancetype)initWithTitle:(NSString *)title\n                         date:(NSDate *)date\n                     location:(CLLocation *)location\n{\n    self = [super init];\n    if (self) {\n        _title    = title;\n        _date     = date;\n        _location = location;\n    }\n    return self;\n}\n\n- (instancetype)initWithTitle:(NSString *)title\n                         date:(NSDate *)date\n{\n    return [self initWithTitle:title date:date location:nil];\n}\n\n- (instancetype)initWithTitle:(NSString *)title\n{\n    return [self initWithTitle:title date:[NSDate date] location:nil];\n}\n\n@end\n```\n\nGiven the above example `initWithTitle:date:location:` is the designated initializer. The other two init methods are the secondary initializers because they are just calling the designated initializer of the class where they are implemented.\n\n#### Designated Initializer\n\nA class should always have one and only one designated initializer, all other init methods should call the designated one (even though there is an exception to this case).\nThis dichotomy does not dictate any requirement about which initializer should be called.\nIt should rather be valid to call any designated initializer in the class hierarchy, and it should be guaranteed that *all* the designated initializer in the class hierarchy are called starting from the furthest ancestor (typically `NSObject`) down to your class. \nPractically speaking this means that the first initialization code executed is the furthest ancestor, and then going down to the class hierarchy; giving to all the classes in the hierarchy the chance to do their specific part of initialization. This totally make sense: you want that everything you inherit from your superclass is in an usable state before doing your actual work.\nEven though it isn't explicitly stated, all the classes in Apple's frameworks are guaranteed to respect this contract and your classes should do the same to be sure to be a good citizen and behave correctly and as expected.\n\nThere are three different situations that may present when defining a new class:\n\n1. No need to override any initializers\n2. Overriding designated initializer\n3. Define a new designated initializer\n\nThe first case is the most trivial: you don't need to add any specific logic at the initialization of your class you simply rely on you parent designated initializer.\nWhen you want to provide additional initialization logic you can decide to override the designated initializer. You should only override your immediate superclass's designated initializer and be sure that your implementation calls the super of the method you're overriding.  \nA typical example is whether you create a `UIViewController` subclass overriding `initWithNibName:bundle:`:\n\n```objective-c\n@implementation ZOCViewController\n\n- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil\n{\n    \u002F\u002F call to the superclass designated initializer\n    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];\n    if (self) {\n        \u002F\u002F Custom initialization\n    }\n    return self;\n}\n\n@end\n```\n\nIn case of `UIViewController` subclass it would be an error to override `init` as, in the case that the caller will try to initialize your class by calling `initWithNib:bundle`, your implementation will not be called. This also contradicts the rule that states that it should be valid to call any designated initializer.\n\nIn case you want to provide your own designated initializer there are three steps that you need to follow in order to guarantee the correct behavior:\n\n1. Declare your designated initializer, being sure to call your immediate superclass's designated initializer.\n2. Override the immediate superclass's designated initializer calling your new designated initializer.\n3. Document the new designated initializer. \n\nLots of developers often miss the last two steps, this is not only a sign of little care, but in the case of the step two is clearly against the contract with the framework and can lead to very non-deterministic behaviors and bugs.\nLet's see an example of the correct way to implement this:\n\n```objective-c\n@implementation ZOCNewsViewController\n\n- (id)initWithNews:(ZOCNews *)news\n{\n    \u002F\u002F call to the immediate superclass's designated initializer\n    self = [super initWithNibName:nil bundle:nil];\n    if (self) {\n        _news = news;\n    }\n    return self;\n}\n\n\u002F\u002F Override the immediate superclass's designated initializer\n- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil\n{\n    \u002F\u002F call the new designated initializer\n    return [self initWithNews:nil];\n}\n\n@end\n```\n\nIn case you don't override `initWithNibName:bundle:` and the caller decides to initialize you class with this method (that would be a perfectly valid option) the method `initWithNews:` will never get called and this will bring to an incorrect initialization sequence where the specific initialization logic of your class is not executed.\n\nEven though it should be possible to infer what method is the designate initializer, it is always good to be clear and explicit (the future you or other developers that will work on your code will thank you). There are two strategies (non mutually exclusive) that you can decide to use: the first one you is to clearly state in the documentation which initializer is the designated one, but better yet you can be nice with your compiler and by using the compiler directive `__attribute__((objc_designated_initializer))` you can signal your intent.\nUsing that directive will also help the compiler helping you and in fact the compiler will issue a warning if in your new designate initializer you don't call your superclass's designated initializer.\nThere are, though, cases in which not calling the class designated initializer (and in turn providing the required parameters) and calling another designated initializer in the class hierarchy will bring the class in an useless state. Referring to the previous example, there is no point in instantiating a `ZOCNewsViewController` that should present a news, without the news itself. In this case you can enforce even more the need to call a very specific designated initializer by simply making all the other designated initializers not available. It is possible to do that by using another compiler directive `__attribute__((unavailable(\"Invoke the designated initializer\"))) `, decorating a method with this attribute will make the compiler issuing an error if you try to call this method.\n\nHere the header relative to the implementation of the previous example (note the use of macros to don't repeat the code and being less verbose).\n\n```objective-c\n\n@interface ZOCNewsViewController : UIViewController\n\n- (instancetype)initWithNews:(ZOCNews *)news ZOC_DESIGNATED_INITIALIZER;\n- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil ZOC_UNAVAILABLE_INSTEAD(initWithNews:);\n- (instancetype)init ZOC_UNAVAILABLE_INSTEAD(initWithNews:);\n\n@end\n\n```\n\nA corollary of what described above is that you should never call a secondary initializer from within the designated one (if the secondary initializer respects the contract, it will call the designated one). Doing so, the call is very likely to invoke one of the subclass's overridden init methods and it will result in infinite recursion.\n\nThere is however an exception to all the rules laid out before that is whether an object conforms to the `NSCoding` protocol and it is initialized through the method `initWithCoder:`.\nWe should distinguish between the case where the superclass is adopting `NSCoding` and when not. \nIn the former case, if you just call `[super initWithCoder:]` you will probably have some shared initialization code with the designated initializer. A good way to handle this is to extract this code in a private method (i.e.  `p_commonInit`).\nWhen your superclass does not adopt `NSCoding` the recommendation is to threat `initWithCoder:` as a secondary initializer and therefore call the `self` designated initializer. Note that this is against what suggested by Apple in the [Archives and Serializations Programming Guide](https:\u002F\u002Fdeveloper.apple.com\u002Flibrary\u002Fmac\u002Fdocumentation\u002Fcocoa\u002FConceptual\u002FArchiving\u002FArticles\u002Fcodingobjects.html#\u002F\u002Fapple_ref\u002Fdoc\u002Fuid\u002F20000948-BCIHBJDE) where is stated:\n\n> the object should first invoke its superclass's designated initializer to initialize inherited state\n\nfollowing this will actually lead to a non-deterministic behavior that will change if your class is or not a direct subclass of `NSObject`.\n\n#### Secondary Initializer\n\nAs stated in the previous paragraph, a secondary initializer is a sort of convenience method to provide default values \u002F behaviors to the designated initializer.\nThat said, it seems clear that you should not do any mandatory initialization in such method and you should never assume that this method will gets called. Again, the only methods that we are guaranteed to get called are the designated initializer.\nThis imply that in your secondary designated initializer you should always call another secondary initializer or your `self` designated initializer.  Sometimes, by mistake, one can type `super`; doing this will cause not to respect the aforementioned sequence of initialization (in this specific case by skipping the initialization of the current class).\n\n##### References\n\n- https:\u002F\u002Fdeveloper.apple.com\u002Flibrary\u002Fios\u002FDocumentation\u002FGeneral\u002FConceptual\u002FDevPedia-CocoaCore\u002FObjectCreation.html\n- https:\u002F\u002Fdeveloper.apple.com\u002Flibrary\u002Fios\u002Fdocumentation\u002FGeneral\u002FConceptual\u002FCocoaEncyclopedia\u002FInitialization\u002FInitialization.html\n- https:\u002F\u002Fdeveloper.apple.com\u002Flibrary\u002Fios\u002FDocumentation\u002FGeneral\u002FConceptual\u002FDevPedia-CocoaCore\u002FMultipleInitializers.html\n- https:\u002F\u002Fblog.twitter.com\u002F2014\u002Fhow-to-objective-c-initializer-patterns\n\n\n\n### instancetype\n\nOne often doesn't realize that Cocoa is full of conventions, and they can help the compiler being a little bit more smart. Whether the compiler encounters `alloc` or `init` methods, it will know that, even though the return type of both method is `id`, those methods will always return objects that are an instance of the receiving class's type. As a consequence, this allows the compiler to provide and enforce the type checking (i.e. check that the methods called on the returned instance are valid). This kind of Clang smartness is due to what is called [related result type](http:\u002F\u002Fclang.llvm.org\u002Fdocs\u002FLanguageExtensions.html#related-result-types), meaning that \n\n> messages sent to one of alloc and init methods will have the same static type as the instance of the receiver class\n\nTo have more information about the convention that allow to automatically identify the related result type please refer to the [appropriate section]((http:\u002F\u002Fclang.llvm.org\u002Fdocs\u002FLanguageExtensions.html#related-result-types)) in the Clang Language Extensions guide.\nA related result type can be explicitly stated using the `instancetype` keyword as return type and this can be very helpful in situation where a factory method or convenience constructor is used. This will hint the compiler with the correct type checking and, probably more important, will behave correctly also when subclassing.\n\n```objective-c\n@interface ZOCPerson\n+ (instancetype)personWithName:(NSString *)name;\n@end\n```\n\nEven though, according to the clang specification, `id` can be promoted to `instancetype` by the compiler. In the case of `alloc` or `init` we strongly encourage to use the return type `instancetype` for all class and instance methods that returns an instance of the class.\nThis is mostly to form the habit and to be consistent (and possibly having a more readable interface) in all your APIs. Once again, by making small adjustments to your code you can improve the readability: with a simple glance you will be able to distinguish which methods are returning an instance of your class. Sort of details you will appreciate in the long run.\n\n##### Reference\n- http:\u002F\u002Ftewha.net\u002F2013\u002F02\u002Fwhy-you-should-use-instancetype-instead-of-id\u002F\n- http:\u002F\u002Ftewha.net\u002F2013\u002F01\u002Fwhen-is-id-promoted-to-instancetype\u002F\n- http:\u002F\u002Fclang.llvm.org\u002Fdocs\u002FLanguageExtensions.html#related-result-types\n- http:\u002F\u002Fnshipster.com\u002Finstancetype\u002F\n\n\n\n### Initialization Patterns\n\n#### Class cluster\nClass cluster as described in the Apple's documentation is\n> an architecture that groups a number of private, concrete subclasses under a public, abstract superclass.\n\nIf this description sounds familiar probably your instinct is correct. Class cluster is the Apple lingo for the [Abstract Factory](http:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FAbstract_factory_pattern) design pattern.\nThe idea with class cluster is very simple: you typically have an abstract class that during the initialization process uses information, generally provided as parameters of the initializer method or available in the environment, to apply a logic and instantiate a concrete subclass. This \"public facing\" class should internally have a good knowledge of its subclass to be able to return the private subclass that best suited the task.\nThis pattern is very useful because it removes the complexity of this initialization logic from the caller that only knows about the interface to communicate with the object, without actually caring about the underlying  implementation.\nClass clusters are widely used in the Apple's frameworks; some of the most notably examples are `NSNumber` that can return an appropriate subclass depending of the type of number provided (Integer, Float, etc...) or `NSArray` that will return a concrete subclass with the best storage policy.\nThe beauty of this pattern is that the caller can be completely unaware of the concrete subclass; in fact it can be used when designing a library to be able to swap the underlaying returned class without leaking any implementation detail as long as is respectful of the contract established in the abstract class.\n\nIn our experience the use of a Class Cluster can be very helpful in removing a lot of conditional code.\nA typical example of this is when you have the same UIViewController subclass for both iPhone and iPad, but the behavior is slightly different depending on the the device.\nThe naïve implementation is to put some conditional code checking the device in the methods where the different logic is needed, even though initially the place where this conditional logic is applied may be quite few they naturally tend to grow producing an explosion of code paths.\nA better design can be achieved by creating an abstract and generic view controller that will contain all the shared logic and then two specializing subclass for every device. \nThe generic view controller will check the current device idiom and depending on that it will return the appropriate subclass.\n\n\n```objective-c\n@implementation ZOCKintsugiPhotoViewController\n\n- (id)initWithPhotos:(NSArray *)photos\n{\n    if ([self isMemberOfClass:ZOCKintsugiPhotoViewController.class]) {\n        self = nil;\n\n        if ([UIDevice isPad]) {\n            self = [[ZOCKintsugiPhotoViewController_iPad alloc] initWithPhotos:photos];\n        }\n        else {\n            self = [[ZOCKintsugiPhotoViewController_iPhone alloc] initWithPhotos:photos];\n        }\n        return self;\n    }\n    return [super initWithNibName:nil bundle:nil];\n}\n\n@end\n```\n\nThe previous code example show how to create a class cluster. First of all the `[self isMemberOfClass:ZOCKintsugiPhotoViewController.class]` is done to prevent the necessity to override the init method in the subclass in order to prevent an infinite recursion. \nWhen `[[ZOCKintsugiPhotoViewController alloc] initWithPhotos:photos]` will get called the previous check will be true, the `self = nil` is to remove every reference to the instance of `ZOCKintsugiPhotoViewController` that it will be deallocated , following there is the logic to choose which subclass should be initialized. \nLet's assume that we are running this code on an iPhone and that `ZOCKintsugiPhotoViewController_iPhone` is not overriding `initWithPhotos:`; in this case, when executing `self = [[ZOCKintsugiPhotoViewController_iPhone alloc] initWithPhotos:photos];` the `ZOCKintsugiPhotoViewController` will be called and here is when the first check comes handy, given that now is not exactly  `ZOCKintsugiPhotoViewController` the check will be false calling the `return [super initWithNibName:nil bundle:nil];` this will make continue the initialization following the correct initialization path highlighted in the previous session.\n\n#### Singleton\n\nGenerally avoid using them if possible, use dependency injection instead.\nNevertheless, unavoidable singleton objects should use a thread-safe pattern for creating their shared instance. As of GCD, it is possible to use the `dispatch_once()` function to\n\n```objective-c\n+ (instancetype)sharedInstance\n{\n   static id sharedInstance = nil;\n   static dispatch_once_t onceToken = 0;\n   dispatch_once(&onceToken, ^{\n      sharedInstance = [[self alloc] init];\n   });\n   return sharedInstance;\n}\n```\n\nThe use of dispatch_once(), which is synchronous, replaces the following, yet obsolete, idiom:\n\n```objective-c\n+ (instancetype)sharedInstance\n{\n    static id sharedInstance;\n    @synchronized(self) {\n        if (sharedInstance == nil) {\n            sharedInstance = [[MyClass alloc] init];\n        }\n    }\n    return sharedInstance;\n}\n```\n\nThe benefits of `dispatch_once()` over this are that it's faster, it's also semantically cleaner, because the entire idea of dispatch_once() is \"perform something once and only once\", which is precisely what we're doing. This approach will also prevent [possible and sometimes prolific crashes][singleton_cocoasamurai].\n\nClassic examples of acceptable singleton objects are the GPS and the accelerometer of a device. Even though Singleton objects can be subclassed, the cases where this comes useful are rare. The interface should put in evidence that the given class is intended to be used as a Singleton. Therefore, often a single public `sharedInstance` class method would suffice and no writable properties should be exposed.\n\nTrying to use a Singleton as a container for objects to share across the code or layer of your application is ugly and nasty, and should be interpreted as a design smell.\n\n[singleton_cocoasamurai]: http:\u002F\u002Fcocoasamurai.blogspot.com\u002F2011\u002F04\u002Fsingletons-your-doing-them-wrong.html\n\n## Properties\n\nProperties should be named as descriptively as possible, avoiding abbreviation, and camel-case with the leading word being lowercase. Luckily our tool of choice is able to autocomplete everything we type (well... almost everything. Yes, I'm looking at you Xcode's Derived Data) so there is no reason to save a couple of chars, and it's better to convey as much information as possible in your source code.\n\n**For example:**\n```objective-c\nNSString *text;\n```\n\n**Not:**\n```objective-c\nNSString* text;\nNSString * text;\n```\n(Note: this preference is different for constants. This is actually a matter of common sense and readability: C++ developers often prefer to separate the type from the name of the variable, and as the type in its pure form would be `NSString*` (for objects allocated on the heap, as in C++ it'd be possible to allocate objects on the stack) the format `NSString* text;` is used.)\n\nUse auto-synthesize for properties rather than manual `@synthesize` statements unless your properties are part of a protocol rather than a concrete class. If Xcode can automatically synthesize the variable, then let it do so; moreover it'd be a part of the code that is just redundant and that you have to maintain without a real benefit.\n\nYou should always use the setter and getter to access the property, except for the `init` and `dealloc` methods. Generally speaking, using the property gives you an increased visual clue that what you're accessing is outside you current scope and therefor is subject to side-effect.\n\nYou should always prefer the setter because:\n\n* Using the setter will respect the defined memory-management semantics (`strong`, `weak`, `copy` etc...). This was definitely more relevant before ARC but it's still relevant; think, for example, the `copy` semantic, every time you use the setter the passed value is copied without any additional operation;\n* KVO notifications (`willChangeValueForKey`, `didChangeValueForKey`) are fired automatically;\n* It is easier to debug: you can set a breakpoint on the property declaration and the breakpoint will fire every time the getter\u002Fsetter is called, or you can set a breakpoint inside a custom setter\u002Fgetter;\n* It allows to add extra logic when setting a value in a single place.\n\nYou should alway prefer the getter:\n\n* It is resilient to future change (e.g. the property is dynamically generated);\n* It allows subclassing;\n* It is easier to debug (i.e. Is possible to put a breakpoint in the getter and see who's accessing that specific getter);\n* It makes the intent clear and explicit: by accessing an ivar `_anIvar` you are actually accessing `self->_anIvar`. This can lead to problems, for instance, accessing the iVar inside a block (you're capturing and retaining self even if you don't explicitly see the keyword `self`);\n* It automatically fires KVO notifications;\n* The overhead introduced by the message sending is very low and in the most of the case is negligible. For more information on the performance penalty introduced by the property you may find an interesting performance rundown  [Should I Use a Property or an Instance Variable?](http:\u002F\u002Fblog.bignerdranch.com\u002F4005-should-i-use-a-property-or-an-instance-variable\u002F)\n\n#### Init and Dealloc\n\nThere is however an exception to what stated before: you must never use the setter (or the getter) in the `init` (and other initializer method), and instead you should always access directly the variable using the instance variable. This is to be defensive against subclassing: eventually a subclass can override the setter (or getter) and trying to call other methods, access properties or iVars that aren't in a consistent state or fully-initialized. Remember that an object is considered fully initialized and in a consistent state only after the init returns. The same applies for the `dealloc` method (during the `dealloc` method an object can be in a inconsistent state). This is also clearly stated many times over time:\n\n* [Advanced Memory Management Programming Guide](https:\u002F\u002Fdeveloper.apple.com\u002Flibrary\u002Fmac\u002Fdocumentation\u002FCocoa\u002FConceptual\u002FMemoryMgmt\u002FArticles\u002FmmPractical.html#\u002F\u002Fapple_ref\u002Fdoc\u002Fuid\u002FTP40004447-SW6) under the self-explanatory section \"Don't Use Accessor Methods in Initializer Methods and dealloc\";\n* [Migrating to Modern Objective-C](http:\u002F\u002Fadcdownload.apple.com\u002F\u002Fwwdc_2012\u002Fwwdc_2012_session_pdfs\u002Fsession_413__migrating_to_modern_objectivec.pdf) at WWDC 2012 at slide 27;\n* in a [pull request](https:\u002F\u002Fgithub.com\u002FNYTimes\u002Fobjective-c-style-guide\u002Fissues\u002F6) form Dave DeLong's. \n\nMoreover, using the setter in the init will not play nicely with `UIAppearence` proxy (please refer to [UIAppearance for Custom Views](http:\u002F\u002Fpetersteinberger.com\u002Fblog\u002F2013\u002Fuiappearance-for-custom-views\u002F) for additional informations).\n\n#### Dot-Notation\n\nWhen using the setter\u002Fgetter always prefer the dot notation.\nDot-notation should *always* be used for accessing and mutating properties.\n\n**For example:**\n```objective-c\nview.backgroundColor = [UIColor orangeColor];\n[UIApplication sharedApplication].delegate;\n```\n\n**Not:**\n```objective-c\n[view setBackgroundColor:[UIColor orangeColor]];\nUIApplication.sharedApplication.delegate;\n```\nUsing the dot notation will ensure a visual clue to help distinguish between a property or a typical method call.\n\n### Property Declaration\n\nThe preferred way to declare a property is the following format\n\n```objective-c\n@property (nonatomic, readwrite, copy) NSString *name;\n```\n\nThe property attributes should be ordered as following: atomicity, read\u002Fwrite and memory-managements storage. By doing this your attributes are more likely to change in the right most position and it's easier to scan with your eyes.\n\nYou must use `nonatomic` attribute, unless strictly necessary. On iOS, the locking introduced by `atomic` can significantly affect the performances.\n\nProperties that stores a block, in order to keep it alive after the end of the declaration scope, must be `copy` (the block is initially created on the stack, calling `copy` cause the block to be copied on the heap).\n\nIn order to achieve a public getter and a private setter, you can declare the public property as `readonly` and re-declare the same property in the the class extension as `readwrite`:\n\n```objective-c\n@interface MyClass : NSObject\n@property (nonatomic, readonly) NSObject *object\n@end\n\n@implementation MyClass ()\n@property (nonatomic, readwrite, strong) NSObject *object\n@end\n```\n\nIf the name of a `BOOL` property is expressed as an adjective, the property can omit the \"is\" prefix but specifies the conventional name for the get accessor, for example:\n\n```objective-c\n@property (assign, getter=isEditable) BOOL editable;\n```\nText and example taken from the [Cocoa Naming Guidelines](https:\u002F\u002Fdeveloper.apple.com\u002Flibrary\u002Fmac\u002F#documentation\u002FCocoa\u002FConceptual\u002FCodingGuidelines\u002FArticles\u002FNamingIvarsAndTypes.html#\u002F\u002Fapple_ref\u002Fdoc\u002Fuid\u002F20001284-BAJGIIJE).\n\nIn the implementation file avoid the use of `@synthesize`, Xcode is already adding this for you.\n\n#### Private Properties\n\nPrivate properties should be declared in class extensions (anonymous categories) in the implementation file of a class. Named categories (e.g. `ZOCPrivate`) should never be used unless extending another class.\n\n**For example:**\n\n```objective-c\n@interface ZOCViewController ()\n@property (nonatomic, strong) UIView *bannerView;\n@end\n```\n\n### Mutable Object\n\nAny property that potentially can be set with a mutable object (e.g. `NSString`,`NSArray`,`NSURLRequest`) must have the memory-management type to `copy`. This is done in order to ensure the encapsulation and prevent that the value is changed after the property is set without that the object know it.\n\nYou should also avoid to expose mutable object in the public interface, because this allows clients of your class to change your own internal representation and break the encapsulation. You can provide a read-only property that returns an immutable copy of your object:\n\n```objective-c\n\u002F* .h *\u002F\n@property (nonatomic, readonly) NSArray *elements\n\n\u002F* .m *\u002F\n- (NSArray *)elements {\n  return [self.mutableElements copy];\n}\n```\n\n### Lazy Loading\n\nThere are cases when instantiating an object can be expensive and\u002For needs to be configured once and has some configuration involved that you don't want to clutter the caller method.\n\nIn this case, instead of allocating the object in the init method one could opt for overriding the property getter for lazy instantiation. Usually the template for this kind of operation is the following:\n\n```objective-c\n- (NSDateFormatter *)dateFormatter {\n  if (!_dateFormatter) {\n    _dateFormatter = [[NSDateFormatter alloc] init];\n        NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@\"en_US_POSIX\"];\n        [dateFormatter setLocale:enUSPOSIXLocale];\n        [dateFormatter setDateFormat:@\"yyyy-MM-dd'T'HH:mm:ss.SSSSS\"];\n  }\n  return _dateFormatter;\n}\n```\n\nEven though this can be beneficial in some circumstance we advice to be thoughtful when you decide to do, and actually this should be avoided. The following are the arguments against the use of property with lazy initialization:\n\n* The getter should not have side effect. By looking a getter on the right-hand side you're not thinking that this is causing an object to be allocated or will lead to side effect. In fact, trying to call a getter without using the returned value the compiler will emit the warning \"getter should not used for side effect\";\n* You're moving the cost of the initialization as side effect of the first access, this will lead to difficulties to optimize performance issues (that are also hard to instrument);\n* The moment of instantiation can be non deterministic: for example you're expecting that this property is first accessed by a method but as soon as you change the class implementation, the accessor gets called before your original expectation. This can cause problems especially if the instantiation logic has dependencies on other state of the class that may be different. In general is better to explicitly express the dependency;\n* This behavior might not be KVO friendly. If the getter changes the reference it should fire a KVO notification for notify the change, it can be weird to receive a change notification when accessing a getter.\n\n\n## Methods\n\n### Parameter Assert\nYour method may require some parameter to satisfy certain condition (i.e. not to be nil): in such cases it's a good practice to use `NSParameterAssert()` to assert the condition and eventually throwing an exception.\n\n### Private methods\n\nNever prefix your private method with a single underscore `_`, this prefix is reserved by Apple, doing otherwise expose you to the risk of overriding an existing Apple's private method. A recommended approach is to use the `p_` prefix (e.g. `p_privateMethod`).\n\n## Equality\n\nIn case you need to implement equality remember the contract: you need to implement both the `isEqual` and the `hash` methods. If two objects are considered equal through `isEqual`, the `hash` method must return the same value, but if `hash` returns the same value the object are not guaranteed to be equals.\n\nThis contracts boils down to how the lookup of those objects is done when are stored in collections (i.e. `NSDictionary` and `NSSet` use hash table data structure underneath).\n\n```objective-c\n@implementation ZOCPerson\n\n- (BOOL)isEqual:(id)object {\n    if (self == object) {\n        return YES;\n    }\n\n    if (![object isKindOfClass:[ZOCPerson class]]) {\n        return NO;\n    }\n\n    \u002F\u002F check objects properties (name and birthday) for equality\n    ...\n    return propertiesMatch;\n}\n\n- (NSUInteger)hash {\n    return [self.name hash] ^ [self.birthday hash];\n}\n\n@end\n```\n\nIt is important to notice that the hash method must not return a constant. This is a typical error and causes serious problems as it will cause 100% of collisions in the hash table as the value returned by the hash method is actually used as key in the hash table.\n\nYou should also always implement a typed equality check method with the following format `isEqualTo\u003C#class-name-without-prefix#>:`\nIf you can, it's always preferable to call the typed equal method in order to avoid the type checking overhead.\n\nA complete pattern for the isEqual* method should be as so:\n\n```objective-c\n- (BOOL)isEqual:(id)object {\n    if (self == object) {\n      return YES;\n    }\n\n    if (![object isKindOfClass:[ZOCPerson class]]) {\n      return NO;\n    }\n\n    return [self isEqualToPerson:(ZOCPerson *)object];\n}\n\n- (BOOL)isEqualToPerson:(Person *)person {\n    if (!person) {\n        return NO;\n    }\n\n    BOOL namesMatch = (!self.name && !person.name) ||\n                       [self.name isEqualToString:person.name];\n    BOOL birthdaysMatch = (!self.birthday && !person.birthday) ||\n                           [self.birthday isEqualToDate:person.birthday];\n\n  return haveEqualNames && haveEqualBirthdays;\n}\n```\n\nGiven an object instance the computation of the `hash` should be deterministic, this is extremely important if the object is added to a container object (i.e. `NSArray`, `NSSet`, or `NSDictionary`) otherwise the behavior will be undefined (all container objects use the object's hash to do the lookup and enforce specific property like the uniqueness of the objects contained). That said, the calculation of the hash should always be made only by using immutable properties or, better yet, by guarantee the immutability of the objects.\n\n\n# Categories\n\nIt is ugly, we know, but categories should always be prefixed with your lower case prefix and an underscore i.e. `- (id)zoc_myCategoryMethod`. This practice is also [recommended by Apple](https:\u002F\u002Fdeveloper.apple.com\u002Flibrary\u002Fios\u002Fdocumentation\u002Fcocoa\u002Fconceptual\u002FProgrammingWithObjectiveC\u002FCustomizingExistingClasses\u002FCustomizingExistingClasses.html#\u002F\u002Fapple_ref\u002Fdoc\u002Fuid\u002FTP40011210-CH6-SW4).\n\nThis is absolutely needed because implementing a category method with a name already existing in the extended object or in another category may result in an undefined behavior. Practically, what is going to happen is that the implementation of the last category loaded will be the one that gets called. \n\nIn case you want to be sure that you're not replacing any implementation with your own category you can set the environment variable `OBJC_PRINT_REPLACED_METHODS` to `YES`, this will print in the console the names of the methods that have been replaced. \nAt the time of writing LLVM 5.1 does not emit any warning or error for this, so be careful and don't override methods in categories.\n\nA good practice is to use prefix also for category names.\n\n**Example:**\n\n```objective-c\n@interface NSDate (ZOCTimeExtensions)\n- (NSString *)zoc_timeAgoShort;\n@end\n```\n\n**Not:**\n\n```objective-c\n@interface NSDate (ZOCTimeExtensions)\n- (NSString *)timeAgoShort;\n@end\n```\n\nCategory can be used to group related method in a header file. This is a very common practice in Apple's framework (nearby is proposed an extract from `NSDate` header) and we strongly encourage to do the same in your code. \nIn our experience creating this groups can be helpful in further refactoring: when the interface of a class starts growing can be a signal that your class is doing to much and therefore violating the Single Responsibility Principle, the previously created groups be used to better understand the different responsibilities and help in breaking down the class in more self-contained components.\n\n```objective-c\n\n@interface NSDate : NSObject \u003CNSCopying, NSSecureCoding>\n\n@property (readonly) NSTimeInterval timeIntervalSinceReferenceDate;\n\n@end\n\n@interface NSDate (NSDateCreation)\n\n+ (instancetype)date;\n+ (instancetype)dateWithTimeIntervalSinceNow:(NSTimeInterval)secs;\n+ (instancetype)dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval)ti;\n+ (instancetype)dateWithTimeIntervalSince1970:(NSTimeInterval)secs;\n+ (instancetype)dateWithTimeInterval:(NSTimeInterval)secsToBeAdded sinceDate:(NSDate *)date;\n\u002F\u002F ...\n@end\n```\n\n# Protocols\n\nA great miss in the Objective-C world is the outcome of the latest decades about abstract interfaces. The term interface is typically used to refer to the `.h` file of a class but it has also another meaning well known to Java programmers which is basically used to describe to a set of methods not backed by a concrete implementation.\nIn Objective-C the latter case is achieved by using protocols. For historical reasons, protocols (used as Java interfaces) are not so much used in Objective-C code and in general by the community. It's mainly because the majority of the code developed at Apple don't embrace this approach and almost all developers tend to follow Apple's patterns and guidelines. Apple uses protocols almost only for the delegation pattern.\nThe concept of abstract interface is very powerful, has roots in the computer science history and there are no reasons to pretend it can't be used in Objective-C.\n\nHere will be explained a powerful usage of protocols (intended as abstract interfaces) going through a concrete example: starting from a very bad designed architecture up to reaching a very well and reusable piece of code.\n\nThe example presented is the implementation of a RSS feed reader (think of it as a common test task asked during technical interviews).\n\nThe requirement is straightforward: presenting a remote RSS feed in a table view.\n\nA very naïve approach would be to create a `UITableViewController` subclass and code the entire logic for the retrieving of the feed data, the parsing and the displaying in one place, which is, in other words, a MVC (Massive View Controller). This would work but it's very poorly designed and unfortunately it'd suffice to pass the interview step in some not-so-demanding tech startups.\n\nA minimal step forward would be to follow the Single Responsibility Principle and create at least 2 components to do the different tasks:\n\n- a feed parser to parse the results gathered from an endpoint\n- a feed reader to display the results\n\nThe interfaces for these classes could be as so:\n\n```objective-c\n\n@interface ZOCFeedParser : NSObject\n\n@property (nonatomic, weak) id \u003CZOCFeedParserDelegate> delegate;\n@property (nonatomic, strong) NSURL *url;\n\n- (id)initWithURL:(NSURL *)url;\n\n- (BOOL)start;\n- (void)stop;\n\n@end\n\n```\n\n```objective-c\n\n@interface ZOCTableViewController : UITableViewController\n\n- (instancetype)initWithFeedParser:(ZOCFeedParser *)feedParser;\n\n@end\n\n```\n\nThe `ZOCFeedParser` is initialized with a `NSURL` to the endpoint to fetch the RSS feed (under the hood it will probably use NSXMLParser and NSXMLParserDelegate to create meaningful data) and the `ZOCTableViewController` is initialized with the parser. We want it to display the values retrieved by the parser and we do it using delegation with the following protocol:\n\n```objective-c\n\n@protocol ZOCFeedParserDelegate \u003CNSObject>\n@optional\n- (void)feedParserDidStart:(ZOCFeedParser *)parser;\n- (void)feedParser:(ZOCFeedParser *)parser didParseFeedInfo:(ZOCFeedInfoDTO *)info;\n- (void)feedParser:(ZOCFeedParser *)parser didParseFeedItem:(ZOCFeedItemDTO *)item;\n- (void)feedParserDidFinish:(ZOCFeedParser *)parser;\n- (void)feedParser:(ZOCFeedParser *)parser didFailWithError:(NSError *)error;\n@end\n\n```\n\nIt's a perfectly reasonable and suitable protocol to deal with RSS, I'd say. The view controller will conform to it in the public interface:\n\n```objective-c\n@interface ZOCTableViewController : UITableViewController \u003CZOCFeedParserDelegate>\n```\n\nand the final creation code is like so: \n\n```objective-c\nNSURL *feedURL = [NSURL URLWithString:@\"http:\u002F\u002Fbbc.co.uk\u002Ffeed.rss\"];\n\nZOCFeedParser *feedParser = [[ZOCFeedParser alloc] initWithURL:feedURL];\n\nZOCTableViewController *tableViewController = [[ZOCTableViewController alloc] initWithFeedParser:feedParser];\nfeedParser.delegate = tableViewController;\n```\n\nSo far so good and you're probably happy with this new code, but how much of this code can be effectively reused? The view controller can only deal with objects of type `ZOCFeedParser`: at this point we just split the code in 2 components without any additional and tangible value than separation of responsibilities.\n\nThe responsibility of the view controller should be to \"display items provided by \u003Csomeone>\" but if we are allowed to pass to it only `ZOCFeedParser` objects this can't hold. Here surfaces the need for a more general type of object to be used by the view controller.\n\nWe modify our feed parser introducing the `ZOCFeedParserProtocol` protocol (in the ZOCFeedParserProtocol.h file where also `ZOCFeedParserDelegate` will be).\n\n```objective-c\n\n@protocol ZOCFeedParserProtocol \u003CNSObject>\n\n@property (nonatomic, weak) id \u003CZOCFeedParserDelegate> delegate;\n@property (nonatomic, strong) NSURL *url;\n\n- (BOOL)start;\n- (void)stop;\n\n@end\n\n@protocol ZOCFeedParserDelegate \u003CNSObject>\n@optional\n- (void)feedParserDidStart:(id\u003CZOCFeedParserProtocol>)parser;\n- (void)feedParser:(id\u003CZOCFeedParserProtocol>)parser didParseFeedInfo:(ZOCFeedInfoDTO *)info;\n- (void)feedParser:(id\u003CZOCFeedParserProtocol>)parser didParseFeedItem:(ZOCFeedItemDTO *)item;\n- (void)feedParserDidFinish:(id\u003CZOCFeedParserProtocol>)parser;\n- (void)feedParser:(id\u003CZOCFeedParserProtocol>)parser didFailWithError:(NSError *)error;\n@end\n\n```\n\nNotice that the delegate protocol now deals with objects conforming to our new protocol and the interface file of the ZOCFeedParser would be more skinny:\n\n```objective-c\n\n@interface ZOCFeedParser : NSObject \u003CZOCFeedParserProtocol>\n\n- (id)initWithURL:(NSURL *)url;\n\n@end\n\n```\n\nAs `ZOCFeedParser`now conforms to `ZOCFeedParserProtocol`, it must implement all the required methods.\nAt this point the view controller can accept any object conforming to the new protocol, having the certaincy that the object will respond to `start` and `stop` methods and that it will provide info through the delegate property. This is all the view controller should know about the given objects and no implementation details should concern it.\n\n\n```objective-c\n\n@interface ZOCTableViewController : UITableViewController \u003CZOCFeedParserDelegate>\n\n- (instancetype)initWithFeedParser:(id\u003CZOCFeedParserProtocol>)feedParser;\n\n@end\n\n```\n\nThe change in the above snippet of code might seem a minor change, but actually it is a huge improvement as the view controller would work against a contract rather than a concrete implementation. This leads to many advantages:\n\n- the view controller can now accept any object that provide some information via the delegate property: this can be a RSS remote feed parser, a local one, a service that read other types of data remotely or even a service that fetch data from the local database;\n- the feed parser object can be totally reused (as it was before after the first refactoring step);\n- `ZOCFeedParser` and `ZOCFeedParserDelegate` can be reused by other components;\n- `ZOCViewController` (UI logic apart) can be reused;\n- it is easier to test as it'd be possible to use a mock object conforming to the expected protocol.\n\nWhen implementing a protocol you should always strive to adhere to the [Liskov Substitution Principle](http:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FLiskov_substitution_principle). This principle states that you should be able to replace one implementation of an interface (\"protocol\" in the Objective-C lingo) with another without breaking either the client or the implementation.\n\nIn other words this means that your protocol should not leak the detail of the implementing classes; be even more careful when designing the abstraction expressed by you protocol and always keep in mind that th","《Zen and the Art of the Objective-C Craftsmanship》是一本专注于Objective-C编程规范与最佳实践的指南。该项目通过详细讨论条件语句、命名规则、类和对象设计、代码美化等核心编程要素，帮助开发者编写出更清晰、更易维护的Objective-C代码。它不仅涵盖了基本语法的使用建议，还深入探讨了诸如委托模式、块（blocks）以及面向切面编程等高级主题。适合于希望提升自身Objective-C编码技能或遵循统一编码标准的iOS\u002FmacOS开发者阅读参考。",2,"2026-06-11 03:15:10","top_language"]