An Objective-C formatter for iOS and macOS code
This Objective-C formatter runs clang-format in its Objective-C mode. clang-format comes from the same LLVM project as the Clang compiler that builds Objective-C in Xcode, so it knows the language's unusual syntax: @interface and @implementation blocks, property attributes, multi-part method names, message sends in square brackets and block literals.
Example
#import <UIKit/UIKit.h>
@interface ProfileViewController:UIViewController<UITableViewDataSource>
@property(nonatomic,strong)NSArray<NSString*>*items;
@end
@implementation ProfileViewController
-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section{return self.items.count;}
-(void)loadWithCompletion:(void(^)(BOOL success,NSError*error))completion{[self.api fetchItemsWithHandler:^(NSArray*result,NSError*error){self.items=result;completion(error==nil,error);}];}
@end
With the Google preset:
#import <UIKit/UIKit.h>
@interface ProfileViewController : UIViewController <UITableViewDataSource>
@property(nonatomic, strong) NSArray<NSString*>* items;
@end
@implementation ProfileViewController
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section {
return self.items.count;
}
- (void)loadWithCompletion:(void (^)(BOOL success, NSError* error))completion {
[self.api fetchItemsWithHandler:^(NSArray* result, NSError* error) {
self.items = result;
completion(error == nil, error);
}];
}
@end
A space is added after the - method marker, around the superclass colon and before the protocol list. The block passed to fetchItemsWithHandler: is indented relative to the message send, and the closing }]; lines up with the start of the statement.
Google vs. LLVM for Objective-C
- Google (default) follows the Google Objective-C Style Guide: 2-space indent, the
*attached to the type (NSString* name), and no space between@propertyand its attribute list. - LLVM attaches the
*to the name (NSString *name), the style used in Apple's own headers and documentation samples. - WebKit and Microsoft give 4-space indentation, which many Xcode users prefer because Xcode indents with 4 spaces by default.
If you want output that looks like Xcode's defaults, try LLVM with Indent set to 4 spaces.
Message sends and colon alignment
When a message send with several arguments exceeds the column limit, clang-format breaks it at the argument labels and aligns the colons, the traditional Objective-C layout:
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
}
Lower the Column limit to see this style more often, or raise it to keep calls on one line.
Nullability, generics and blocks
Modern Objective-C carries a lot of annotation that makes code bridge cleanly to Swift: NS_ASSUME_NONNULL_BEGIN / NS_ASSUME_NONNULL_END regions, nullable and _Nullable qualifiers, and lightweight generics such as NSArray<NSString *> *. The formatter keeps all of these exactly where you put them and only adjusts spacing; it does not add missing annotations. Block types are easier to read through a typedef, for example typedef void (^CompletionHandler)(BOOL success, NSError *error);, and clang-format spaces such typedefs consistently with the rest of the file.
Options
- Style – Google by default; six other presets.
- Indent – the preset's width, or 2–8 spaces, or tabs.
- Column limit – 100 by default; Google's Objective-C guide uses 100 as well. 0 disables wrapping.
Tips and limitations
- The formatter treats input as Objective-C. For pure C headers use the C Formatter; for Objective-C++ (
.mm) files, most code formats well here too. - Literals such as
@"text",@[ ]and@{ }are kept; dictionary literals are broken one entry per line when long. - Like all clang-format modes, it does not check that the code compiles. A missing
@endor bracket shows up as indentation that drifts to the right from that point on.
Creating model classes from an API response? JSON to Objective-C generates interfaces with properties that you can format here. Code is processed locally in your browser.