@monoku/react-native-payments-stripe
Version:
React Native Payments add-on for processing payments with Stripe.
266 lines (167 loc) • 5.7 kB
Markdown
# Stripe iOS Objective-C Style Guide
## Ground Rules
### Spacing
- Indent using 4 spaces. No tabs.
- Avoid starting methods with an empty line
- There should not be a need to use multiple consecutive empty lines
- Asterisks should be attached to the variable name `NSString *text` unless it's `NSString * const Text`
### Variable Naming
- Lean towards clarity over compactness
- Avoid single letter variables. Try using `idx` / `jdx` instead of `i` / `j` in for loops.
- Prefer `urlString` over `URLString` (acronym prefix), `baseUrlString` over `baseURLString` (acronym infix), and `stripeId` over `stripeID` (acronym suffix)
### Control Flow
- Place `else if` and `else` on their own lines:
```objc
if (condition) {
// A
}
else if (condition) {
// B
}
else {
// C
}
```
- Always wrap conditional bodies with curly braces
- Use ternary operators sparingly and for simple conditions only:
```objc
type = isCard ? @"card" : @"unknown";
type = dictionary[@"type"] ?: @"default";
```
### Documentation
- Document using the multi-line syntax in all cases with the content aligned with the first asterisk:
```objc
/**
This is a one line description for a simple method
*/
- (void)title;
/**
This is a multi-line description for a complicated method
@param
@see https://...
*/
- (void)title;
```
### Literals
- Use literals to create immutable instances of `NSString`, `NSDictionary`, `NSArray`, `NSNumber`:
```objc
NSArray *brands = @[@"visa", @"mastercard", @"discover"];
NSDictionary *parameters = @{
@"currency": @"usd",
@"amount": @1000,
};
```
- Dictionary colons should be attached to the key
- Align multi-line literals using default Xcode indentation
### Constants
- Use static constants whenever appropriate. Names should start with a capital letter:
```objc
static NSString * const HTTPMethodGET = @"GET";
static const CGFloat ButtonHeight = 100.0;
```
- Any public static constants should be prefixed with `STP`:
```objc
static NSString * const STPSDKVersion = @"11.0.0";
```
### Folders
- We use flat folder structure on disk with some exceptions
- Save files to the appropriate root level folder. Typical folders include:
- `stripe-ios/Stripe/`
- `stripe-ios/Tests/Tests/`
- `stripe-ios/Example/Stripe iOS Example (Simple)/`
- `stripe-ios/Example/Stripe iOS Example (Custom)/`
- Save public header files in `stripe-ios/Stripe/PublicHeaders/` for Cocoapods compatibility
## Design Patterns
### Imports
- Ordering for imports in headers
- Import system frameworks
- Import superclasses and protocols sorted alphabetically
- Use `` for everything else
```objc
#import <Foundation/Foundation.h>
#import "STPAPIResponseDecodable.h"
#import "STPBankAccountParams.h"
STPAddress, ;
```
- Ordering for imports in implementations
- Import system frameworks
- Import corresponding headers
- Import everything else sorted alphabetically
```objc
#import <PassKit/PassKit.h>
#import "STPSource.h"
#import "STPSource+Private.h"
#import "NSDictionary+Stripe.h"
#import "STPSourceOwner.h"
#import "STPSourceReceiver.h"
#import "STPSourceRedirect.h"
#import "STPSourceVerification.h"
```
### Interfaces and Protocols
- Stick to Xcode default spacing for interfaces, categories, and protocols
- Always define `NS_ASSUME_NON_NULL_BEGIN` / `NS_ASSUME_NON_NULL_END` in headers
```objc
NS_ASSUME_NON_NULL_BEGIN
STPSourceProtocol <NSObject>
// ...
// ...
STPSource : NSObject<STPAPIResponseDecodable, STPSourceProtocol>
// ...
// ...
STPSource () <STPInternalAPIResponseDecodable>
// ...
NS_ASSUME_NON_NULL_END
```
- Category methods on certain classes need to be prefixed with `stp_` to avoid collision:
```
// NSDictionary+Stripe.h
NSDictionary (Stripe)
- (NSDictionary *)stp_jsonDictionary;
```
- Define private properties and methods as class extensions inside the implementation. Ex: `STPSource.m`.
- Define internal properties and methods as class extensions inside a `+Private.h` file. Ex: `STPSource+Private.h`.
- Access private properties and methods from test classes by defining a class extension inside the test implementation:
```
// STPBankAccountTest.m
STPBankAccount ()
+ (STPBankAccountStatus)statusFromString:(NSString *)string;
+ (NSString *)stringFromStatus:(STPBankAccountStatus)status;
STPBankAccountTest : XCTestCase
STPBankAccountTest
// ...
```
### Properties
- Properties should be defined using this syntax:
```
(<nonatomic / atomic>, <weak / copy / strong>, <nullable / _>, <readonly / readwrite>) <class> *<name>;
(<nonatomic / atomic>, <assign>, <readonly / readwrite>) <type> <name>;
```
- Use `copy` for classes with mutable counterparts such as `NSString`, `NSArray`, `NSDictionary`
- Leverage auto property synthesis whenever possible
- Declare `` and `` on separate lines for shorter diffs
### Init
```objc
- (instancetype)init {
self = [super init];
if (self) {
// ...
}
return self;
}
```
### Methods
- See [Coding Guidelines for Cocoa - Naming Methods](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingMethods.html#//apple_ref/doc/uid/20001282-BCIGIJJF)
### Implementation
- Use `#pragma mark - <text>` and `#pragma mark <text>` to group methods In large implementation files:
```objc
#pragma mark - Button Handlers
#pragma mark - UITableViewDataSource
#pragma mark - UITableViewDelegate
```