Swift blog

13571 단어
swift 블로그를 한 번 읽어서 OC와 swift의 차이 및 swift 버전 변동에 대한 세부 사항을 알아보는 것을 권장합니다.
OC id -> Swift Any
OC API의 유연성을 향상시키는 수동 포장 불필요
OC
Swift2
Swift3
id
AnyObject
Any
NSArray *
[AnyObject]
[Any]
NSDictionary *
[NSObject:AnyObject]
[AnyHashable:Any]
NSSet *
Set
Set
주의해야 할 것은 swift2는 더 이상 스텔스 변환을 제공하지 않기 때문에 NS교차는 변환을 표시해야 한다
Overriding methods and conforming to protocols
명명 OC 준수, id->Any
// Swift 2
class Foo: NSObject, NSCopying {
    override func isEqual(_ x: AnyObject?) -> Bool { ... }
    func copyWithZone(_ zone: NSZone?) -> AnyObject { ... }
}

// Swift 3
class Foo: NSObject, NSCopying {
    override func isEqual(_ x: Any?) -> Bool { ... }
    func copy(with zone: NSZone?) -> Any { ... }
}

Untyped Collections
스텔스 브리지가 존재하지 않습니다. as를 사용해야 합니다. swift3에서 가져온 코코아는 Any/AnyHashable를 받아들였기 때문에 집합에 대해서도 [AnyHashable:Any]를 사용할 수 있습니다.
// Swift 2
struct State {
    var name: String
    var abbreviation: String
    var population: Int

    var asPropertyList: [NSObject: AnyObject] {
        var result: [NSObject: AnyObject] = [:]//     NSDictionary
        // Implicit conversions turn String into NSString here…
        result["name"] = self.name
        result["abbreviation"] = self.abbreviation
        // …and Int into NSNumber here.
        result["population"] = self.population
        return result
    }
}

let california = State(name: "California",
                       abbreviation: "CA",
                       population: 39_000_000)
NSNotification(name: "foo", object: nil,
               userInfo: california.asPropertyList)
               
// Swift 3
struct State {
    var name: String
    var abbreviation: String
    var population: Int

    // Change the dictionary type to [AnyHashable: Any] here...
    var asPropertyList: [AnyHashable: Any] {
        var result: [AnyHashable: Any] = [:]
        // No implicit conversions necessary, since String and Int are subtypes
        // of Any and AnyHashable
        result["name"] = self.name
        result["abbreviation"] = self.abbreviation
        result["population"] = self.population
        return result
    }
}
let california = State(name: "California",
                       abbreviation: "CA",
                       population: 39_000_000)
// ...and you can still use it with Cocoa API here
Notification(name: "foo", object: nil,
             userInfo: california.asPropertyList)

The AnyHashable Type
Any 유형은 모든 종류를 보유할 수 있지만 Dictionary,Set는Hasble가 필요합니다. AnyHashble는 swift3에서 제기한hashable의 초클래스입니다. 어떤hash 가능한 유형이든Anyhashble 프로토콜을 실현했습니다. 예를 들어String,Int
Explicit Conversion for Unbridged Contexts
일부 한정된 장소에서 swift는 C와 OC의 디자인을 직접 연결할 수 없다. 예를 들어 id*이다. 이때api는 UnsafePointer를 표시할 것이다. 이때 as변환이 필요하다. 그리고 &
// ObjC
@interface Foo

- (void)updateString:(NSString **)string;
- (void)updateObject:(id *)obj;

@end

// Swift
func interactWith(foo: Foo) -> (String, Any) {
    var string = "string" as NSString // explicit conversion
    foo.updateString(&string) // parameter imports as UnsafeMutablePointer
    let finishedString = string as String

    var object = "string" as AnyObject
    foo.updateObject(&object) // parameter imports as UnsafeMutablePointer
    let finishedObject = object as Any

    return (finishedString, finishedObject)
}

그 밖에 OC의 프로토콜은 클래스 프로토콜로 구조체, 매거 또는 기타 경량급의 통용 유형으로 OC의 프로토콜을 준수할 수 없다
AnyObject Member Lookup
Any는 AnyObject의 검색 행위 예술이 없기 때문에 Any에게 동적으로 메시지를 보낼 수 없지만 AnyObject는 할 수 있습니다. 이때 전환이 필요합니다.
// Swift 2
func foo(x: NSArray) {
    // Invokes -description by magic AnyObject lookup
    print(x[0].description)
}

// Swift 3
func foo(x: NSArray) {
    // Result of subscript is now Any, needs to be coerced to get method lookup
    print((x[0] as AnyObject).description)//              as!NSOjbect
}

Swift Value Types in Objective-C
Any는 모든 구조체, 매거진, 원조 또는 다른 유형을 보유할 수 있다. OC의 id는 swift3에서any와 같고 swift2에서는 수동으로 상자를 봉하거나 클래스로 들어가야 하며 swift3는 필요없다.
// Swift 2
struct CreditCard { number: UInt64, expiration: NSDate }

let PaymentMade = "PaymentMade"

// We can't attach CreditCard directly to the notification, since it
// isn't a class, and doesn't bridge.
// Wrap it in a Box class.
class Box {
    let value: T
    init(value: T) { self.value = value }
}

let paymentNotification =
    NSNotification(name: PaymentMade,
                   object: Box(value: CreditCard(number: 1234_0000_0000_0000,
                                                 expiration: NSDate())))


// Swift 3
let PaymentMade = Notification.Name("PaymentMade")

// We can associate the CreditCard value directly with the Notification
let paymentNotification =
    Notification(name: PaymentMade,
                 object: CreditCard(number: 1234_0000_0000_0000,
                                    expiration: Date()))

주의해야 할 것은 swift3에서 흔히 볼 수 있는 구조체 유형은 코코아 대상이 아니라 투명한 대상으로 교차하고, Int, UInt, Double, Bool은 NSNumber, Int8, UInt16은 투명한 대상으로 교차한다.만약 unrecognized selector sent to _SwiftValue 문제에 부딪히면 OC가 swift 값 형식에 대해 깨우는 방법을 시도할 때 수동으로 관리해야 한다는 것을 나타낸다
swift Any는 Optional을 포함하는 모든 종류를 가지고 있습니다. OC api가 nonull id를 요구하지만 Optional은 패키지를 풀지 않은 상황에서도 매개 변수로 전달할 수 있기 때문에 컴파일 오류가 아니라runtime error를 초래할 수 있습니다.swift3.0.1+Xoce8.1 상기 문제를 해결했다. 호환 문제를 피하기 위해 투명한 대상에 의존하지 마라. 왜냐하면 미래의 swift가 고정된 유형에 연결될 수 있기 때문이다.
Working with JSON in Swift
JSONSerialization Foundation framework
Extracting Values from JSON
JSONserialization 클래스 방법
import Foundation

let data: Data // received from a network request, for example
let json = try? JSONSerialization.jsonObject(with: data, options: [])

json의 맨 윗부분 대상은 일반적으로 사전이나 그룹입니다. 우리는 as?+를 사용할 수 있습니다.if 판단 변환
// Example JSON with object root:
/*
    {
        "someKey": 42.0,
        "anotherKey": {
            "someNestedKey": true
        }
    }
*/
if let dictionary = jsonWithObjectRoot as? [String: Any] {
    if let number = dictionary["someKey"] as? Double {
        // access individual value in dictionary
    }

    for (key, value) in dictionary {
        // access all key / value pairs in dictionary
    }

    if let nestedDictionary = dictionary["anotherKey"] as? [String: Any] {
        // access nested dictionary values by key
    }
}

// Example JSON with array root:
/*
    [
        "hello", 3, true
    ]
*/
if let array = jsonWithArrayRoot as? [Any] {
    if let firstObject = array.first {
        // access individual object in array
    }

    for object in array {
        // access all objects in array
    }

    for case let string as String in array {
        // access only string values in array
    }
}

Creating Model Objects from Values Extracted from JSON
호텔 모델이 있다고 가정해 보세요.
import Foundation

struct Restaurant {
    enum Meal: String {
        case breakfast, lunch, dinner
    }

    let name: String
    let location: (latitude: Double, longitude: Double)
    let meals: Set
}

sever의 JSON 데이터
{
    "name": "Caffè Macs",
    "coordinates": {
        "lat": 37.330576,
        "lng": -122.029739
    },
    "meals": ["breakfast", "lunch", "dinner"]
}

Writing an Optional JSON Initializer
extension Restaurant {
    init?(json: [String: Any]) {
        guard let name = json["name"] as? String,
            let coordinatesJSON = json["coordinates"] as? [String: Double],
            let latitude = coordinatesJSON["lat"],
            let longitude = coordinatesJSON["lng"],
            let mealsJSON = json["meals"] as? [String]
        else {
            return nil
        }

        var meals: Set = []
        for string in mealsJSON {
            guard let meal = Meal(rawValue: string) else {
                return nil
            }

            meals.insert(meal)
        }

        self.name = name
        self.coordinates = (latitude, longitude)
        self.meals = meals
    }
}

Writing a JSON Initializer with Error Handling
enum SerializationError: Error {
    case missing(String)
    case invalid(String, Any)
}

extension Restaurant {
    init(json: [String: Any]) throws {
        // Extract name
        guard let name = json["name"] as? String else {
            throw SerializationError.missing("name")
        }

        // Extract and validate coordinates
        guard let coordinatesJSON = json["coordinates"] as? [String: Double],
            let latitude = coordinatesJSON["lat"],
            let longitude = coordinatesJSON["lng"]
        else {
            throw SerializationError.missing("coordinates")
        }

        let coordinates = (latitude, longitude)
        guard case (-90...90, -180...180) = coordinates else {
            throw SerializationError.invalid("coordinates", coordinates)
        }

        // Extract and validate meals
        guard let mealsJSON = json["meals"] as? [String] else {
            throw SerializationError.missing("meals")
        }

        var meals: Set = []
        for string in mealsJSON {
            guard let meal = Meal(rawValue: string) else {
                throw SerializationError.invalid("meals", string)
            }

            meals.insert(meal)
        }

        // Initialize properties
        self.name = name
        self.coordinates = coordinates
        self.meals = meals
    }
}

Interactive Playgrounds
여기서는 저의 약문 플레이 그라운드를 보실 수 있습니다. 자세를 정확하게 사용하세요.
Literals in Playgrounds
Xcode7.1 색상, 그림, 파일에 사용되는 글꼴 크기 지원 시작
Strings in Swift 2
여기 제 약문을 보러 가셔도 돼요. 정말 swift string을 아세요?
Increasing Performance by Reducing Dynamic Dispatch
swift는 슈퍼클래스를 다시 쓰는 방법과 속성을 허용합니다. 실행 시간에 접근해서 간접적으로 호출해야 합니다.이 기술을 동적 발송이라고 하는데 이 기술은 언어 표현의 복잡성과 대량의runtime 소모를 간접적인 사용에 증가시켰다.다음은 동적 발송을 없애는 세 가지 방식을 소개한다.final,private,WholeModule Optimization
다음 코드를 보십시오
class ParticleModel {
    var point = ( 0.0, 0.0 )
    var velocity = 100.0

    func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
        point = newPoint
        velocity = newVelocity
    }

    func update(newP: (Double, Double), newV: Double) {
        updatePoint(newP, newVelocity: newV)
    }
}

var p = ParticleModel()
for i in stride(from: 0.0, through: 360, by: 1.0) {
    p.update((i * sin(i), i), newV:i*1000)
}

위에서 쓴 바와 같이 컴파일러는 동적 파견 호출을 보낸다
  • p 업데이트 호출
  • p의 업데이트 Point 호출
  • p의point 원조 속성 획득
  • p 획득 속도
  • 이 곳에서 동적 발송을 사용하는 이유는Particle Model의 하위 클래스가 계산 가능한 속성을 통해point,velocity를 다시 쓸 수도 있고 업데이트,updatePonit를 다시 쓸 수도 있기 때문입니다.
    동적 파견 호출의 실현은method table을 찾아서 간접 호출을 실행하는 것입니다.직접 호출하는 속도에 비해 틀림없이 느릴 것이다.
    Use final when you know that a declaration does not need to be overridden
    final 키워드는class,method,property를 다시 쓰지 않도록 제한할 수 있습니다.컴파일러가 동적 발송을 안전하게 취소할 수 있습니다.point,velocity,updatePoint는 동적 발송을 하지 않습니다. 직접 방문하고 update는 동적 발송을 합니다.
    class ParticleModel {
        final var point = ( x: 0.0, y: 0.0 )
        final var velocity = 100.0
    
        final func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
            point = newPoint
            velocity = newVelocity
        }
    
        func update(newP: (Double, Double), newV: Double) {
            updatePoint(newP, newVelocity: newV)
        }
    }
    

    final 수식류를 할 때 이불을 분류할 수 없다는 것을 나타내기 때문에 함수, 속성이 모두final임을 가리킨다
    final class ParticleModel {
        var point = ( x: 0.0, y: 0.0 )
        var velocity = 100.0
        // ...
    }
    

    Infer final on declarations referenced in one file by applying the private keyword.
    private 키워드를 사용하여 현재 파일에 제한합니다. 현재 파일에 이class를 다시 쓰지 않으면 컴파일러는 동적 발송이 적용되지 않는다고 추정합니다.
    class ParticleModel {
        private var point = ( x: 0.0, y: 0.0 )
        private var velocity = 100.0
    
        private func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
            point = newPoint
            velocity = newVelocity
        }
    
        func update(newP: (Double, Double), newV: Double) {
            updatePoint(newP, newVelocity: newV)
        }
    }
    

    final과 마찬가지로private도class를 수식할 수 있다
    Use Whole Module Optimization to infer final on internal declarations.
    인터넷의 기본 액세스 제어 권한은 모듈에서만 볼 수 있음을 나타냅니다.swift 컴파일 파일은 모듈이 독립되어 있어 인터넷 성명이 다른 파일에서 다시 쓰였는지 확인할 수 없습니다.그러나 전체 모듈의 최적화가 시작되면 모든 모듈이 동시에 컴파일되고 컴파일러가 인터넷의 가시성을 추측할 수 있다
    public class ParticleModel {
        var point = ( x: 0.0, y: 0.0 )
        var velocity = 100.0
    
        func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
            point = newPoint
            velocity = newVelocity
        }
    
        public func update(newP: (Double, Double), newV: Double) {
            updatePoint(newP, newVelocity: newV)
        }
    }
    
    var p = ParticleModel()
    for i in stride(from: 0.0, through: times, by: 1.0) {
        p.update((i * sin(i), i), newV:i*1000)
    }
    

    Nullability and Objective-C
    사실 대응하는 게 선택값이에요.
  • !없음
  • ?비워둘 수 있음
  • 좋은 웹페이지 즐겨찾기