├── .github └── PULL_REQUEST_TEMPLATE.md └── README.md /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### 概要 2 | _PRで対応した内容を記載する_ 3 | 4 | ### 対応リスト 5 | - [ ] 対応リスト1 6 | - [ ] 対応リスト2 7 | 8 | ### 更新内容 9 | #### 新規追加 10 | _旧バージョンから追加になった項目について記載する_ 11 | 12 | #### 変更 13 | _旧バージョンから変更になった項目について記載する_ 14 | 15 | ### 特記事項 16 | - ◯◯ 17 | - ◯◯ 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swiftコーディング規約 2 | 3 | # バージョン 4 | v3.0.0 5 | Swift 4 対応版 6 | 7 | # 目次 8 | 9 | - [はじめに](#はじめに) 10 | - [命名規則](#命名規則) 11 | - [ファイルフォーマット](#ファイルフォーマット) 12 | - [アクセス制御](#アクセス制御) 13 | - [クラス](#クラス) 14 | - [プロパティ](#プロパティ) 15 | - [変数](#変数) 16 | - [型](#型) 17 | - [制御](#制御) 18 | - [演算子](#演算子) 19 | - [エラーハンドリング・オプショナル](#エラーハンドリング・オプショナル) 20 | - [クロージャー](#クロージャー) 21 | - [不要なコード削除](#不要なコード削除) 22 | - [ジェネリクス](#ジェネリクス) 23 | - [メモリ管理](#メモリ管理) 24 | - [規約外とした項目](#規約外とした項目) 25 | 26 | # はじめに 27 | 28 | このコーディング規約は以下を方針として策定しています。 29 | - 一貫性 30 | - 可読性 31 | - 冗長性の排除 32 | 33 | # 命名規則 34 | 35 | ## クラス・構造体・列挙体・プロトコル・ジェネリクスの型パラメータ 36 | キャメルケースとし、先頭を大文字とすること。 37 | (UpperCamelCase) 38 | 39 | **理由** 40 | 41 | API Design Guidelinesに従う。 42 | 43 | **例** 44 | 45 | 良い例 46 | 47 | ```swift 48 | class SomeClass { 49 | ... 50 | } 51 | 52 | enum SomeEnum { 53 | ... 54 | } 55 | 56 | struct SomeStruct { 57 | typealias Element = String 58 | 59 | ... 60 | } 61 | 62 | protocol SomeProtocol { 63 | associatedtype Parameter 64 | 65 | ... 66 | } 67 | ``` 68 | 69 | 悪い例 70 | 71 | ```swift 72 | class someClass { 73 | ... 74 | } 75 | 76 | enum someEnum { 77 | ... 78 | } 79 | 80 | struct someStruct { 81 | typealias element = String 82 | 83 | ... 84 | } 85 | 86 | protocol someProtocol { 87 | associatedtype parameter 88 | 89 | ... 90 | } 91 | ``` 92 | 93 | ## 変数・メソッド・enumのcase 94 | キャメルケースとし、先頭は小文字とすること。 95 | (lowerCamelCase) 96 | 97 | **理由** 98 | 99 | API Design Guidelinesに従う。 100 | 101 | **例** 102 | 103 | 良い例 104 | 105 | ```swift 106 | struct SomeStruct { 107 | 108 | let someNumberProperty: Int 109 | 110 | func someMethod() -> String { 111 | ... 112 | } 113 | } 114 | 115 | enum SomeEnum { 116 | 117 | case red 118 | case green 119 | case blue 120 | 121 | ... 122 | } 123 | ``` 124 | 125 | 悪い例 126 | 127 | ```swift 128 | struct SomeStruct { 129 | 130 | let SomeNumberProperty: Int 131 | 132 | func SomeMethod() -> String { 133 | ... 134 | } 135 | } 136 | 137 | enum SomeEnum { 138 | 139 | case Red 140 | case Green 141 | case Blue 142 | 143 | ... 144 | } 145 | ``` 146 | 147 | ## クラス名 148 | クラス名にプレフィックスは付けない。 149 | 150 | **理由** 151 | 152 | Swiftでは名前空間が存在するためクラス名は衝突せず、ただ可読性を下げてしまうため。 153 | 154 | **例** 155 | 156 | 良い例 157 | 158 | ```swift 159 | class SomeClass { 160 | 161 | ... 162 | } 163 | ``` 164 | 165 | 悪い例 166 | 167 | ```swift 168 | class STVSomeClass { 169 | 170 | ... 171 | } 172 | ``` 173 | 174 | ## 頭文字語 175 | すべて大文字またはすべて小文字とすること。 176 | 177 | **理由** 178 | 179 | API Design Guidelinesに従う。 180 | 181 | **例** 182 | 183 | ```swift 184 | let url: URL = ... 185 | let thumbnailURL: URL = ... 186 | 187 | let id: String = ... 188 | let userID: String = ... 189 | ``` 190 | 191 | ## urlとdateの命名 192 | URL型の場合○○URLを使い、String型であれば○○URLStringとする。 193 | 同様にDate型の場合○○Dateを使い、String型であれば○○DateStringとする。 194 | 195 | **理由** 196 | 197 | 混同しやすいため。 198 | 199 | **例** 200 | 201 | 良い例 202 | 203 | ```swift 204 | var thumbnailURL: URL 205 | var imageURLString: String 206 | var lastUpdateDate: Date 207 | var birthdayString: String 208 | ``` 209 | 210 | 悪い例 211 | 212 | ```swift 213 | var thumbnailURL: String 214 | var lastUpdateDate: String 215 | ``` 216 | 217 | ## extensionのファイル名 218 | extensionのみのファイル名は**UIView+○○(機能名).swift**とすること。 219 | 加えて、extensionは機能単位でグルーピングすること。 220 | 221 | **理由** 222 | 223 | extensionであることを明確にするため。 224 | 機能ごとにextensionを作り、可読性をあげるため。 225 | 226 | **良い例** 227 | 228 | UIView+Border.swift 229 | 230 | ```swift 231 | extension UIView { 232 | 233 | @IBInspectable 234 | var cornerRadius: CGFloat { 235 | get { 236 | return layer.cornerRadius 237 | } 238 | set { 239 | layer.cornerRadius = newValue 240 | layer.masksToBounds = newValue > 0 241 | } 242 | } 243 | 244 | @IBInspectable 245 | var borderWidth: CGFloat { 246 | get { 247 | return layer.borderWidth 248 | } 249 | set { 250 | layer.borderWidth = newValue 251 | } 252 | } 253 | 254 | @IBInspectable 255 | var borderColor: UIColor? { 256 | get { 257 | return layer.borderColor.map { UIColor(cgColor: $0) } 258 | } 259 | set { 260 | layer.borderColor = newValue?.cgColor 261 | } 262 | } 263 | } 264 | ``` 265 | 266 | 悪い例 267 | 268 | Border.swift 269 | 270 | ```swift 271 | extension UIView { 272 | 273 | @IBInspectable 274 | var borderColor: UIColor? { 275 | get { 276 | return layer.borderColor.map { UIColor(cgColor: $0) } 277 | } 278 | set { 279 | layer.borderColor = newValue?.cgColor 280 | } 281 | } 282 | 283 | // ↓↓関係ない 284 | var hasSubview: Bool { 285 | return !subviews.isEmpty 286 | } 287 | } 288 | ``` 289 | 290 | ## その他 291 | その他命名に関しては、[API Design Guidelines](https://swift.org/documentation/api-design-guidelines/)を参考にすること。 292 | 以下は*Fundamentals*からの引用です。 293 | 294 | > ・**利用の観点から、明確さ**が最大の目標である。 295 | > メソッドやプロパティなどのエンティティは、一度だけ定義され、何度も使われるものである。 296 | > これらを利用する際、明確かつ簡潔であるようにAPIを設計しなければならない。 297 | > APIの評価をする際は、定義を読むだけでは不十分である。 298 | > コンテキスト上で明確であるよう、APIを使っている例も含めて評価しなければならない。 299 | 300 | > ・**明確さは簡潔さよりも重要である。** 301 | > Swiftのコードは短く書くことができるが、できるだけ少ない文字数で 302 | > 可能な限り最小のコードを実現することが目標ではない。 303 | > Swiftにおける簡潔さは 304 | > 強力な型システムと自然にボイラープレートコードを減らすことができる性質から生まれた、 305 | > 副次的なものである。 306 | 307 | > ・すべての宣言に**ドキュメントとしてコメント**を記載すること。 308 | > ドキュメントを書くことで得られる洞察は設計上に大きな影響をあたえるので、 309 | > 端折らないこと。 310 | 311 | # ファイルフォーマット 312 | 313 | ## ファイル内の順序 314 | 以下の順に書くこと。 315 | extensionを使い、関連メソッドをグルーピングするのは任意とする。 316 | 317 | ```swift 318 | // 1.import 319 | import UIKit 320 | 321 | // 2.protocol 322 | protocol ViewControllerDelegate { 323 | 324 | } 325 | 326 | // 3.class・struct・enum 327 | final class ViewController: UIViewController { 328 | 329 | // 4.typealias 330 | // 5.Inner class, enum & struct 331 | 332 | // 6.property 333 | // 334 | // open → public → internal → fileprivate → private 335 | // 336 | // 6-1.static member 337 | // | 338 | // | 6-1-1.let 339 | // | 340 | // | 6-1-2.var 341 | // | 342 | // | 6-1-3.computed var 343 | // 344 | // 6-2.instance member 345 | // | 346 | // | 6-2-1.@~ 347 | // | 348 | // | 6-2-2.let 349 | // | 350 | // | 6-2-3.var 351 | // | 352 | // | 6-2-3.computed var 353 | 354 | // 7.method 355 | // 356 | // open → public → internal → fileprivate → private 357 | // 358 | // 7-1.static member 359 | // 360 | // 7-2.instance member 361 | // | 362 | // | 7-2-1.init 363 | // | 364 | // | 7-2-2.life cycle 365 | // | 366 | // | 7-2-3.@~ 367 | // | 368 | // | 7-2-3.others 369 | 370 | } 371 | 372 | // 8.extension 373 | extension ViewController: UITableViewDelegate { 374 | 375 | } 376 | ``` 377 | 378 | **理由** 379 | 380 | 書く順序を統一することで、参照したい情報へのアクセスを効率的にする。 381 | 382 | ## 変数宣言時の修飾子の順序 383 | 以下の順に書くこと。 384 | 385 | @~ 386 | ↓ 387 | アクセス制御 388 | ↓ 389 | static, class 390 | ↓ 391 | dynamic, lazy, weak 392 | ↓ 393 | let, var 394 | 395 | **理由** 396 | 397 | 統一のため。 398 | 399 | ## import文の順序 400 | 以下の順に書くこと。 401 | 402 | フレームワーク 403 | ↓ 404 | ライブラリ 405 | 406 | また、同系列内ではアルファベット順に書くこと。 407 | 408 | **理由** 409 | 410 | コンフリクトを防止するため。 411 | 順序を揃えることで可読性を上げるため。 412 | 413 | ## スペース 414 | 415 | - ブラケットの前後には半角スペースを1つおくこと。 416 | - メソッドの戻り値の->の前後に半角スペースを1つおくこと。 417 | - コロンの前はスペースを入れず、コロンの後ろに1つスペースをいれること。(三項演算子を除く) 418 | - カンマの前にはスペースを入れず、カンマの後ろに1つスペースをいれること。 419 | - 演算子の実装の際は演算子の後ろに1つスペースをおくこと。 420 | 421 | **理由** 422 | 423 | 一貫性を持たせるため。 424 | 425 | **例** 426 | 427 | 良い例 428 | 429 | ```swift 430 | func something() -> Int { 431 | let some: Int = 0 432 | } 433 | 434 | func <| (lhs: Int, rhs: Int) -> Int 435 | func <|< (lhs: A, rhs: A) -> A 436 | ``` 437 | 438 | 悪い例 439 | 440 | ```swift 441 | func something()->Int{ 442 | let some :Int = 0 443 | } 444 | 445 | func <|(lhs: Int , rhs: Int)->Int 446 | func <|<(lhs: A,rhs: A)->A 447 | ``` 448 | 449 | ## プロトコルの実装 450 | ①ひとつのextensionで実装するプロトコルは1つとする。 451 | ②可能な限り継承よりもプロトコルを使用すること。 452 | 453 | **理由** 454 | 455 | ①関連メソッドをグルーピングすることで可読性を上げるため。 456 | ②継承は構造体で利用できないため。また、継承可能なのは1つのクラスのみであるのに対し、プロトコルは複数適用可能であるため。 457 | 458 | **例** 459 | 460 | 良い例 461 | 462 | ```swift 463 | class ViewController: UIViewController { 464 | ... 465 | } 466 | 467 | extension ViewController: UITableViewDataSource { 468 | ... 469 | } 470 | 471 | extension ViewController: UITableViewDelegate { 472 | ... 473 | } 474 | ``` 475 | 476 | 悪い例 477 | 478 | ```swift 479 | class ViewController: UIViewController, UITableViewDataSource { 480 | ... 481 | } 482 | ``` 483 | ```swift 484 | extension ViewController: UITableViewDataSource, UITableViewDelegate { 485 | ... 486 | } 487 | ``` 488 | 489 | ## enumの場所 490 | 広く使われるものであれば独立したファイルに宣言すること。 491 | ある構造に特有のものであればその構造内で宣言すること。 492 | 493 | **理由** 494 | 495 | enumのある場所を統一するため。 496 | 497 | ## 関数の宣言 498 | エディター上で折り返したら改行すること。 499 | また、改行をいれたらすべての引数の前で改行すること。 500 | 501 | **理由** 502 | 503 | 可読性を上げるため。 504 | 505 | ## セミコロンの使用禁止 506 | 行末のセミコロンの使用を禁止する。 507 | 508 | **理由** 509 | 510 | 必要ないため。 511 | 512 | ## 条件文の()の禁止 513 | 条件文を()で囲わないこと。 514 | 515 | **理由** 516 | 517 | 必要ないため。 518 | 519 | **例** 520 | 521 | 良い例 522 | 523 | ```swift 524 | if names.isEmpty { 525 | ... 526 | } 527 | ``` 528 | 529 | 悪い例 530 | 531 | ```swift 532 | if (names.isEmpty) { 533 | ... 534 | } 535 | ``` 536 | 537 | ## todo / fixmeの記載 538 | 未対応の機能には以下を記述すること。 539 | 540 | ```swift 541 | // TODO: 〜 542 | ``` 543 | 544 | 修正が必要な場合は以下を記述すること。 545 | 546 | ```swift 547 | // FIXME: 〜 548 | ``` 549 | 550 | **理由** 551 | 552 | 実装漏れを防止するため。 553 | 554 | # アクセス制御 555 | 556 | ## アクセス制御 557 | アクセス制御は可能な限りprivateを指定すること。 558 | 559 | **理由** 560 | 561 | そのクラス内、メソッド内…ということが担保でき、実装変更時の影響範囲を小さくできるため。 562 | 563 | # クラス 564 | 565 | ## final宣言 566 | 継承、オーバーライドをさせたくない場合は明示的にfinalを宣言すること。 567 | 568 | **理由** 569 | 570 | 継承、オーバーライド不可なことを明示的に示すことで設計意図を示せるため。 571 | また、副次的にパフォーマンス向上にも繋がるため。 572 | 573 | # プロパティ 574 | 575 | ## self.でのアクセス 576 | 必要な時にのみ使用すること。 577 | (引数と同じ名前のプロパティ、クロージャ内等) 578 | 579 | **理由** 580 | 581 | 統一し、また冗長性を排除するため。 582 | 583 | **例** 584 | 585 | 良い例 586 | 587 | ```swift 588 | struct Person { 589 | 590 | let name: String 591 | 592 | init(name: String) { 593 | self.name = name 594 | } 595 | 596 | func printName() { 597 | print(name) 598 | } 599 | 600 | let callback: () -> String = { 601 | return self.name 602 | } 603 | } 604 | ``` 605 | 606 | 悪い例 607 | 608 | ```swift 609 | struct Person { 610 | 611 | let name: String 612 | 613 | func printName() { 614 | print(self.name) 615 | } 616 | } 617 | ``` 618 | 619 | ## getクロージャの省略 620 | 算出型プロパティにおいて、ゲッターのみ定義する場合はgetのクロージャを省略すること。 621 | 622 | **理由** 623 | 624 | 不要なため。 625 | 626 | **例** 627 | 628 | 良い例 629 | 630 | ```swift 631 | class Person { 632 | 633 | let first: String 634 | let family: String 635 | 636 | var full: String = { 637 | return first + family 638 | } 639 | } 640 | ``` 641 | 642 | 悪い例 643 | 644 | ```swift 645 | class Person { 646 | 647 | let first: String 648 | let family: String 649 | 650 | var full: String = { 651 | get { 652 | return first + family 653 | } 654 | } 655 | } 656 | ``` 657 | 658 | # 変数 659 | 660 | ## 定数・変数の宣言 661 | var宣言を使用するのは、その値が変わり得る等、明確な理由があるときのみとする。 662 | それ以外の場合はlet宣言を使用する。 663 | 664 | **理由** 665 | 666 | より安全なコードにするため。 667 | 意図しない値の変更を防ぐため。 668 | 669 | letを使用することでプログラマーが値が変わらないことを確認することができる。 670 | 逆に、varによって宣言された変数が変更されることを予期できる。 671 | 672 | # 型 673 | 674 | ## 型推論 675 | 最大限利用すること。 676 | 677 | **理由** 678 | 679 | 冗長性を排除し、シンプルなコードにするため。 680 | 681 | **例** 682 | 683 | 良い例 684 | 685 | ```swift 686 | let name = "sample" 687 | 688 | let image = UIImage(named: "test") 689 | 690 | view.backgroundColor = .blue 691 | 692 | let view = UIView(frame: .zero) 693 | 694 | enum CustomResult { 695 | case Success 696 | case Error 697 | } 698 | var result: CustomResult? 699 | result = .Success 700 | 701 | let selector = #selector(viewWillAppear) 702 | 703 | ※数値を扱う場合は注意 704 | let int = 1 // Int型 705 | let double = 1.0 // Double型 706 | let float:Float = 1.0 // Float型にしたい場合は明記する 707 | ``` 708 | 709 | 悪い例 710 | 711 | ```swift 712 | let name: String = "sample" 713 | 714 | let image: UIImage = UIImage(named: "test")! 715 | 716 | view.backgroundColor = UIColor.blue 717 | 718 | let view = UIView(frame: CGRect.zero) 719 | 720 | enum CustomResult { 721 | case Success 722 | case Error 723 | } 724 | var result: CustomResult? 725 | result = CustomResult.Success 726 | 727 | let selector = #selector(ViewController.viewWillAppear) 728 | ``` 729 | 730 | ## 空配列・空辞書の初期化 731 | 空配列・空辞書の初期化の際は、型推論を利用した形で書くこと。 732 | 733 | **理由** 734 | 735 | 統一のため。 736 | 737 | **例** 738 | 739 | 良い例 740 | 741 | ```swift 742 | var names = [String]() 743 | var jsonDic = [String: Any]() 744 | ``` 745 | 746 | 悪い例 747 | 748 | ```swift 749 | var names: [String] = [] 750 | var jsonDic: [String: Any] = [:] 751 | ``` 752 | 753 | ## 糖衣構文の使用 754 | 糖衣構文がある場合はそちらを使用すること。 755 | Voidに関しては、可読性を理由に例外を認める。 756 | 757 | **理由** 758 | 759 | 統一のため。 760 | 761 | **例** 762 | 763 | 良い例 764 | 765 | ```swift 766 | var names: [String] 767 | var jsonDic: [String: Any] 768 | var title: String? 769 | var someClosure: () -> () 770 | ``` 771 | 772 | 悪い例 773 | 774 | ```swift 775 | var names: Array 776 | var jsonDic: Dictionary 777 | var title: Optional 778 | var someClosure: Void -> Void 779 | ``` 780 | 781 | ## Objective-Cクラスの扱い 782 | 文字列はNSString型でなく、String型を使用すること。 783 | また、文字列長判定にはcharacters.countを使用すること。 784 | 785 | NSNumber、NSArray、NSDictionary型も同様に、 786 | Swiftネイティブな型を利用すること。 787 | 788 | **理由** 789 | 790 | swiftの型で統一するため。 791 | 792 | # 制御構文 793 | 794 | ## 早期Return 795 | guard文を利用し、例外の場合に早めに制御を返すこと。 796 | 797 | **理由** 798 | 799 | guardにより制御が返ることを明示し、可読性を上げるため。 800 | また、ネストを減らすことで書きやすさ読みやすさを上げるため。 801 | 802 | **例** 803 | 804 | 良い例 805 | 806 | ```swift 807 | guard hogehoge else { 808 | return 809 | } 810 | ``` 811 | 812 | 悪い例 813 | 814 | ```swift 815 | if hogehoge { 816 | 817 | } else { 818 | return 819 | } 820 | ``` 821 | 822 | # エラーハンドリング・オプショナル 823 | 824 | ## Implicitly Unwrapped 型 825 | 利用をIBOutletに限定する。 826 | 827 | **理由** 828 | 829 | nilアクセスの可能性をできるだけ下げるため。 830 | 831 | ## アンラップ処理 832 | 833 | !(forced unwrap)を使わず、optional chaining, optional binding, nil coalescingを使用すること。 834 | また、optional bindingの際には、同じ変数名で変数宣言すること。 835 | 836 | **理由** 837 | 838 | nilアクセスの可能性をできるだけ下げるため。 839 | アンラップ前の変数を使ってしまうバグを防ぐため。 840 | 841 | **例** 842 | 843 | 良い例 844 | 845 | ```swift:GoodOptionalChaining.swift 846 | final class ViewController: UIViewController { 847 | override func viewDidLoad() { 848 | super.viewDidLoad() 849 | let navigationItem = navigationController?.navigationItem 850 | } 851 | } 852 | ``` 853 | 854 | ```swift:GoodOptionalBinding.swift 855 | let response: Any = [:] 856 | if let json = response as? [String: Any] { 857 | ... 858 | } 859 | ``` 860 | 861 | ```swift:GoodNilCoalescing.swift 862 | let someNumber: Int? = 10 863 | let otherNumber: Int = someNumber ?? 0 864 | ``` 865 | 866 | ```swift:GoodBindingNaming.swift 867 | if let some = some { 868 | ... 869 | } 870 | ``` 871 | 872 | 悪い例 873 | 874 | ```swift:BadOptionalChaining.swift 875 | final class ViewController: UIViewController { 876 | override func viewDidLoad() { 877 | super.viewDidLoad() 878 | let navigationItem = navigationController!.navigationItem 879 | } 880 | } 881 | ``` 882 | 883 | ```swift:BadOptionalBinding.swift 884 | let response: Any = [:] 885 | let json = response as! [String: Any] 886 | ``` 887 | 888 | ```swift:BadNilCoalescing.swift 889 | let someNumber: Int? = 10 890 | let otherNumber: Int = someNumber! 891 | ``` 892 | 893 | ```swift:BadBindingNaming.swift 894 | if let bindedSome = some { 895 | ... 896 | } 897 | ``` 898 | 899 | ## try~catch 900 | catchで例外を処理しない場合はtry!ではなく、try?を使用する。 901 | 902 | **理由** 903 | 904 | nilアクセスの可能性をできるだけ下げるため。 905 | 906 | **例** 907 | 908 | 良い例 909 | 910 | ```swift 911 | let someInt = try? someErrorThrowMethod() ?? 0 912 | ``` 913 | 914 | 悪い例 915 | 916 | ```swift 917 | let someInt = try! someErrorThrowMethod() 918 | ``` 919 | 920 | # クロージャー 921 | 922 | ## クロージャーの表記 923 | 924 | ①関数の最後の引数として関数にクロージャを渡す必要があって、かつクロージャが1つの場合には後置クロージャを使用する。 925 |  またクロージャ内のパラメータは明確に意味がわかるようにする。(一行で記述する場合に限り、引数名を省略すること。) 926 | ②クロージャが関数やメソッドの唯一の引数の場合は、関数名やメソッド名の後ろの()を省略する。 927 | ③後置クロージャを持つメソッドでメソッドチェーンで記述する場合は、スペースを入れる or 改行するで統一する。 928 | 929 | **理由** 930 | 931 | ①複数のクロージャを引数にもつ場合に後置クロージャを使用すると可読性が落ちるため。 932 |  複数行のクロージャ内で引数名を省略した場合に可読性が落ちるため。 933 |  複数のクロージャを引数にするメソッドの呼び出しでtrailingクロージャの省略形を使うと、外部引数名が省略され、 934 |  可読性が落ちるため。 935 | ②省略可能なため。 936 | ③実装者によって記述が異なることを防ぐため。 937 | 938 | **例** 939 | 940 | 良い例 941 | 942 | ```swift 943 | let someClosure: String -> Int? = { Int($0) } 944 | 945 | let someClosure: String -> Int? = { string in 946 | 947 | let intValue = Int(string) 948 | return intValue 949 | } 950 | 951 | UIView.animate(withDuration: 10.0) { 952 | print("animate") 953 | } 954 | 955 | UIView.animate(withDuration: 10.0, 956 | animations: { 957 | print("animate") 958 | }, 959 | completion: { _ in 960 | print("completed") 961 | }) 962 | 963 | let value = numbers.map {$0 * 2}.filter {$0 > 50}.map {$0 + 10} 964 | ``` 965 | 966 | 悪い例 967 | 968 | ```swift 969 | let someClosure: String -> Int? = { 970 | 971 | let intValue = Int($0) 972 | return intValue 973 | } 974 | 975 | UIView.animate(withDuration: 10.0, animations:{ 976 | print("animate") 977 | }) 978 | 979 | UIView.animate(withDuration: 10.0, 980 | animations: { 981 | print("animate") 982 | }) { _ in 983 | print("competed") 984 | } 985 | ``` 986 | 987 | # 不要なコード削除 988 | 989 | ## 不要なコードの削除 990 | テンプレートで実装されているメソッドやコメントで不要なコードは削除する 991 | 992 | **例** 993 | 994 | ```swift 995 | override func didReceiveMemoryWarning() { 996 | super.didReceiveMemoryWarning() 997 | // Dispose of any resources that can be recreated. 998 | } 999 | 1000 | ``` 1001 | 1002 | # ジェネリクス 1003 | 1004 | ## ジェネリクスの活用 1005 | 可能な限りジェネリクスを活用すること 1006 | 1007 | **理由** 1008 | 1009 | 汎用性が高まるため、またコード量を削減できるため。 1010 | 1011 | **例** 1012 | Tupleを作成するメソッド 1013 | 1014 | 良い例 1015 | 1016 | ```swift 1017 | 1018 | func makeTuple (a: T, b: T) -> (T, T) { 1019 | return (a, b) 1020 | } 1021 | 1022 | ``` 1023 | 1024 | 悪い例 1025 | 1026 | ```swift 1027 | 1028 | // Intの場合 1029 | func makeTuple (a: Int, b: Int) -> (Int, Int) { 1030 | return (a, b) 1031 | } 1032 | 1033 | // Stringの場合 1034 | func makeTuple (a: String, b: String) -> (String, String) { 1035 | return (a, b) 1036 | } 1037 | 1038 | ``` 1039 | 1040 | # メモリ管理 1041 | 1042 | ## 弱参照 1043 | 弱参照をする際にはunownedではなくweakを使用すること。 1044 | 1045 | **理由** 1046 | 1047 | nilアクセスの可能性をできるだけ下げるため。 1048 | 1049 | [weak self]・・・弱参照先がメモリ解放されている場合にnilになる(Optional型と同様にアンラップが必要) 1050 | [unowned self]・・・Optional型ではないため、弱参照先がメモリ解放されている場合にクラッシュする 1051 | 1052 | **例** 1053 | 1054 | 良い例 1055 | 1056 | ```swift 1057 | someFunc { [weak self] in 1058 | guard let weakSelf = self { 1059 | return 1060 | } 1061 | let sampleTuple = weakSelf.makeTuple(a: "A", b: "B") 1062 | print(sampleTuple) 1063 | ... 1064 | } 1065 | 1066 | someFunc { [weak self] in 1067 | if let weakSelf = self { 1068 | let sampleTuple = weakSelf.makeTuple(a: "A", b: "B") 1069 | print(sampleTuple) 1070 | } else { 1071 | print("Error") 1072 | } 1073 | ... 1074 | } 1075 | ``` 1076 | 1077 | 悪い例 1078 | 1079 | ```swift 1080 | someFunc { [weak self] in 1081 | let sampleTuple = self?.makeTuple(a: "A", b: "B") 1082 | print(sampleTuple!) 1083 | ... 1084 | } 1085 | 1086 | someFunc { [unowned self] in 1087 | ... 1088 | } 1089 | ``` 1090 | 1091 | # 規約外とした項目 1092 | 1093 | ## warningを解消する 1094 | warningを可能な限り解消すること。 1095 | 1096 | **却下理由** 1097 | 1098 | Xcodeに関する事項であり、コーディングの規約としては不適切と判断した。 1099 | 1100 | ## 関数型のメソッドに関する制約 1101 | 関数型の使用を制限する。 1102 | 1103 | **却下理由** 1104 | 1105 | プロジェクトごとに判断されるべきものであり、コーディング規約としては不適切と判断した。 1106 | 1107 | ## AutoLayoutに関する制約 1108 | AutoLayoutを使用する際に関する規約。 1109 | 1110 | **却下理由** 1111 | 1112 | 各プロジェクトに裁量を任せることとし、コーディング規約の対象外とした。 1113 | --------------------------------------------------------------------------------