Last active
November 10, 2015 11:43
-
-
Save mgrebenets/4bfda3e1d701ef053b87 to your computer and use it in GitHub Desktop.
Objective-C Code Formatting Sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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