Git Product home page Git Product logo

spacecommander's Introduction

[ Space Commander]

[ Space Commander] provides tools which enable a team of iOS developers to commit Objective-C code to a git repository using a unified style format, without requiring any manual fixup.

Corgi image

You can use it to:

  • Enforce formatting conventions before code is committed.
  • Format code with a single command (both individual files or the entire repo).
  • Fail a build (during a pull request) if unformatted code made it into the branch.

At Square, [ Space Commander] has streamlined iOS development, especially when it comes to pull requests. Applying formatting standards no longer requires manual developer attention; that time is better spent elsewhere!

You may wish to fork [ Space Commander] to apply your team's particular set of formatting rules (more details below), or clone to enjoy Square's flavor of Objective-C formatting.

Installation Locally

To add formatting pre-commit checks to your repo, from the target repo, run path/to/spacecommander/setup-repo.sh.

Usage

After running setup-repo.sh, formatting checks will run automatically before every commit.

To format an individual file and modify it in place, run format-objc-file.sh <file>. To format it without modification, run format-objc-file-dry-run.sh <file>

To format all of the Objective-C files in your repository in-place, run format-objc-files-in-repo.sh.

Details

To install the pre-commit hook, each developer on the project runs the setup script. This installs a precommit hook which will verify that code is formatted before the commit succeeds.

If there were formatting errors during the commit, a script to fixup code automatically can be run in order to commit without error.

At Square, this formatting repository is referenced as a submodule of a larger iOS project, so that the formatting rules and scripts are locked to a revision of the parent repository. This way, we can check the formatting as part of the build process, and fail the build if the formatting is not current (we can also check out older SHAs without any difficulty).

clang-format expects the custom rules file to exist in the same directory that the command is run from, and so a .gitignore-d symlink of the rules file is added to the target repository. It is a symlink so that the developer only needs to update the git SHA of the formatting repository to get the latest formatting rules from upstream.

Configuration

To format files only within selected directories, specify the name each directory in a file named .formatting-directory, separated by newlines (and without whitespace escaped). Otherwise, all Objective-C files tracked in the repo will be checked.

To ignore files within directories, add the name of each directory on a new line to a file named .formatting-directory-ignore.

To modify the formatting output, edit the following:

  • .clang-format for built in clang-format options.
  • format-objc-file-dry-run.sh and format-objc-file.sh for rules that are implemented in custom/.
  • Testing Support/ files to validate your changes.

Add #pragma Formatter Exempt or // MARK: Formatter Exempt as the first line of the file if the formatter should ignore it.

Installation for Pull Request Validation

The following instructions are Square-specific. We use a build system called mobuild. The hook that we use, which can be integrated into other build systems, is format-objc-mobuild

If you want style checking as a mandatory step to get a mergeable PR, do the following:

  • Add this repository as a cocoapod, or add it as a submodule in a Scripts/ directory.
  • Ensure that your repository has setup .sqiosbuild.json and .stashkins files at the top level (more info on the Square wiki page titled All About Mobuild).
  • The build machines are setup to check for the above conditions, and if they're met, automatically run format-objc-mobuild.
  • Open a PR with a modified Objective-C file to verify these checks are running.

Updating Style Options

Change formatting policies by modifying .clang-format. Available style options are listed on the clang website.

Please also update UnformattedExample.m (under ./Testing Support/) with an example of code that your formatting changes should correct.

Then, update FormattedExample.m (in the same place) with the expected result, and verify that your changes produce the desired result by running a simple test: ./test.sh

Custom Formatters

clang-format is fantastic and we love it, but it has some limitations. We've added our own ad-hoc formatting capabilities through scripts which live in custom/. If you add a custom file formatting script to custom/, invoke it in format-objc-file.sh and format-objc-file-dry-run.sh and add examples of input / output to files in Testing Support/.

Undesired Result?

The formatter can't do everything. It may occasionally produce an undesirable result, in which case you can either:

  • Refactor code to produce a line that is simpler and less confusing to the formatter.
  • Use // clang-format off and // clang-format on to selectively enable/disable clang-format for specific lines of a file.
  • Add #pragma Formatter Exempt or // MARK: Formatter Exempt as the first line of the file, and it will not be formatted at all.
  • Wislawa Szymborska said "All imperfection is easier to tolerate if served up in small doses." [ Space Commander] will remove nearly all formatting imperfections, but you may need to tolerate an occasional deviation from the expected result.

Contributing

We’re glad you’re interested in [ Space Commander], and we’d love to see where you take it. Please read our contributing guidelines prior to submitting a Pull Request.

Thanks, and happy formatting!

spacecommander's People

Contributors

addoshi avatar alanf avatar dependabot[bot] avatar dfed avatar emablekos avatar ericmuller22 avatar garrefa avatar jamieq avatar justinseanmartin avatar ksuther avatar mikesilvis avatar notjosh avatar rhgills avatar segiddins avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spacecommander's Issues

Combination Anonymous Function declaration/call is broken up

 UIViewController *const modalToDismiss = ^UIViewController *{
            switch (container.presentationStyle) {
                case MQCardOnFileLinkingFlowViewPresentationStyleModal:
                    return self.currentModalViewController;

                case MQCardOnFileLinkingFlowViewPresentationStyleFullScreen:
                    return (self.currentModalViewController != self.fullScreenNavigationController) ? self.fullScreenNavigationController : nil;
            }
}();

becomes

 UIViewController *const modalToDismiss = ^UIViewController *
        {
            switch (container.presentationStyle) {
                case MQCardOnFileLinkingFlowViewPresentationStyleModal:
                    return self.currentModalViewController;

                case MQCardOnFileLinkingFlowViewPresentationStyleFullScreen:
                    return (self.currentModalViewController != self.fullScreenNavigationController) ? self.fullScreenNavigationController : nil;
            }
        }
        ();

SortIncludes: true breaks spacecommander?

I'm having an issue where if I have SortIncludes: true in my .clang-format file it will never consider the file properly formatted.

I see in this commit:
0b38808

That SortIncludes was set to false in the default .clang-format but we would prefer to continue using it.

Is this just not an option anymore?

Block inside container literal causes broken indentation

The following currently doesn't work correctly in space commander:

@implementation Example

- (void)callbackWithSuccess:(dispatch_block_t)success
{
    NSError *error = nil;
    [self createModelWithMapping:@{
        @"key": [NSArray ins_arrayWithCount:5 usingBlock:^__nullable id (NSUInteger idx) {
            return nil;
        }],
    } error:&error];
    if (success) {
        success();
    }
}

@end

Instead, it is formatted as:

@implementation Example

- (void)callbackWithSuccess:(dispatch_block_t)success
{
    NSError *error = nil;
    [self createModelWithMapping:@{
        @"key": [NSArray ins_arrayWithCount:5 usingBlock:^__nullable id (NSUInteger idx) {
            return nil;
}],
} error:&error];
if (success) {
    success();
}
}

@end

Is there a way to work around this? It seems to be a common use case, for example when defining Mantle value transformers.

Adds Unnecessary Semicolons

The formatter adds unneccessary semicolons to constructor arguments when they span multiple lines.

Steps to reproduce:

  1. I added spacecommander in as a git submodule in my repo.
  2. I added a pre install hook in my Podfile, and then looked at the diff.
pre_install do |installer|
  `./Libraries/spacecommander/format-objc-files-in-repo.sh`
end

screen shot 2015-06-27 at 7 33 08 pm

screen shot 2015-06-27 at 7 37 08 pm

Ignoring files

Is there any way to ignore files other than #pragma Formatter Exempt? I'm using protocol buffers which get recompiled on every build, would prefer to be able to ignore these files using a glob, e.g.: *.pbobjc.m.

Generics in category break indentation

Currently this:

@interface NSDictionary<__covariant KeyType, __covariant ObjectType> (INSScrub)

@property (readonly, copy) NSDictionary<KeyType, ObjectType> *ins_scrubbed;

@end

Becomes this:

@interface NSDictionary <__covariant KeyType, __covariant ObjectType>
(INSScrub)

    @property(readonly, copy) NSDictionary<KeyType, ObjectType> *ins_scrubbed;

@end

Tried removing break penalties from the clang-format config but it seems to be unrelated. When I remove the type signature from the interface it works as expected.

NS_SWIFT_NAME with getter: is formatted incorrectly

Given the following code in a header:

typedef NS_ENUM(NSUInteger, MyEnum) {
    MyEnumValueA,
    MyEnumValueB,
    MyEnumValueC,
};

extern NSString *MyEnumGetDescription(MyEnum value) NS_SWIFT_NAME(getter:MyEnum.description(self:));

running format-objc-file.sh will result in this:

typedef NS_ENUM(NSUInteger, MyEnum) {
    MyEnumValueA,
    MyEnumValueB,
    MyEnumValueC,
};

extern NSString *MyEnumGetDescription(MyEnum value) NS_SWIFT_NAME(getter
                                                                  : MyEnum.description(self:));

which is invalid, and throws a warning in Xcode:

'swift_name' attribute has invalid identifier for context name`

here's the .clang-format used when running against this code:

---
IndentNestedBlocks: false
AllowNewlineBeforeBlockParameter: false

Language:        Cpp
AccessModifierOffset: -1
ConstructorInitializerIndentWidth: 4
SortIncludes: false

AlignAfterOpenBracket: true
AlignEscapedNewlinesLeft: true
AlignOperands: false
AlignTrailingComments: true

AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortLoopsOnASingleLine: true

AlwaysBreakAfterDefinitionReturnType: false
AlwaysBreakTemplateDeclarations: false
AlwaysBreakBeforeMultilineStrings: false

BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false

BinPackArguments: true
BinPackParameters: true
ColumnLimit: 0
ConstructorInitializerAllOnOneLineOrOnePerLine: true
DerivePointerAlignment: false
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: true
IndentWrappedFunctionNames: false
IndentFunctionDeclarationAfterType: false
MaxEmptyLinesToKeep: 2
KeepEmptyLinesAtTheStartOfBlocks: false
NamespaceIndentation: Inner
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 10000
PenaltyBreakComment: 300
PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Right
SpacesBeforeTrailingComments: 1
Cpp11BracedListStyle: true
Standard:        Auto
IndentWidth:     4
TabWidth:        8
UseTab:          Never
BreakBeforeBraces: Custom
BraceWrapping: 
    AfterClass: true
    AfterControlStatement: false
    AfterEnum: false
    AfterFunction: true
    AfterNamespace: true
    AfterObjCDeclaration: true
    AfterStruct: false
    AfterUnion: false
    BeforeCatch: false
    BeforeElse: false
    IndentBraces: false

SpacesInParentheses: false
SpacesInSquareBrackets: false
SpacesInAngles:  false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpaceAfterCStyleCast: false
SpacesInContainerLiterals: true
SpaceBeforeAssignmentOperators: true

ContinuationIndentWidth: 4
CommentPragmas:  '^ IWYU pragma:'
ForEachMacros:   [ foreach, Q_FOREACH, BOOST_FOREACH ]
SpaceBeforeParens: ControlStatements
DisableFormat:   false
...

format-objc-files.sh -s nothing happened

After run git commit -a, I get this:

🚸 Format and stage individual files:
"/Users/aren/Documents/lollypop/spacecommander"/format-objc-file.sh 'lollypop-client-ios/femometer/femometer-client/thermometer/App/BMTAppDelegate.m' && git add 'lollypop-client-ios/femometer/femometer-client/thermometer/App/BMTAppDelegate.m';
🚀Format and stage all affected files:
"/Users/aren/Documents/lollypop/spacecommander"/format-objc-files.sh -s
🔴 There were formatting issues with this commit, run the👆 above👆 command to fix.
💔 Commit anyway and skip this check by running git commit --no-verify

It works when run format-objc-file.sh for one file, but nothing happen when run

"/Users/aren/Documents/lollypop/spacecommander"/format-objc-files.sh -s

Have I missed something?

please release 1.1.11 version

currently cocoapod main repository contains too old version - this repository contains more fresh one. Please update version in cocoapod repository

Ignoring Directories

Similar to this issue #5.

I have some directories in my project file that contain machine generated objective-c files and would want space commander to ignore those directories. Rather than listing all other directories in .formatting-directory, I'd like to be able to have an ignore list in say a .formatting-directory-ignore file.

I made a quick attempt at the script here:
master...addoshi:master

Let me know if this is something worth making a PR for. Thanks! :)

Formatting adds two newlines in header comment block

I was seeing an issue yesterday where running the formatter on this file:

https://github.com/st3fan/osx-10.9/blob/34e34a6a539b5a822cda4074e56a7ced9b57da71/IOKitUser-907.1.13/hid.subproj/IOHIDDevicePlugIn.h

It seems to always always add two more newlines in the comment block for IOHIDDeviceTransactionInterface. If run enough times, you get output that looks like:

471 /*!
472 
473 
474 
475 
476 
477 
478 
479 
480     @interface  IOHIDDeviceTransactionInterface
481     @abstract   The object you use to access a HID transaction from user space, returned by version 1.5 of the IOHIDFamily.
482     @discussion The functions listed here will work with any version of the IOHIDDeviceTransactionInterface. This functionality
483                 is useful when either setting or getting the values for multiple parsed elements.
484 */
485 typedef struct IOHIDDeviceTransactionInterface {
486     IUNKNOWN_C_GUTS;

Seems like a bug in the formatter, as the file is never clean and requires adding the formatter exempt comment.

Seemingly incorrect space in method signature.

Consider the following method signature:

+ (void)swapImplementationOf:(SEL)old with:(SEL)new
{
    // ...
}

For some reason the use of the word new triggers a space being inserted before it:

-+ (void)swapImplementationOf:(SEL)old with:(SEL)new
++ (void)swapImplementationOf:(SEL)old with:(SEL) new

This doesn’t seem to be a configurable option, so it appears to be a bug. I did a quick search through the codebase but couldn’t find anything related to new, so at least filing a ticket for now.

I’m working around it for now by renaming the parameter.

Run at compile-time?

Is it possible to run Space Commander in Xcode, possibly as a run script phase, to identify and address potential styling issues at compile-time rather than at the point of commit?

Not work quite right when format the Objective-C block

I've got my block formatted like this

[deviceManager syncDatasByIndexes:indexes finish:^{
[self doSomething]; // not formatted
}];

or this way:

[deviceManager syncDatasByIndexes:indexes
[deviceManager syncDatasByIndexes
                           finish:^{
  [self doSomething]; // not formatted
                           }];

Should I change the .clang-format "Language" value?
Or this feature hasn't supported yet?

Parameter after block literal confuses indentation

Possibly related to #40?

INSAFSuccessBlock INSAPIClientModelSuccessHandler(Class mantleClass, NSString *__nullable keyPath, INSHTTPSuccess __nullable success, INSHTTPFailure __nullable failure)
{
    return INSAPIClientModelSuccessChain(mantleClass, keyPath, ^(__kindof INSModel *model, id _) {
        if (success) {
            success(model);
        }
    }, failure);
}

Becomes:

INSAFSuccessBlock INSAPIClientModelSuccessHandler(Class mantleClass, NSString *__nullable keyPath, INSHTTPSuccess __nullable success, INSHTTPFailure __nullable failure)
{
    return INSAPIClientModelSuccessChain(mantleClass, keyPath, ^(__kindof INSModel *model, id _) {
        if (success) {
            success(model);
        }
    },
                                         failure);
}

I would prefer this not to be changed at all (i.e. not aligned), but the extraneous newline looks like a bug.

Don't remove trailing newline for function call

Is it possible to get spacecommander to respect this:

@import UIKit;

void main() {
    CGRect rect = CGRectMake(
        0.f,
        0.f,
        100.f,
        200.f
    );

    NSLog(@"%@", NSStringFromCGRect(rect));
}

Rather than converting it to this?

@import UIKit;

void main() {
    CGRect rect = CGRectMake(
        0.f,
        0.f,
        100.f,
        200.f);

    NSLog(@"%@", NSStringFromCGRect(rect));
}

This looks like a shortcoming with clang-format but not sure if it's possible to workaround with a script in spacecommander.

clang-format 3.8 and block indentation

A follow-up from #30 and #32. clang-format 3.7 and 3.8 have some pretty significant differences in how they do block formatting. The changes appear to be by design, but I disagree pretty strongly with the design (see also this clang Bugzilla bug). I've attached two files showing the difference between 3.7 and 3.8. 3.8 is extremely aggressive about block indentation, regardless of settings.

format-test-3.8.txt
format-test-3.7.txt

I made a custom build of clang-format that reverts or adds options for the behaviors that cause this change in block formatting behavior (my clang fork at https://github.com/ksuther/clang/tree/clang-format-customization and my spacecommander fork at flexibits@af9708b).

For anyone wondering "upgrade at all?" 3.7 has a number of bugs that have been fixed. The big one is that formatting inside blocks was broken in 3.7, and fixed in 3.8 (I believe this is what #30 is about). Some small ones that I've noticed in my own code have to do with Obj-C literals, handling casting inside Obj-C literals, and general handling of parentheses in Obj-C.

Uninstall?

What's the opposite of setup_repo.sh?

The Closing Bracket On Method Calls With A Block Argument Does Not Have Matching Indentation

If you have this block of code:

[system presentViewControllerWithClass:[TAFOutboundSearchResultsViewController class]
                    configurationBlock:^(TAFOutboundSearchResultsViewController *outboundSearchResultsViewController) {
// TODO: Fill In Code Here
}];

When you run the formatter, it converts the block of code to this:

[system presentViewControllerWithClass:[TAFOutboundSearchResultsViewController class]
                    configurationBlock:^(TAFOutboundSearchResultsViewController *outboundSearchResultsViewController) {
// TODO: Fill In Code Here
                    }];

screen shot 2015-06-30 at 1 52 07 pm

This issue existed in the past when I was just using a .clang-format file and the clang-format command-line tool, so I think fixing this is more of a feature request than an actual bug. Thanks again for fixing #10.

Can't detects new files

Step

  • Create a new file XXX.{h,m}
  • git add
  • format-objc-files-in-repo.sh

Spacecommander not detect the new files.

Directories with spaces in .formatting-directory being ignored

I can't tell if this is Bash witchcraft, or intended behaviour, or what.

Looking at https://github.com/square/spacecommander/blob/master/lib/common-lib.sh#L12, we see that directories_to_check() replaces spaces (' ') with escaped spaces ('\ ') via a sed command, which seems like a good idea Because Bash™.

BUT tracing the output, it seems that Bash will automatically quote the paths automatically (?!), and as such it will be looking for a string with a literal '\' in its path. Obviously it won't find that!

Detail

I've cut the .formatting-directory down to the following:

Clue/Tests
Clue/Clue WatchKit Extension

Then running the format-objc-files-in-repo.sh, I get the following output:

$ Submodules/spacecommander/format-objc-files-in-repo.sh
+ IFS='
'
++ date +%s
+ start_date=1446651719
+ export CDPATH=
+ CDPATH=
+++ dirname Submodules/spacecommander/format-objc-files-in-repo.sh
++ cd Submodules/spacecommander
++ pwd
+ DIR=/Users/joshua/dev/work/Clue/wheel-iOS/Submodules/spacecommander
+ source /Users/joshua/dev/work/Clue/wheel-iOS/Submodules/spacecommander/lib/common-lib.sh
++ IFS='
'
++ all_valid_objc_files_in_repo
++ directories_to_check
++ locations_to_diff=
++ '[' -e .formatting-directory ']'
+++ cat .formatting-directory
+++ sed 's/ /\\ /g'
++ locations_to_diff='Clue/Tests
Clue/Clue\ WatchKit\ Extension'
+++ git ls-tree --name-only --full-tree -r HEAD -- Clue/Tests 'Clue/Clue\ WatchKit\ Extension'
+++ grep -e '\.m$' -e '\.mm$' -e '\.h$' -e '\.hh$'
++ files='Clue/Tests/BWAPICredentialServiceTest.m
Clue/Tests/BWAPIRequestOperationManagerTest.m
Clue/Tests/BWAPIServiceTest.m
...
Clue/Tests/TagParsingTest.m'
++ grep -v Pods/
++ grep -v Carthage/
+ objc_files='Clue/Tests/BWAPICredentialServiceTest.m
Clue/Tests/BWAPIRequestOperationManagerTest.m
Clue/Tests/BWAPIServiceTest.mtionManagerTest.m
Clue/Tests/BWAPIServiceTest.m
...
Clue/Tests/TagParsingTest.m'
+ '[' -z 'Clue/Tests/BWAPICredentialServiceTest.m
Clue/Tests/BWAPIRequestOperationManagerTest.m
Clue/Tests/BWAPIServiceTest.m
...
Clue/Tests/TagParsingTest.m' ']'
...
+ '[' -z '' ']'
++ date +%s
+ end_date=1446651719
+ time_diff=0
+ echo '0 minutes and 0 seconds to format objc.'
0 minutes and 0 seconds to format objc.
+ exit 0

Specifically the lines:

++ locations_to_diff='Clue/Tests
Clue/Clue\ WatchKit\ Extension'
+++ git ls-tree --name-only --full-tree -r HEAD -- Clue/Tests 'Clue/Clue\ WatchKit\ Extension'

See the escaping in the quoted string? That's not the best of situations 🐊

The fix I'm using, but I can't tell if it's a totally stupid idea (or else I'd send a PR!) is to remove the sed, and then I get the output as expected:

...
++ '[' -e .formatting-directory ']'
+++ cat .formatting-directory
++ locations_to_diff='Clue/Tests
Clue/Clue WatchKit Extension'
+++ git ls-tree --name-only --full-tree -r HEAD -- Clue/Tests 'Clue/Clue WatchKit Extension'
...
++ files='Clue/Clue WatchKit Extension/BWWKEApplication.h
Clue/Clue WatchKit Extension/BWWKEApplication.m
Clue/Tests/BWAPICredentialServiceTest.m
Clue/Tests/BWAPIRequestOperationManagerTest.m
...

So basically..

Can we drop that sed command and trust Bash to do the Right Thing™? Is that a flag option, a version thing, an OS thing?

Automatic formatting

Space Commander is great, but one downside I found is that I have to manually execute commands from a terminal to fix formatting problems. Even though it tells me which command to run I still need to copy and paste it into the terminal (or type manually).

Is there a less painful way of using Space Commander, e.g. a GUI or Xcode plugin?

Running it as a build step is one option, however, it destroys your undo history inside Xcode: if you hit Build and Xcode reloads your file you can't use undo.

format-objc-hook should be using `diff -q`

In this line, we should be using diff -q instead. It returns on the first difference, doesn't need to construct a "diff", and is subsequently much faster.

difference=$("$DIR"/format-objc-file-dry-run.sh "$file" | diff "$file" - | wc -l)

Formatting breaks code

This:

        NSDateComponents *todayComp = [calendar components:(NSCalendarUnitYear |
                                                            NSCalendarUnitMonth |
                                                            NSCalendarUnitDay |
                                                            NSCalendarUnitWeekday |
                                                            NSCalendarUnitHour |
                                                            NSCalendarUnitMinute |
                                                            NSCalendarUnitSecond)
                                                  fromDate:today];

gets formatted into this:

        NSDateComponents *todayComp = [calendar components:(NSCalendarUnitYear |
                                                            NSCalendarUnitMonth |
                                                            NSCalendarUnitDay |
                                                            NSCalendarUnitWeekday |
                                                            NSCalendarUnitHour |
                                                            NSCalendarUnitMinute |
                                                            NSCalendarUnitSecond);
                                                  fromDate:today];

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.