-
Notifications
You must be signed in to change notification settings - Fork 195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
revamped rule 2.5 + updated style guide for swift 3 #8
Conversation
@@ -682,24 +689,18 @@ doSomethingWithClosure() { response: NSURLResponse in | |||
[1, 2, 3].flatMap { String($0) } | |||
``` | |||
|
|||
* **3.8.2** When listing parameters, if using a capture list and/or specifying a (non-void) return type, wrap the parameter list in parentheses. Otherwise, the parentheses can be avoided. | |||
* **3.8.2** When listing parameters in a closure, wrap the parameter list in parentheses. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this a compiler error now? If so, we don't need this rule.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, removing.
``` | ||
|
||
* **3.8.3** If specifying a closure as a type, you don’t need to wrap it in parentheses unless it is required (e.g. if the type is optional or the closure is within another closure). Always wrap the arguments in the closure in a set of parentheses - use `()` to indicate no arguments and use `Void` to indicate that nothing is returned. | ||
|
||
```swift | ||
let completionBlock: (success: Bool) -> Void = { | ||
let completionBlock: (Bool) -> Void = { success in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't follow the rule from above, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is. The rule is talking about wrapping the entire declaration in parentheses, e.g. ((Bool -> Void)
instead of (Bool) -> Void
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I was talking about the parameter name before the in
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yes, my bad. Fixing!
|
||
```swift | ||
struct Error: ErrorType { | ||
struct Error: Swift.Error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like you should name this differently instead of Error
. Use like MyError
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was struggling to come up with a good name for this, since Error
works so well and anything else just seems extraneous. I wish Apple had kept this as ErrorType
or ErrorProtocol
=.
This works just fine if you just use Swift.Error
here instead however, and it lets you keep the good naming. None of the alternatives that I've considered (ErrorWithMessage
, DescriptiveError
, ErrorContainer
, Errrrroooorrrr
, etc.) seem to be as clean as just Error
.
This is especially useful when you want to namespace an error type within a class. For example:
class FileLoader {
enum Error: Swift.Error {
// ...
}
// V.S.
enum FileLoaderError: Error {
// ...
}
}
FileLoader.Error
is a far better than FileLoader.FileLoaderError
and fits more with the Swift API Guideline of avoiding needless words.
@@ -395,10 +402,10 @@ let lastName = name.lastName | |||
|
|||
* **3.1.5** Be wary of retain cycles when creating delegates/protocols for your classes; typically, these properties should be declared `weak`. | |||
|
|||
* **3.1.6** Be careful when calling `self` directly from a closure as this can cause a retain cycle - use a [capture list](https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-XID_163) when this might be the case: | |||
* **3.1.6** Be careful when calling `self` directly from an escaping closure as this can cause a retain cycle - use a [capture list](https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-XID_163) when this might be the case: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like we should probably add either another rule or something hear about preferring to always use non-escaping. And probably putting a link to something that explains what the differences are.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that might be useful, but it will be out of scope for this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we recommend not using [weak self] when it wouldn't be preventing a memory leak?
I think that instead of adding [weak self] everywhere just to be safe, it would be better to have people stop, pause, and think about the object graph and whether there would actually be a leak or not. By getting into the habit of thinking about cycles in object graphs, people would be more likely to notice leaks in other situations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@staguer We can address this separately since your comment is about the current rule whether we're using Swift 3 or not. Out of scope for this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good.
b42c17e
to
6da003d
Compare
|
||
// NOT PREFERRED | ||
static private let kMyPrivateNumber: Int | ||
static private let myPrivateNumber: Int | ||
``` | ||
|
||
* **3.2.2** The access modifier keyword should not be on a line by itself - keep it inline with what it is describing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we add something about @discardableResult and @testable being on the same or on their own lines?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, I agree that a rule about annotations might be useful, but it's not something new for Swift 3. We can talk about it separately.
@@ -710,19 +707,20 @@ let completionBlock: () -> Void = { | |||
let completionBlock: (() -> Void)? = nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't need the = nil default value, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's a local constant, you do need it. It only gets auto-initialized to nil
if it is a property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM after
@@ -514,6 +521,10 @@ class Pirate { | |||
let pirateName = "LeChuck" | |||
``` | |||
|
|||
* **3.2.5** Prefer `private` to `fileprivate` where possible. | |||
|
|||
* **3.2.6** When choosing between `public` and `open`, prefer `open` if you intend for something to be subclassable outside of a given module and `public` otherwise. Note that anything `internal` and above can be subclassed in tests by using `@testable import`, so this shouldn't be a reason to use `open`. In general, lean towards being a bit more liberal with using `open` when it comes to libraries, but a bit more conservative when it comes to a modules in a codebase such as an app where it is easy to change things in multiple modules simultaneously. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove "a" before modules.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
d'oh, fixed, thanks!
LGTM |
See changes in diff.
Rule 2.5 is a major difference; other changes are mainly updating code examples to fit with Swift 3.
Two other new rules: 3.2.5 and 3.2.6 about usage of
fileprivate
andopen
.