Swift 4.0 대 Swift 3.0 - 차이점 및 새로운 기능

게시 됨: 2021-10-05

Apple이 잘 알려진 Swift 언어의 새 버전을 출시하는 날이 마침내 우리를 강타했습니다. 우리는 그것으로부터 무엇을 기대해야 합니까? 떨리는 마음으로 Swift 4 버전에 포함될 새로운 업데이트에 대한 간략한 개요를 제공하기로 결정했습니다.

3 스위프트의 초석.

코드를 작성할 수 있는 환상적인 언어인 Swift는 자체적인 이점이 있으며 Objective-C 언어보다 "오래 산다"고 주장합니다.

Swift와 Objective-C의 주요 차이점에 대해 읽을 수 있습니다.

Swift는 빠르고 유형이 안전 하며 표현력이 뛰어납니다 . 그것은 전화와 태블릿, 데스크탑과 서버에 소프트웨어를 작성하는 데 사용될 수 있습니다. 분명히 코드를 실행하는 모든 것입니다. Apple의 Swift Playgrounds 코딩 방법 학습 앱을 사용하거나 Xcode에서 Playgrounds를 사용하면 즉시 작업 결과를 확인할 수 있습니다. 처음. 새로운 추가 버전이 있을 때마다 더 빠르고 빨라지며 Swift 4 버전의 경우도 마찬가지입니다.
안정적인 준비?

Xcode 9가 Swift 4에 대해 가지고 있는 또 다른 훌륭한 기능 - 다가오는 마이그레이션에 대해 크게 걱정할 필요가 없으며 이 기사를 읽으면서 그 이유를 알게 될 것입니다.

말하자면, 이번 가을에 우리에게 제공하는 봉봉과 Swift 4의 새로운 기능을 간략하게 살펴보겠습니다.

시작하기

언어 자체는  개발자 세계의 Xcode인 편리한 IDE 없이는 그다지 유용하지 않습니다. Mac App Store 또는 Apple 개발자 사이트의 다운로드 페이지에서 최신 버전의 Xcode 9를 다운로드할 수 있지만 먼저 활성 개발자 계정이 있는지 확인하십시오. 매우 안정적이어서 일상적인 코딩 루틴을 위해 Xcode 8을 대체할 수 있습니다.

xcversion을 사용하여 여러 버전의 Xcode를 설치할 수도 있습니다.

새 프로젝트를 시작하는 경우 시작하는 것이 좋습니다. 그러나 이미 Swift 3.x로 작성된 프로젝트가 있는 경우 마이그레이션 프로세스를 거쳐야 합니다.

새로운 기능에 익숙해지기 위해 먼저 Playground에서 시도하는 것이 좋습니다.

이 기사를 읽는 동안 'SE-____' 형식의 Swift Evolution 제안에 대한 링크를 확인할 수 있습니다.

스위프트 4로 마이그레이션

Swift의 한 주요 버전에서 다음 버전으로의 마이그레이션은 항상 매우 강렬했습니다. 특히 Swift 2.x에서 3.0으로의 마이그레이션은 더욱 그렇습니다. 일반적으로 프로젝트당 약 1-2일이 소요되지만 Swift 4로 마이그레이션하는 것이 조금 더 쉽고 훨씬 빠르게 전달할 수 있습니다.

사전 마이그레이션 준비

Xcode 9는 Swift 4뿐만 아니라 과도기 버전 3.2도 지원하므로 프로젝트는 큰 어려움 없이 컴파일되어야 합니다. 이것은 Swift 4 컴파일러와 마이그레이션 도구가 두 버전의 언어를 모두 지원하기 때문에 가능합니다. 대상마다 다른 Swift 버전을 지정할 수 있습니다. 이는 일부 타사 라이브러리가 아직 업데이트되지 않았거나 프로젝트에 여러 대상이 있는 경우에 매우 유용합니다. 그러나 언어뿐만 아니라 SDK에도 몇 가지 변경 사항이 있으므로 Apple이 SDK API를 계속 조정함에 따라 일부 업데이트가 코드에 적용되어야 할 가능성이 매우 큽니다...

신속한 마이그레이션 도구

항상 그렇듯이 Apple은 이전 Swift 버전에서 마이그레이션하는 데 도움이 되는 Xcode에 번들로 제공되는 Swift 마이그레이션 도구를 제공합니다. 편집 -> 변환 -> 현재 Swift 구문으로 이동 하고 변환할 대상을 선택하여 Xcode에서 실행할 수 있습니다.

어떤 Objective-C 추론 기본 설정을 적용할 것인지 묻는 메시지가 표시됩니다.

추가 변경 사항이 Swift 4에서 지배적이므로 Swift 마이그레이션 도구가 대부분의 변경 사항을 관리합니다.

코코아팟

대부분의  개발자는 프로젝트에 CocoaPods 종속성 관리자를 사용합니다. Swift Package Manager가 매우 빠르게 개선되기는 하지만 그만큼 성숙하지 않기 때문입니다. 위에서 언급했듯이 모든 타사 라이브러리가 아직 Swift 4로 업데이트된 것은 아니므로 일부를 컴파일하는 동안 오류가 발생할 수 있습니다. 이 문제를 해결할 수 있는 한 가지 가능한 솔루션은 Podfile post_install 스크립트를 추가하여 아직 업데이트되지 않은 해당 포드에 대해 Swift 버전 3.2 를 지정하는 것 Podfile .

 old_swift_3_pods = [ 'PodName1', 'PodName2', ] post_install do |installer| installer.pods_project.targets.each do |target| if old_swift_3_pods.include? target.name target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '3.2' end end end end

그런 다음 실행

 pod install

이제 오류 없이 포드를 컴파일할 수 있습니다.

Swift 4 API 변경 사항 및 추가 사항에 대해 살펴보겠습니다.

API 변경 및 추가

문자열

String 이제 SE-0163 제안 덕분에 Collection 프로토콜을 따릅니다. 스위프트 1.x를 기억하십니까?

String 직접 반복할 수 있으므로 이제 characters 배열 속성이 필요하지 않습니다.

 let string = "Hello, Mind Studios!" for character in string { print(character) }

이것은 또한 count , isEmpty , map() , filter() , index(of:) 등과 같은 String 에서 모든 Collection 메서드와 속성을 사용할 수 있음을 의미합니다.

 string.count // No more `string.characters.count` string.isEmpty // false let index = string.index(of: " ") // 6 let reversedCollection = "abc".reversed() let reversedString = String(reversedCollection) // "cba" // String filtering let string = "ni123n456iniASijasod! 78a9-kasd aosd0" let numbersString = string.filter { Int(String($0)) != nil } // "1234567890"

Substring 유형

Swift 4는 String Substring 시퀀스를 나타내는 새로운 Substring 유형을 제공합니다(위에 언급된 SE-0163에 설명된 대로).

 // Split string into substrings let string = "Hello, Mind Studios!" let parts = string.split(separator: " ") // ["Hello,", "Mind", "Studios!"] type(of: parts.first!) // Substring.Type

StringSubstring 이제 거의 동일하고 상호 운용 가능한 새로운 StringProtocol 을 지원합니다.

 var hello = parts.first! // Concatenate a String onto a Substring hello += " !" // "Hello, !" // Create a String from a Substring let helloDog = String(hello) // "Hello, !"

중요 사항

SE-0163에는 매우 중요한 메모가 있습니다.

 Long-term storage of `Substring` instances is discouraged. A substring holds a reference to the entire storage of a larger string, not just to the portion it presents, even after the original string's lifetime ends. Long-term storage of a substring may therefore prolong the lifetime of elements that are no longer otherwise accessible, which can appear to be memory leakage.

즉, SubstringString 하위 시퀀스의 임시 저장소로 사용하기 위한 것입니다. 일부 메소드 또는 다른 클래스에 전달하려면 먼저 String 변환하십시오.

 let substring: Substring = ... // Substring let string = String(substring) // String someMethod(string)

어쨌든, Swift의 유형 시스템은 String 이 예상되는 어딘가에 Substring 을 전달하지 않도록 도와줄 것입니다(새 StringProtocol 을 매개변수 유형으로 사용하지 않는다고 가정).

여러 줄 문자열 리터럴

SE-0168은 세 개의 큰따옴표 """ 를 사용하여 여러 줄 문자열 리터럴에 대한 간단한 구문을 도입했습니다. 이는 대부분의 텍스트 형식(예: JSON 또는 HTML) 또는 일부 긴 텍스트를 이스케이프 없이 붙여넣을 수 있음을 의미합니다.

 let multilineString = """ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam mattis lorem et leo laoreet fermentum. Mauris pretium enim ac mi tempor viverra et fermentum nisl. Sed diam nibh, posuere non lectus at, ornare bibendum erat. Fusce mattis sem ac feugiat vulputate. Morbi at nunc maximus, vestibulum orci et, dictum neque. Vestibulum vulputate augue ac libero vulputate vestibulum. Nullam blandit et sapien non fermentum. Proin mollis nisl at vulputate euismod. """

문자열 리터럴에서 줄 바꿈 이스케이프

SE-0182는 줄 끝에 백슬래시가 있는 여러 줄 문자열 리터럴에서 줄 바꿈을 이스케이프하는 기능을 추가합니다.

 let escapedNewline = """ Line 1, Line 2 \ next part of line 2, Line 3 """ print(escapedNewline)
 Line 1, Line 2 next part of line 2, Line 3

향상된 유니코드 지원

Swift 4는 유니코드 9에 대한 지원을 제공합니다. 즉, 유니코드 문자 계산 문제가 이제 사라졌습니다.

 "".count // 1, in Swift 3: 2 "".count // 1, in Swift 3: 2 "".count // 1, in Swift 3: 2 - person + skin tone "".count // 1, in Swift 3: 4 "".count // 3, in Swift 3: 1

위에서 강조한 모든 변경 사항 및 구현된 제안(다른 많은 것들과 마찬가지로)은 String Manifesto라고 하는 광범위하게 설명된 기능 집합에서 뿌리를 내리고 있습니다.

액세스 제어

Swift 3는 액세스 제어에 매우 모순된 요소를 가져왔습니다. 정말 혼란스러울 수 있는 fileprivate 액세스 수정자입니다.
이전에는 private 액세스 수준 수정자를 사용하여 다른 형식에서 형식 멤버를 숨기고 형식 정의에 정의된 메서드와 속성을 통해서만 private 멤버에 액세스할 수 있었습니다.
fileprivate 사용하여 동일한 파일 내에서 속성 및 메서드와 같은 형식 멤버에 대한 액세스를 공유할 수 있습니다.
사실 private 사용하면 어떤 유형의 확장이 해당 유형의 멤버에 액세스할 수 없을 때 문제가 발생하므로 이러한 상황에서 fileprivate 를 사용하는 것은 매우 일반적인 솔루션이었으며 이는 또 다른 문제로 이어졌습니다. 동일한 파일이 해당 구성원에도 액세스할 수 있습니다.

Swift 4는 SE-0169에 설명된 것과 같이 동일한 파일에서 해당 유형의 private 멤버에 액세스할 수 있도록 유형의 확장을 허용하여 모든 것을 정리합니다.

 struct User { private let firstName: String private let lastName: String } extension User: CustomStringConvertible { var description: String { return "User: \(firstName) \(lastName)" } }

사전 및 세트

Sequence Dictionary 초기화

Dictionary 은 이제 Sequence 로 초기화할 수 있지만 모든 시퀀스를 이 초기화에서 전달할 수 있는 것은 아니며 튜플 (Key, Value) 포함하는 시퀀스만 전달할 수 있습니다. 여기서 Key 는 사전의 키 유형이고 Value 는 사전 값 유형을 나타냅니다.

 let stocksIdentifiers = ["AAPL", "GOOGL", "NKE"] let stocksValues = [158.28, 940.13, 53.73] let pairs = zip(stocksIdentifiers, stocksValues) let stocksValuesDict = Dictionary(uniqueKeysWithValues: pairs) // ["GOOGL": 940.13, "NKE": 53.73, "AAPL": 158.28]

여기서 zip 함수는 2개의 시퀀스에서 쌍( Tuple )을 생성합니다. 이 함수에 대한 자세한 내용은 Swift 표준 라이브러리 문서에서 확인할 수 있습니다.

사전 병합

2개의 동일한 키의 값을 결합하는 데 사용되는 uniquingKeysWith 매개변수에 클로저를 전달하여 Tuple 시퀀스에서 사전을 생성할 때 중복 키를 처리하는 방법을 지정할 수 있습니다.

예 1:

 let duplicates = [("a", 1), ("b", 5), ("a", 3), ("b", 3)] let dictionary = Dictionary(duplicates, uniquingKeysWith: { (first, _) in return first }) // ["b": 5, "a": 1]

여기서 동일한 키를 가진 모든 다음 값을 무시하고 첫 번째 값을 그대로 둡니다.

예 2:

문자열에서 각 문자가 몇 번 나타나는지 계산합니다.

 let string = "Hello!" let pairs = Array(zip(string, repeatElement(1, count: string.count))) let counts = Dictionary(pairs, uniquingKeysWith: +) // ["H": 1, "e": 1, "o": 1, "l": 2, "!": 1]

예 3:

merge 방법 사용:

 let values = ["a": 1, "b": 5] var additionalValues = ["b": 3, "c": 2, "a": 3] additionalValues.merge(values, uniquingKeysWith: +) // ["b": 8, "c": 2, "a": 4]

기본값이 있는 첨자

이전에는 값이 nil인 경우 기본값을 제공하기 위해 nil 병합 연산자를 사용하는 것이 일반적이었습니다.

스위프트 3:

 let dict = ["a": 1, "b": 5] dict["c"] ?? 0 // 0

Swift 4는 아래 첨자(SE-0165의 일부)에 새로운 default 도입합니다.

 let dict = ["a": 1, "b": 5] dict["c", default: 0] // 0, equals to `dict["c"] ?? 0` in Swift 3

기본 값으로 첨자를 추가하는 동안 사전을 변경할 수도 있습니다.

 let string = """ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam mattis lorem et leo laoreet fermentum. Mauris pretium enim ac mi tempor viverra et fermentum nisl. Sed diam nibh, posuere non lectus at, ornare bibendum erat. Fusce mattis sem ac feugiat vulputate. Morbi at nunc maximus, vestibulum orci et, dictum neque. Vestibulum vulputate augue ac libero vulputate vestibulum. Nullam blandit et sapien non fermentum. Proin mollis nisl at vulputate euismod. """ var wordsCountByLine = [Int: Int]() let lines = string.split(separator: "\n") for (index, line) in lines.enumerated() { let lineWordsCount = line.split(separator: " ").count wordsCountByLine[index, default: 0] += lineWordsCount } print(wordsCountByLine) // [2: 10, 4: 15, 5: 7, 6: 6, 7: 6, 0: 8, 1: 7, 3: 10]

사전별 맵 및 필터

시퀀스 요소 그룹화

프로토콜의 제한된 관련 유형

제안 SE-0142는 관련 유형 선언에 조건절을 추가합니다.

 extension Sequence where Element: Numeric { var sum: Element { var result: Element = 0 for element in self { result += element } return result } } [1,2,3,4].sum

보관 및 직렬화(인코딩/디코딩)

이전에는 일부 사용자 정의 유형을 직렬화하려면 오래되고 잘 알려진 NSCoding 프로토콜을 사용해야 했습니다. 문제는 structenum 과 같은 비 클래스 유형이 이 프로토콜을 준수할 수 없으므로 개발자가 NSCoding 준수할 수 있는 중첩 클래스를 생성하여 추가 호환성 계층을 제공하는 것과 같은 해킹을 사용하는 것 외에는 할 일이 없다는 것입니다.

Swift 4는 SE-0166 덕분에 이 문제에 대한 매우 편리한 솔루션을 제공합니다 - Codable 프로토콜의 도입:

 struct Employee: Codable { let name: String let age: Int let role: Role enum Role: String, Codable { case manager case developer case admin } } struct Company { let name: String let officeLocation: Location? let employees: [Employee] } struct Location : Codable { let latitude: Double let longitude: Double }

이와 같은 간단한 경우에 필요한 것은 모든 사용자 정의 유형에 Codable 프로토콜 준수를 추가하는 것 Codable . 컴파일러는 모든 마법을 수행합니다. 그게 다야!

Codable A는 typealias 의 컴포지션 DecodableEncodable 당신은, 예를 들어, 단지 선언 할 수 있도록 프로토콜 Decodable 당신이 JSON 데이터에서 유형의 인스턴스를 해독하려면 프로토콜 준수.

부호화

Codable 값을 직렬화 또는 역직렬화하려면 인코더 또는 디코더 개체를 사용해야 합니다. Swift 4에는 인코딩/디코딩 중에 발생할 수 있는 다양한 유형의 오류에 대한 새로운 CocoaError 뿐만 아니라 JSON 및 속성 목록에 대한 인코더/디코더 세트가 이미 제공됩니다. NSKeyedArchiverNSKeyedUnarchiverCodable 유형도 지원합니다.

 let employee = Employee(name: "Peter", age: 27, role: .manager) let company = Company(name: "Awesome Company", officeLocation: nil, employees: [employee]) let encoder = JSONEncoder() let companyData = try encoder.encode(company) let string = String(data: companyData, encoding: .utf8)! print(string) >>> { "name" : "Awesome Company", "employees" : [ { "name" : "Peter", "age" : 27, "role" : "manager" } ] }

케이크 한 조각, 그렇죠?

디코딩

디코더는 Data 에서 사용자 정의 Codable 유형을 역직렬화하는 데 사용됩니다. 데이터 자체에서 디코딩할 유형을 모르므로 디코딩할 유형을 지정해야 합니다(예: Employee 또는 [Employee] .

 let decoder = JSONDecoder() let jsonData = """ [ { "name" : "Peter", "age" : 27, "role" : "manager" }, { "name" : "Alex", "age" : 26, "role" : "developer" }, { "name" : "Eugene", "age" : 30, "role" : "admin" } ] """.data(using: .utf8)! let employees = try decoder.decode([Employee].self, from: jsonData)
 If one of `Codable` type instances fails to decode, then whole collection will fail to decode.

사용자 지정 키 이름

대부분의 경우 사용자 정의 Swift 유형에서 사용하는 이름은 이 유형을 나타내는 JSON 데이터의 키와 일치하지 않습니다. 당신이 중첩 열거 이름을 만들 수있는 사용자 정의 형 속성 이름과 JSON 키 사이의 매핑 만들려면 CodingKeys 준수해야 CodingKey 프로토콜 :

 struct Country: Decodable { let id: String let name: String let phoneCode: String private enum CodingKeys: String, CodingKey { case id = "alpha3" case name case phoneCode = "phone_code" } }

사용자 정의 디코딩

복잡한 경우에는 Decodable 프로토콜에서 사용자 정의 이니셜라이저를 구현할 수 있습니다.

 struct Transaction { let id: Int let action: String let source: String let amount: Int let state: TransactionState let createdAt: Date let authorName: String enum TransactionState: String, Decodable { case done case canceled case processed } } extension Transaction: Decodable { private enum CodingKeys: String, CodingKey { case id case action = "action_name" case source = "source_name" case amount case state case createdAt = "created_at" case author } private enum AuthorKeys: String, CodingKey { case fullName = "full_name" } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decode(Int.self, forKey: .id) actionName = try container.decode(String.self, forKey: .action) sourceName = try container.decode(String.self, forKey: .source) let createdAtValue = try container.decode(Double.self, forKey: .createdAt) createdAt = Date(timeIntervalSince1970: createdAtValue) state = try container.decode(TransactionState.self, forKey: .state) amount = try container.decodeIfPresent(Int.self, forKey: .amount) ?? 0 do { let authorContainer = try container.nestedContainer(keyedBy: AuthorKeys.self, forKey: .author) authorName = try authorContainer.decode(String.self, forKey: .fullName) } catch { authorName = "" } } }

키 값 코딩

Swift 4가 제공하는 편리한 기능 중 하나는 SE-0161에 설명된 Smart KeyPaths입니다. 강력하게 형식화되지 않고 Objective-C 멤버에 대해서만 작동하는 Swift 3 #keyPath() 와 달리 Swift 4 #keyPath() 는 일반 클래스입니다. 즉, 이제 키 경로가 강력하게 형식화됩니다. 몇 가지 예를 살펴보겠습니다.

 struct User { var username: String }

키 경로 \<Type>.<path> 의 일반 형식, 여기서 <Type> 은 유형 이름이고 <path> 는 하나 이상의 속성 체인입니다(예: \User.username :

 let user = User(username: "max") let username = user[keyPath: \User.username] // "max"

변경 가능한 경우 이 키 경로로 새 값을 작성할 수도 있습니다.

 var user = User(username: "max") user[keyPath: \User.username] = "alex" // "alex"

키 경로는 계층 구조의 한 수준으로 제한되지 않습니다.

 struct Comment { let content: String var author: User } let max = User(username: "max") let comment = Comment(content: "Nice post!", author: max) let authorUsername = comment[keyPath: \Comment.author.username] // "max"

키 경로는 변수에 저장할 수 있습니다.

 let authorKeyPath = \Comment.author let usernameKeyPath = authorKeyPath.appending(path: \.username) let authorUsername = comment[keyPath: usernameKeyPath] // "max"

선택적 속성과 계산 속성에 키 경로를 사용할 수도 있습니다.

 struct Post { let title: String var comments: [Comment] var topComment: Comment? { return comments.first } } let max = User(username: "max") let alex = User(username: "alex") var post = Post(title: "What's new in Swift 4", comments: []) let topCommentAuthorUsernameKeyPath = \Post.topComment?.author.username post[keyPath: topCommentAuthorUsernameKeyPath] // nil let comment = Comment(content: "", author: alex) let anotherComment = Comment(content: "Nice post!", author: max) post.comments = [comment, anotherComment] post[keyPath: topCommentAuthorUsernameKeyPath] // "alex"

SE-0161 하이라이트가 주요 경로의 첨자를 지원함에도 불구하고 아직 구현되지 않았습니다.

 post.comments[keyPath: \.[0].content] // error: key path support for subscript components is not implemented let firstCommentAuthorKeyPath = \Post.comments[0].author // error: key path support for subscript components is not implemented

KVO

새로운 키 경로 외에도 키-값 관찰 API가 Swift 4에서도 업데이트되었습니다.

 New KVO APIs depend on Objective-C runtime and works for `NSObject` subclasses only, so it can't be used for Swift structs and classes which don't inherit `NSObject`. In order to observe property it should be marked as `@objc dynamic var`.
 class User: NSObject { @objc dynamic var name: String var username: String init(name: String, username: String) { self.name = name self.userName = userName super.init() } } let user = User(name: "Max", username: "max") let nameObservation = user.observe(\.name, options: [.new, .old]) { user, change in // NSKeyValueObservation if let oldValue = change.oldValue, let newValue = change.newValue { print("fullName has changed from \(oldValue) to \(newValue)") } else { print("fullName is now \(user.name)") } } user.name = "Alex" // name has changed from Max to Alex

관찰을 중지하려면 invalidate() 메서드를 호출하십시오.

 nameObservation.invalidate() user.name = "Elina" // observer isn't get called

초기화 시에도 정지되오니 보관을 원하실 경우 반드시 사유지나 다른 곳에 보관해 두시기 바랍니다.

단측 범위

SE-0172는 기존 범위 연산자의 접두사/후위 버전을 통해 생성된 "단측" 범위와 다양한 종류의 범위를 사용하는 메서드 생성을 단순화하는 새로운 RangeExpression 프로토콜을 RangeExpression 합니다.

무한 시퀀스

단측 범위를 사용하여 무한 시퀀스를 구성할 수 있습니다.

 let letters = ["a", "b", "c", "d"] let numberedLetters = Array(zip(1..., letters)) // [(1, "a"), (2, "b"), (3, "c"), (4, "d")]
 let string = "Hello, Mind Studios!" let index = string.index(of: ",")! string[..<index] // "Hello" string[...index] // "Hello,"

패턴 일치에서 단측 범위 사용

 let value = 5 switch value { case 1...: print("greater than zero") case 0: print("zero") case ..<0: print("less than zero") default: break }

일반 첨자

SE-0148 첨자는 이제 일반 인수 및 반환 유형을 가질 수 있습니다.

 struct JSON { let data: [String: Any] subscript<T>(key: String) -> T? { return data[key] as? T } } let jsonDictionary: [String: Any] = [ "name": "Ukraine", "flag": "", "population": 42_500_000 ] let json = JSON(data: jsonDictionary) let population: Int? = json["population"] // 42500600
 extension Dictionary where Value == String { subscript<T: RawRepresentable>(key: Key) -> T? where T.RawValue == Value { guard let string = self[key] else { return nil } return T(rawValue: string) } } enum Color: String { case red case green case blue } let dictionary = [1: "red"] let color: Color? = dictionary[1] // red

Objective-C 추론 제한

Swift 4는 Objective-C(SE-0160)에서 선언을 사용할 수 있어야 하는 경우에만 @objc 추론을 제한하여 최소화합니다.
이렇게 하면 사용하지 않는 경우 중복 Objective-C 코드를 컴파일하지 않아 앱의 바이너리 크기가 줄어들고 @objc가 유추되는 시기를 더 잘 제어할 수 있습니다. NSObject 파생 클래스는 더 이상 @objc를 유추하지 않습니다.

그러나 Swift 코드가 계속해서 암시적 추론을 하는 몇 가지 상황이 있습니다.

  • @objc 속성이 있는 선언

  • @objc 프로토콜의 요구 사항을 충족하는 선언

  • @IBAction, @IBInspectable, @IBOutlet, @NSManaged, @GKInspectable 속성이 있는 선언

전체 클래스에 대해 @objc 추론을 활성화하려면 새로운 @objcmembers 속성을 사용할 수 있습니다.
특정 확장 또는 기능에 대한 @objc 추론을 비활성화하려면 새로운 @nonobjc 속성을 추가하십시오.

클래스 및 프로토콜 작성

Swift 4에서는 이제 다른 Swift 유형과 함께 프로토콜을 구성할 수 있습니다.

 User & Codable & CustomStringConvertible typealias MyType = User & Codable & CustomStringConvertible

스위프트 4의 장점.

Apple이 새 언어 버전을 출시할 때 종종 발생하기 때문에 Swift 4의 장점은 정말 큽니다. 향상된 언어 성능 외에도 마이그레이션 프로세스도 크게 안정화되었습니다. Swift 2.2를 3.0으로 마이그레이션하는 과정을 떠올리면 모든 종속성을 이전하는 복잡한 과정을 떠올립니다. Swift 4.0 변경으로 인해 타사 라이브러리를 실제로 "재배치"하지 않고 그대로 둘 수 있습니다. Swift 자체를 업데이트하기만 하면 됩니다.

또한 Swift 4.0 대 3.0 개선 사항과 관련하여 컴파일된 바이너리 파일 크기가 변경되어 앱 크기가 감소했습니다. 예를 들어 모바일 애플리케이션의 무게는 20MB였으며 최신 Swift 버전에서는 약 17MB가 소요됩니다. 그리고 Swift 4와 Swift 3 사이에는 기본적인 차이점이 있습니다. 버그가 수정되었고 언어가 조금 더 빨라졌습니다.

Swift가 사용된 지 몇 년이 지났고, 모든 업데이트가 있을 때마다 계속 발전하고 있습니다. 새로운 언어가 업데이트될 때마다 이전에 알려지지 않은 새로운 개발 관점이 생겨나고 새로운 iOS 지평을 탐색할 수 있기를 기대합니다.

iOS 개발을 위한 MVP vs MVC vs MVVM vs VIPER에 대한 기사를 놓치지 마세요.

Max Mashkov와 Elina Bessarabova가 작성했습니다 .