Skip to content

Instantly share code, notes, and snippets.

@mgrebenets
Last active November 10, 2015 11:43
Show Gist options
  • Save mgrebenets/4bfda3e1d701ef053b87 to your computer and use it in GitHub Desktop.
Save mgrebenets/4bfda3e1d701ef053b87 to your computer and use it in GitHub Desktop.
Objective-C Code Formatting Sample
//
// Copyright blah-blah
//
// ---
// Group of assignments
int x = 5;
int longVariableName = 444;
unsigned long long anotherVar = 3;
// ---
// Enums
typedef NS_OPTIONS(NSUInteger,ImageType) {
ImageTypeNone = 0,
ImageTypeThumbnail = 1 << 0,
ImageTypeWideLead = 1 << 1,
ImageTypeNarrowLead = 1 << 2,
ImageTypeIndexLead = 1 << 3,
ImageTypeAll = 0xff,
};
extern NSString *const ServiceErrorDomain;
typedef NS_ENUM(NSInteger, ServiceErrorCode){
ServiceErrorCodeKillApp = 501,
ServiceErrorCodeImageNotAvailable = 1404,
ServiceErrorCodeSection = 4401,
ServiceErrorCodeAsset = 4402
};
typedef NS_OPTIONS(NSUInteger, ServiceErrorAction) {
ServiceErrorActionNone = 0, /** Unknown */
ServiceErrorActionAlert = 1 << 0, /** Alert are allowed */
ServiceErrorActionBannerAuto = 1 << 1, /** Banner with automatic hiding actions are allowed */
ServiceErrorActionBannerManual = 1 << 2, /** Banner with manual actions are allowed */
ServiceErrorActionBackground = 1 << 3, /** Background action without user notification are allowed */
ServiceErrorActionLog = 1 << 4, /** Log action */
};
typedef NS_OPTIONS(NSUInteger, ServiceErrorAction) {
ServiceErrorActionNone = 0, /** Unknown */
ServiceErrorActionAlert = 1, /** Alert are allowed */
ServiceErrorActionAlert = 1 << 0, /** Alert are allowed */
ServiceErrorActionBannerAuto = 1 << 1, /** Banner with automatic hiding actions are allowed */
ServiceErrorActionBannerManual = 1 << 2, /** Banner with manual actions are allowed */
ServiceErrorActionBackground = 1 << 3, /** Background action without user notification are allowed */
ServiceErrorActionLog = 1 << 4, /** Log action */
};
typedef NS_ENUM(NSUInteger, ServiceErrorAction) {
ServiceErrorActionNone = 0, /** Unknown */
ServiceErrorActionAlert = 1 << 0, /** Alert are allowed */
ServiceErrorActionBannerAuto = 1 << 1, /** Banner with automatic hiding actions are allowed */
ServiceErrorActionBannerManual = 1 << 2, /** Banner with manual actions are allowed */
ServiceErrorActionBackground = 1 << 3, /** Background action without user notification are allowed */
ServiceErrorActionLog = 1 << 4, /** Log action */
};
typedef NS_ENUM(NSUInteger, ServiceFetchingType) {
ServiceFetchingTypeNone, /** Unknown */
ServiceFetchingTypeVirtute, /** Lorem ipsum dolor sit amet related events */
ServiceFetchingTypeVirtutes, /** Lorem ipsum dolor sit amet events */
ServiceFetchingTypePicture, /** Lorem ipsum dolor sit amet */
ServiceFetchingTypePictureAsset, /** Lorem ipsum dolor sit amet, amet, amet */
ServiceFetchingTypeAsset, /** Lorem ipsum dolor sit amet */
};
// ---
// Properties
@property(nonatomic,assign,getter=isReady)BOOL ready;
@property (nonatomic, assign, getter=isReady) BOOL ready;
// ---
// Const Qualifiers, Literals
static NSSting *const key = @"key";
static NSSting * const key = @"key";
// Dictionary and Array
NSDictionary * const attr = @{NSFileProtectionKey : NSFileProtectionNone};
NSDictionary *const attr = @{ NSFileProtectionKey : NSFileProtectionNone };
NSDictionary * attr = @{ NSFileProtectionKey : NSFileProtectionNone };
NSDictionary *attr = @{ NSFileProtectionKey : NSFileProtectionNone };
NSArray *arr = @[@"a",@"b",@"c"];
NSArray *arr = @[@"a",@"b",@"c" ];
// ---
// Case Switches
switch (x) {
case A: return nil;
default: return 5;
}
switch (x) {
case A: return nil;
default: return 5;
}
// ---
// Preprocessor definition alignments
#ifdef WHATEVER
#define ALIGNED_DEFINITION
#endif
#ifdef WHATEVER
#define UNALIGNED_DEFINITION
#endif
#if defined(DEBUG) && DEBUG!=0
BOOL NSIsBeingDebugged(void);
extern void NSDebugger(void);
#else
# define NSIsBeingDebugged() (NO)
# define NSDebugger() do{}while(0)
#endif
// ---
// Pragmas
// Must be 2 lines before pragma
#pragma - Must have 2 lines before and 1 after
#pragma Yet another pragma
// No newline there
// Absolutely correct pragma
#pragma - Correct pragma
// End of correct pragma
// ---
// Comments
// ---
//Bad comment with no space
// Good comment with the space
//bad lowercase comment with no space
// bad lowercase comment with space
///Bad tripple slash comment with no space
///bad tripple slash lowercase comment with no space
/// bad tripple slash comment with space
/*
* Block comment witht the stars not aligned and space after star
*/
/**
*Block comment with stars not aligned and no space after start
*/
/**
Block comment with no stars
*/
/**
* Block comment with aligned stars and space after star
*/
/**
* Block comment with aligned stars and tab after star
* More tabs
* But this one is space
*/
/**
* Block comment with markdown that causes issues
* ## Known Issues
* - Why is it doing this
* - Why is it doing this
*/
/**
* VVV Documenter
*/
/**
* More VVV Documenter
*
* @param progress progress description
* @param animated animated description
*/
// ---
// Pragma
- (void)code;
#pragma No newlines before pragma
- (void)noNewlineAfterPragma;
- (void)code;
#pragma Extra newlines before pragma
- (void)extraNewlinesAfterPragma;
// ---
// Newlines
-(void)code;
-(void)extraNewlinesBetweenCode;
// ---
// Spaces
// Operators
a=b-c;
a = b - c;
a ++;
a++;
a?b:c;
a ? b : c;
a?:b;
a? :b;
a ?: b;
a-=b;
a -= b;
-- a+b;
--a + b;
a/b;
a / b;
x=a*b;
x = a * b;
// This is actually type declaration (b is pointer to type a)
a*b;
a * b;
( a-b );
(a - b);
a<b;
a < b;
a||b;
a || b;
a|b;
a | b;
a|b || c && d | e;
int x = a&b || c && d | e;
// When at start of the line 'a &b' treated as type and var name
a&b || c && d | e;
// Preprocessor
a ## b;
a##b;
// ---
// Braces
if (a) {
// This comment is for else, but is aligned to the left
} else {
}
if (a) {
// This is how it should be
} else {
}
if (a)
{
// X
}
else
{
//Y
}
// Uncrustify's fix check
if (a < b && b > c) {
// ...
}
// ---
// Imports
// TODO:
// ---
// Multiline Conditionals
// In clang-format this is controlled by BreakBeforeBinaryOperators
// `None` breaks _after_ operators
// `All` breaks _before_ operators
if (![[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error]
|| ![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:&error]) {
}
// But this one clang-format will leave untouched
if (![[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error] ||
![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:&error]) {
}
// Another example of multiline conditionals
if (carrier.carrierName
&& (FunctionCall(carrier.carrierName)
|| FunctionCall(carrier.isoCountryCode)
|| FunctionCall(carrier.mobileCountryCode)
|| FunctionCall(carrier.mobileCountryCode))) {
// Stub
}
if (carrier.carrierName &&
(FunctionCall(carrier.carrierName) ||
FunctionCall(carrier.isoCountryCode) ||
FunctionCall(carrier.mobileCountryCode) ||
FunctionCall(carrier.mobileCountryCode))) {
// Stub
}
// ---
// Language Extensions
// __has_include
// This is know to be broken by both clang-format and uncrustify
// if spaces are forced around `/` operator
#if defined(__has_include) && __has_include(<FacebookSDK/FacebookSDK.h>)
#endif
// ---
// Type Casting
(int *)x = NULL;
(int *) x = NULL;
(int*)x = NULL;
(int*) x = NULL;
// Stuff below gets extra space
// Case outside `[]` to avoid this issue
[(DataSource *)dataSource menuForTableView:tableView section:idx rowAnimation:animation];
[(DataSource *) dataSource menuForTableView:tableView section:idx rowAnimation:animation];
// ---
// Blocks
// Note that `completion:` is on the same line as `}`
// This will prevent uncrustify from doing proper Xcode style formatting
[UIView animateWithDuration:0.5
animations:^{
self.view.alpha = 0.0;
} completion:^(BOOL finished) {
[self removeFromParentViewController];
[self.view removeFromSuperview];
[self.delegate didDismiss:self];
}];
// Make sure you have newline after `}` so that uncrustify does a better job
[UIView animateWithDuration:0.5
animations:^{
self.view.alpha = 0.0;
}
completion:^(BOOL finished) {
[self removeFromParentViewController];
[self.view removeFromSuperview];
[self.delegate didDismiss:self];
}];
// This is how it should be formatted Xcode-style
// All arguments aligned by `:`
- (void)startAnimation {
[UIView animateWithDuration:0.3
animations:^{
self.progressView.alpha = 1.0;
}
completion:^(BOOL completion) {
[self updateCurrentStatusWith:StateRunning];
}];
}
// More cases with small errors here and there
- (void)failedAnimation {
[UIView animateWithDuration:0.3
animations:^{
self.progressView.backgroundColor = [UIColor redColor];
}
completion:nil];
}
- (void)successAnimation {
[UIView animateWithDuration:0.8
animations:^{
self.progressView.backgroundColor = [UIColor greenColor];
}
completion:^(BOOL completion){
if (completion) {
[self updateCurrentStatusWith:StateNone];
}
}];
}
- (void)stopAnimation {
[UIView animateWithDuration:0.3
animations:^{
self.progressView.alpha = 0.0;
}
completion:^(BOOL completion){
self.progress = 0;
[self stateReset];
}];
}
// This is another example of multiple blocks as arguments
// Gets badly broken by uncrustify + clang-format combo
[LIAlertView showAlertViewWithTitle:NSLocalizedString(@"Alert Title", nil)
message:message
cancelButtonTitle:NSLocalizedString(@"Cancel", nil)
cancelButtonHandler:^{
[self loadLoremIpsum];
}
otherButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonHandler:^{
[self loadLoremIpsum];
}];
// And this gets extra space after value...
// Depending on the align_oc_msg_colon_first
// Because first argument name is too short (set) extra spaces will be added after value and before :
// Set align_oc_msg_colon_first to true to avoid this behavior
dispatch_async(self.queue, ^{
[self.trackerXYZ set:[SomeClass someMethod:4]
value:someValue];
});
// More related examples
dispatch_async(self.queue, ^{
[self.tracker set:[SomeClass someMethod:4] value:someValue];
});
// Uncrustify may add some extra spaces before valueChangedBlock and :
// Depends on align_oc_msg_colon_first
SwitchCellController *cellController = [[SwitchCellController alloc] initWithTitle:section.name
valueChangedBlock:^(UITableView *tableView, TableViewSwitchCellController *cellController) {
[object methodWithArgument:argument.on];
NSError *error = nil;
if (![[SomeManager sharedSomeManager] saveContext:&error]) {
NSLog(@"Error: Something went wrong!");
}
}];
dispatch_async(queue, ^{
[object method:[arg method:4] method:arg];
});
dispatch_async(queue, ^{
[object method:[arg method:4]
method:arg];
});
dispatch_async(queue, ^{
[object set:[arg method:4]
value:arg];
});
dispatch_async(queue, ^{
[object set:[arg method:4]
method:arg];
});
dispatch_async(queue, ^{
[object method:[arg method:4]
value:arg];
});
// This nested construction is too complicated for clang-format to handle
// Uncrustify does a bit better job
- (NSOrderedSet *)assetsForAssetType:(AssetType)assetType {
return [self.childAssets filteredOrderedSetUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(Asset *asset, NSDictionary *bindings) {
return asset.assetType == assetType;
}]];
}
- (NSOrderedSet *)assetsForAssetType:(AssetType)assetType {
return [self.childAssets filteredOrderedSetUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(Asset *asset, NSDictionary *bindings) {
return asset.assetType == assetType;
}]
];
}
- (NSOrderedSet *)assetsForAssetType:(AssetType)assetType {
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL (Asset *asset, NSDictionary *bindings) {
return asset.assetType == assetType;
}];
return [self.childAssets filteredOrderedSetUsingPredicate:predicate];
}
// ---
// Protocols
- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key {}
- (void)setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key {}
[object:^BOOL(id < Protocol > broken) {
}];
[object:^BOOL(id <Protocol> broken) {
}];
[object:^BOOL(id<Protocol> broken) {
}];
[object:^BOOL(id < Protocol_Name_With1234 > broken) {
}];
@interface SomeManager()<Protocol, Protocol>
@end
@interface SomeManager ()<Protocol, Protocol>
@end
@interface SomeManager () <Protocol, Protocol>
@end
@protocol ViewControllerDelegate <NSObject>
- (void)didDismissViewController;
@end
@protocol ViewControllerDelegate<NSObject>
- (void)didDismissViewController;
@end
@interface WebViewController : UIViewController <UIWebViewDelegate>
@end
// Subscripts
- (id)objectForKeyedSubscript:(id <NSCopying>)key;
- (id)objectForKeyedSubscript:(id<NSCopying>)key;
- (void)setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key;
- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key;
// Some Stuff with nested blocks and ifs
[weakSelf.backgroundSaveContext performBlock:^{
SomeThing *backgroundThing = [weakSelf sectionWithObjectID:objectID inContext:weakSelf.backgroundSaveContext];
[backgroundThing configureWithPayload:payload];
NSError *saveError = nil;
if (![weakSelf saveContext:weakSelf.backgroundSaveContext saveParent:NO error:&saveError]) {
NSLog(@"ERROR Saving Context: %@", saveError.localizedDescription);
abort();
}
NSAssert(![objectID isTemporaryID], @"Some error");
[weakSelf.observers enumerateObjectsUsingBlock:^(id<SomeServiceObserver> observer, BOOL *stop) {
if ([observer respondsToSelector:@selector(serviceManager:didUpdateThingWithObjectID:identifier:)]) {
[observer serviceManager:weakSelf didUpdateThingWithObjectID:objectID identifier:thing.identifier];
}
}];
if (completion) {
completion(nil);
}
}];
// And this massive monster
LoremIpsumAmetisyCellController *someCellController = [[LoremIpsumAmetisyCellController alloc] initWithTitle:thing.name
identifier:thing.identifier
thingosObjectID:thing.objectID
downloadEnabled:thing.downloadAllowed.boolValue
selectionBlock:^(UITableView *tableView, id<TableViewCellController> cellController) {
[weakSelf.delegate didSelectThingWithID:thing.objectID title:title];
}
downloadBlock:^(id<TableViewCellController> cellController) {
[weakSelf startDownloadThingWithID:thing.objectID cellController:cellController];
}];
// Line comments can have wrong alignment
if (condition) {
dispatch_group_t group = dispatch_group_create();
//get the lorem ipsum
thing = self.things.firstObject;
otherThing = self.otherThings.firstObject;
// Lorem ipsum blah blah
if (thing) {
dispatch_group_enter(group);
[thing getFullThingWithCompletionBlock:^(NSError *error) {
dispatch_group_leave(group);
}];
}
} else {
completionBlock(bError);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment