Can you write high-quality Objective-C code?

Can you write high-quality Objective-C code?

Dot notation syntax

Properties and idempotent methods (methods that return the same result when called multiple times) are accessed using dot notation, and all other methods use square bracket notation.

Good style:

  1. view.backgroundColor = [UIColor orangeColor];
  2. [UIApplication sharedApplication].delegate;
Bad style:
  1. [view setBackgroundColor:[UIColor orangeColor]];
  2. UIApplication.sharedApplication.delegate;

spacing

A single space is required between binary operators and their arguments, and no space is required between unary operators, casts, and their arguments. A single space is required after keywords and before parentheses.

  1. void *ptr = &value + 10 * 3 ;
  2.  
  3. NewType a = (NewType)b;
  4.  
  5. for ( int i = 0 ; i <</span> 10 ; i++) {
  6.  
  7. doCoolThings();
  8.  
  9. }

Place one space on each side of the square brackets in array and dictionary literals.

NSArray *theShit = @[ @1, @2, @3 ];

Dictionary literals have no space between the key and the colon, and one space between the colon and the value.

NSDictionary *keyedShit = @{ GHDidCreateStyleGuide: @YES };

In a C function declaration, no space is left before the left parenthesis, and the function name should have a namespace identifier like a class.

Good style: void RNCwesomeFunction(BOOL hasSomeArgs);

Long literals should be split across multiple lines.

Good style:

  1. NSArray *theShit = @[
  2.  
  3. @ "Got some long string objects in here." ,
  4.  
  5. [AndSomeModelObjects too],
  6.  
  7. @ "Moar strings."  
  8.  
  9. ];
  10.  
  11. NSDictionary *keyedShit = @{
  12.  
  13. @ "this.key" : @ "corresponds to this value" ,
  14.  
  15. @ "otherKey" : @ "remoteData.payload" ,
  16.  
  17. @ "some" : @ "more" ,
  18.  
  19. @ "JSON" : @ "keys" ,
  20.  
  21. @ "and" : @ "stuff" ,
  22.  
  23. };

Use 4 spaces for indentation of each line of code. Do not use tabs for indentation.

The left curly brace following a method signature and other keywords (if/else/switch/while, etc.) always appears on the same line as the statement, while the right curly brace occupies a separate line.

Good style:

  1. if (user.isHappy) {
  2.  
  3. //Do something  
  4.  
  5. }
  6.  
  7. else {
  8.  
  9. //Do something else  
  10.  
  11. }

If there are multiple functional areas within a method, blank lines can be used to separate the functional areas.

Each line of code should not exceed 100 characters.

Each method is preceded by a 99-character wide comment line. Comment lines can improve the code's recognizability compared to blank lines. When a line of code is very long, comment lines also serve as out-of-bounds detection. Comment lines:

//////////////////////////////////////////////////////////////////////////////////////////////////////////

Conditional Statements

All logic blocks must be surrounded by curly braces, even if the conditional body only needs one line of code.

Good style practices:

  1. if (!error) {
  2.  
  3. return success;
  4.  
  5. }

Bad style:

if (!error)

return success;

or:

if (!error) return success;

Ternary Operator

Long ternary operators should be enclosed in parentheses. The ternary operator is only used for assignment and parameterization.

  1. Blah *a = (stuff == thing ? foo : bar);

The coalesced nil ternary operator should be avoided if possible.

Bad style:

  1. Blah *b = thingThatCouldBeNil ?: defaultValue;

Multiple branching conditions should use if statements or be refactored into instance variables.

Good style:

  1. result = a > b ? x : y;

Bad style:

  1. result = a > b ? x = c > d ? c : d : y;

Exception and Error Handling

Do not use exceptions (NSException) in flow control statements.

Exceptions are only used to indicate programmer errors.

To indicate an error, use NSError*.

When a method returns an error parameter by reference, the status of the return value should be checked, not the status of the error parameter.

Good style:

  1. NSError *error;
  2.  
  3. if (![self trySomethingWithError:&error]) {
  4.  
  5. // Handle Error  
  6.  
  7. }

Bad style:

  1. NSError *error;
  2.  
  3. [self trySomethingWithError:&error];
  4.  
  5. if (error) {
  6.  
  7. // Handle Error  
  8.  
  9. }

Assigning a non-Null value to an error parameter when the method is executed successfully will cause the path to jump to the false conditional branch (and then the program crashes).

acting

Except for inheriting a class or implementing a protocol, only use the class declaration @class directive in the header file, and do not use #import to import the class header file.

If a delegate has only a few methods, such as submit and cancel, it is recommended to use blocks to write action response codes.

Since the declaration of proxy methods is generally very long, the proxy object and other protocol objects must be placed below the instance variable definition, otherwise the alignment of the instance variable definition will be disrupted.

When multiple protocols need to be implemented, separate each protocol name into a separate line.

Good style:

  1. @interface CustomModelViewController : TTViewController <</span>
  2.  
  3. TTModelDelegate,
  4.  
  5. TTURLRequestDelegate
  6.  
  7. > {

method

A method name first describes what is returned, followed by the circumstances under which it is returned. The type of the arguments passed in is described before the colon in the method signature. The following format syntax is used for class and instance method names:

  1. [object/ class thing+condition];
  2.  
  3. [object/ class thing+input:input];
  4.  
  5. [object/ class thing+identifer:input];

Cocoa naming example:

  1. realPath = [path stringByExpandingTildeInPath];
  2.  
  3. fullString = [string stringByAppendingString:@ "Extra Text" ];
  4.  
  5. object = [array objectAtIndex: 3 ];
  6.  
  7. // Class methods  
  8.  
  9. newString = [NSString stringWithFormat:@ "%f" , 1.5 ];
  10.  
  11. newArray = [NSArray arrayWithObject:newString];

Good naming style for custom methods:

  1. recipients = [email recipientsSortedByLastName];
  2.  
  3. newEmail = [CDCEmail emailWithSubjectLine:@ "Extra Text" ];
  4.  
  5. emails = [mailbox messagesReceivedAfterDate:yesterdayDate];

When you need to get another type of object value, the method naming format syntax is as follows:

  1. [object adjective+thing];
  2.  
  3. [object adjective+thing+condition];
  4.  
  5. [object adjective+thing+input:input];

Good naming style for custom methods:

  1. capitalized = [name capitalizedString];
  2.  
  3. rate = [number floatValue];
  4.  
  5. newString = [string decomposedStringWithCanonicalMapping];
  6.  
  7. subarray = [array subarrayWithRange:segment];

Method signatures should be as clear as possible.

Bad style:

  1. -sortInfo // Return the sorted result or sort the info  
  2.  
  3. -refreshTimer // Return a timer for refresh or refresh timer  
  4.  
  5. -update // What to update and how to update  

Good style:

  1. -currentSortInfo // "current" clearly modifies the noun SortInfo  
  2.  
  3. -refreshDefaultTimer // refresh is a verb.  
  4.  
  5. -updateMenuItemTitle // An action is happening  

A space should be placed after the method type modifier +/-, and a space should be placed between each parameter name.

Good style:

  1. - ( void )setExampleText:(NSString *)text image:(UIImage *)image;

If the method name is particularly long, split the method name into multiple lines.

Good style:

  1. color = [NSColor colorWithCalibratedHue: 0.10  
  2.  
  3. Saturation: 0.82  
  4.  
  5. brightness: 0.89  
  6.  
  7. alpha: 1.00 ];

Do not declare private instance variables and methods in header files. Instead, declare private variables and methods in the class extension of the implementation file.

Bad style:

  1. //MyViewController.h file  
  2.  
  3. @interface MyViewController : UIViewController<</span>
  4.  
  5. UITalbeViewDataSource,
  6.  
  7. UITableViewDelegate> {
  8.  
  9. @private :
  10.  
  11. UITableView *_myTableView; // Private instance variable  
  12.  
  13. }
  14.  
  15. // Properties used internally  
  16.  
  17. @property (nonatomic,strong) NSNumber *variableUsedInternally;
  18.  
  19. - ( void )sortName; // Method for internal use only  
  20.  
  21. @end  
  22. Good style:
  23.  
  24. //MyViewController.m file uses class extension  
  25.  
  26. @interface MyViewController()<</span>
  27.  
  28. UITalbeViewDataSource,
  29.  
  30. UITableViewDelegate> {
  31.  
  32. UITableView *_myTableView;
  33.  
  34. // Instance variables that need to be accessed externally are declared as properties, and those that do not need to be accessed externally are declared as instance variables  
  35.  
  36. NSNumber * variableUsedInternally;
  37.  
  38. }
  39.  
  40. // Starting from Xcode 4.3, you don't need to write a forward declaration of the method, and Interface Builder and Storyboard can still find the definition of the method  
  41.  
  42. @end  

Constructors should usually return instance types rather than id types.

parameter

Commonly used prefixes before method parameter names include "the", "an", and "new".

Good style:

  1. - ( void ) setTitle: (NSString *) aTitle;
  2.  
  3. - ( void ) setName: (NSString *) newName;
  4.  
  5. - (id) keyForOption: (CDCOption *) anOption
  6.  
  7. - (NSArray *) emailsForMailbox: (CDCMailbox *) theMailbox;
  8.  
  9. - (CDCEmail *) emailForRecipients: (NSArray *) theRecipients;

variable

Variable names should be self-descriptive. Except in for() loop statements, single-letter variables should be avoided (such as i, j, k, etc.). The naming prefixes of the current object in general loop statements include "one", "a/an". For simple single objects, use "item".

Good style:

  1. for (i = 0 ; i < count; i++) {
  2.  
  3. oneObject = [allObjects objectAtIndex: i];
  4.  
  5. NSLog (@ "oneObject: %@" , oneObject);
  6.  
  7. }
  8.  
  9. NSEnumerator *e = [allObjects objectEnumerator];
  10.  
  11. id item;
  12.  
  13. while (item = [e nextObject])
  14.  
  15. NSLog (@ "item: %@" , item);

The asterisk indicator of a pointer variable should be next to the variable, such as NSString *text, not NSString* text or NSString * text.

Try to use properties instead of instance variables. Except for accessing instance variables synthesized by properties in initialization methods (init, initWithCoder:, etc.), dealloc methods, and custom setter and getter methods, use properties for access in other situations.

Good style:

  1. @interface RNCSection: NSObject
  2.  
  3. @property (nonatomic) NSString *headline;
  4.  
  5. @end  

Bad style:

  1. @interface RNCSection : NSObject {
  2.  
  3. NSString *headline;
  4.  
  5. }

When you use the @synthesize directive, the compiler automatically creates an instance variable for you starting with an underscore _, so there is no need to declare both the instance variable and the property.

Bad style:

  1. @interface RNCSection : NSObject {
  2.  
  3. NSString *headline;
  4.  
  5. }
  6.  
  7. @property (nonatomic) NSString *headline;
  8.  
  9. @end  

Good style:

  1. @interface RNCSection: NSObject
  2.  
  3. @property (nonatomic) NSString *headline;
  4.  
  5. @end  

Do not use @synthesize unless required by the compiler. Note that @optional properties in @protoco protocols must be explicitly synthesized using the @synthesize directive.

Abbreviations

Although method names should not use abbreviations, some abbreviations have been used repeatedly in the past, so using these abbreviations can better express the meaning of the code. The following table lists the abbreviations that Cocoa accepts.

.................................................................................

Here are some commonly used acronyms:

ASCII PDF XML HTML URL RTF HTTP TIFF JPG PNG GIF LZW ROM RGB CMYK MIDI FTP

name

Method and variable names should be as self-describing as possible.

Good style:

  1. UIButton *settingsButton;

Bad style:

  1. UIButton *setBut;

For NSString, NSArray, NSNumber, or BOOL types, the name of the variable generally does not need to indicate its type.

Good style:

  1. NSString *accountName;
  2.  
  3. NSMutableArray *mailboxes;
  4.  
  5. NSArray *defaultHeaders;
  6.  
  7. BOOL userInputWasUpdated;

Bad style:

  1. NSString *accountNameString;
  2.  
  3. NSMutableArray *mailboxArray;
  4.  
  5. NSArray *defaultHeadersArray;
  6.  
  7. BOOL userInputWasUpdatedBOOL;

If the variable is not of the above basic common types, the variable name should reflect its own type. But sometimes only one instance of a certain class is needed, so only the name based on the class name is needed.

  1. NSImage *previewPaneImage;
  2.  
  3. NSProgressIndicator *uploadIndicator;
  4.  
  5. NSFontManager *fontManager; // Naming based on class name  

In most cases, variables of type NSArray or NSSet only need to use the plural form of the word (such as mailboxes), without including "mutable" in the name. If the plural variable is not of type NSArray or NSSet, you need to specify its type.

Good style:

  1. NSDictionary *keyedAccountNames;
  2.  
  3. NSDictionary * messageDictionary;
  4.  
  5. NSIndexSet * selectedMailboxesIndexSet;

Since Objective-C does not support namespaces, to prevent namespace conflicts, add a three-letter uppercase prefix (such as RNC) to class names and constant variable names. This rule can be ignored for Core Data entity names. If you subclass a standard Cocoa class, it is a good practice to merge the prefix with the parent class name. For example, a class that inherits UITableView can be named RNCTableView.

Constant variable names are written in camel case (the first letter of the first word is lowercase, and the first letter of the remaining words is uppercase. For example, firstName instead of first_name or firstname.) and use the associated class name as its naming prefix.

Recommended practice:

  1. static   const NSTimeInterval RNCArticleViewControllerNavigationFadeAnimationDuration = 0.3 ;

Not recommended:

  1. static   const NSTimeInterval fadetime = 1.7 ;

Underline

When using properties, instance variables should be accessed and set using self. Local variable names should not contain underscores. Instance variable names must be prefixed with an underscore _ to narrow the range of options that Xcode automatically completes.

Notes

Comments can be used to explain the code when necessary. When updating the code, be sure to update the comments to prevent misunderstanding of the code.

Use javadoc-style documentation comment syntax. The first line of the comment is a summary of the comment API, and subsequent comment lines explain the code in more detail.

Good style:

  1. @property (nonatomic) NSUInteger maxContentLength;

init and dealloc

The dealloc method should be placed at the top of the implementation method, directly after the @synthesize or @dynamic statement. The init method should be placed below the dealloc method.

The structure of the init method should look like this:

  1. - (instancetype)init {
  2.  
  3. self = [ super init]; // or call the designated initalizer  
  4.  
  5. if (self) {
  6.  
  7. // Custom initialization  
  8.  
  9. }
  10.  
  11. return self;
  12.  
  13. }

Literals

For NSString, NSDictionary, NSArray, and NSNumber classes, when you need to create immutable instances of these classes, you should use the literal representation of these classes. When using literal representation, nil does not need to be passed into NSArray and NSDictionary as a literal value. This syntax is compatible with older iOS versions, so it can be used in iOS5 or older versions.

Good style:

  1. NSArray *names = @[@ "Brian" , @ "Matt" , @ "Chris" , @ "Alex" , @ "Steve" , @ "Paul" ];
  2.  
  3. NSDictionary *productManagers = @{@ "iPhone" : @ "Kate" , @ "iPad" : @ "Kamal" , @ "Mobile Web" : @ "Bill" };
  4.  
  5. NSNumber *shouldUseLiterals = @YES ;
  6.  
  7. NSNumber *buildingZIPCode = @10018 ;

Bad style:

  1. NSArray *names = [NSArray arrayWithObjects:@ "Brian" , @ "Matt" , @ "Chris" , @ "Alex" , @ "Steve" , @ "Paul" , nil];
  2.  
  3. NSDictionary *productManagers = [NSDictionary dictionaryWithObjectsAndKeys: @ "Kate" , @ "iPhone" , @ "Kamal" , @ "iPad" , @ "Bill" , @ "Mobile Web" , nil];
  4.  
  5. NSNumber *shouldUseLiterals = [NSNumber numberWithBool:YES];
  6.  
  7. NSNumber *buildingZIPCode = [NSNumber numberWithInteger: 10018 ];

Avoid using certain types of numbers unless necessary (use 5.3 instead of 5.3f).

CGRect Function

Prefer using C99 structure initialization syntax to using structure helper functions (such as CGRectMake()).

CGRect rect = {.origin.x = 3.0, .origin.y = 12.0, .size.width = 15.0, .size.height = 80.0 };

When accessing the x, y, width, and height members of the CGRect structure, you should use the CGGeometry function instead of directly accessing the structure members. Apple's introduction to the CGGeometry function:

All functions described in this reference that take CGRect data structures as inputs implicitly standardize those rectangles before calculating their results. For this reason, your applications should avoid directly reading and writing the data stored in the CGRect data structure. Instead, use the functions described here to manipulate rectangles and to retrieve their characteristics.

Good style:

  1. CGRect frame = self.view.frame;
  2.  
  3. CGFloat x = CGRectGetMinX(frame);
  4.  
  5. CGFloat y = CGRectGetMinY(frame);
  6.  
  7. CGFloat width = CGRectGetWidth(frame);
  8.  
  9. CGFloat height = CGRectGetHeight(frame);

Bad style:

  1. CGRect frame = self.view.frame;
  2.  
  3. CGFloat x = frame.origin.x;
  4.  
  5. CGFloat y = frame.origin.y;
  6.  
  7. CGFloat width = frame.size.width;
  8.  
  9. CGFloat height = frame.size.height;

constant

Prefer constant variables rather than embedded string literals or numbers, because constant variables can easily reuse commonly used variable values ​​(such as π), and can quickly modify values ​​without search and replacement. Constant variables should be declared as static types, and do not use #define, unless the constant variable is used as a macro.

Good style:

  1. static NSString * const RNCAboutViewControllerCompanyName = @ "The New York Times Company" ;
  2.  
  3. static   const CGFloat RNCImageThumbnailHeight = 50.0 ;

Bad style:

  1. #define CompanyName @ "The New York Times Company"  
  2.  
  3. #define thumbnailHeight 2  

Enumeration Types

When using the enum keyword, it is recommended to use the fixed base type syntax recently introduced by Apple, because this will get strong type checking and code completion. The SDK now includes a fixed base type macro - NS_ENUM().

NS_ENUM was introduced in iOS 6. To support previous iOS versions, use a simple inline method:

  1. #ifndef NS_ENUM
  2.  
  3. #define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
  4.  
  5. #endif

Good style:

  1. typedef NS_ENUM(NSInteger, RNCAdRequestState) {
  2.  
  3. RNCAdRequestStateInactive,
  4.  
  5. RNCAdRequestStateLoading
  6.  
  7. };

Private properties

Private properties should be declared in the class extension of the implementation file (that is, an anonymous category). Do not declare private properties in a named category (such as RNCPrivate or private) unless you are extending another class.

Good style:

  1. @interface NYTAdvertisement ()
  2.  
  3. @property (nonatomic, strong) GADBannerView *googleAdView;
  4.  
  5. @property (nonatomic, strong) ADBannerView *iAdView;
  6.  
  7. @property (nonatomic, strong) UIWebView *adXWebView;
  8.  
  9. @end  

Naming pictures

The names of images should be consistent, with the image's purpose as the image file name. The file name should be in camel case, and can be followed by a custom class name or custom attribute name (if there is an attribute name), and can also be followed by a description of the color and/or location, and the final state of the image.

Good style:

RefreshBarButtonItem / RefreshBarButtonItem@2x and RefreshBarButtonItemSelected / RefreshBarButtonItemSelected@2x

ArticleNavigationBarWhite / ArticleNavigationBarWhite@2x and ArticleNavigationBarBlackSelected / ArticleNavigationBarBlackSelected@2x.

Images that are used for similar purposes should be managed separately using an image folder.

Boolean Type

Because nil is interpreted as NO, there is no need to compare it with nil. Do not compare variables with YES directly, because YES is defined as 1 and BOOL type is an 8-bit unsigned int, that is, the value of BOOL is not only 1 or 0.

Good style:

  1. if (!someObject) {
  2.  
  3. }

Bad style:

  1. if (someObject == nil) {
  2.  
  3. }

For a BOOL value: Two best practices:

  1. if (isAwesome)
  2.  
  3. if (![someObject boolValue])

Bad style:

  1. if ([someObject boolValue] == NO)
  2.  
  3. if (isAwesome == YES) // Never do this.  

If a BOOL property name is an adjective, omitting the "is" prefix is ​​allowed, but the accessor must specify a conventional method name, such as:

@property (assign, getter=isEditable) BOOL editable;

Singleton

Shared singleton instances should be created using thread-safe patterns.

  1. + (instancetype)sharedInstance {
  2.  
  3. static id sharedInstance = nil;
  4.  
  5.   
  6.  
  7. static dispatch_once_t onceToken;
  8.  
  9. dispatch_once(&onceToken, ^{
  10.  
  11. sharedInstance = [[self alloc] init];
  12.  
  13. });
  14.  
  15.   
  16.  
  17. return sharedInstance;
  18.  
  19. }

appendix

Xcode Themes

Most developers use the default font color theme of Xcode. In fact, a good theme can not only improve the recognition of source code, but also add fun to coding. Here are two links to Xcode font color themes:

https://github.com/vinhnx/Ciapre-Xcode-theme

https://github.com/tursunovic/xcode-themes

Code Snippet

Skilled use of the code snippet library can increase your coding speed. In Xcode4, open a project and make the editing area visible on the right, then click the fourth {} icon on the right bottom panel to open the code snippet library, where you can drag commonly used codes. The following is a link to the latest open source code snippet library:

https://github.com/mattt/Xcode-Snippets

<<:  8 pictures to understand Java

>>:  Why is the entry-level capacity of iPhone only 16GB?

Recommend

Introduction to the first release of Huawei AppGallery

First release resource introduction 1. Home page ...

New product online event planning and promotion!

When it comes to online event planning, the most ...

Analysis of the e-commerce operation growth formula!

Compared with previous years, this year's Dou...

Sharing practical experience in operating and promoting Xiaohongshu

As of January this year, Xiaohongshu has more tha...

Is there really water on the moon? This means...

Recently, Chinese scientists discovered an unknow...

An inventory of information flow video advertising formats!

With the development of the times, users' imm...