Swift blog
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)
}
위에서 쓴 바와 같이 컴파일러는 동적 파견 호출을 보낸다
동적 파견 호출의 실현은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
사실 대응하는 게 선택값이에요.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.