Swift 5.7 Generic

Horus-iOS·2022년 6월 9일
0

https://developer.apple.com/videos/play/wwdc2022/110352

WWDC22에서 소개된 Swift 5.7 Generic 구현 예시

2022년 6월 9일 기준 XCode 14.0 베타 버전이 사용 가능합니다. WWDC22에서 소개된 내용을 직접 사용해보고자 XCode 14.0 베타 버전을 설치하고, 아래 메소드를 소개된 내용으로 바꿔봤습니다.

func startRecord<T>(deviceInput: AVCaptureDeviceInput, recorder: T, deviceOrientation: AVCaptureVideoOrientation) where T: AVCaptureFileOutputRecordingDelegate { ... }

아래와 같이 바꾸고 빌드하면 정상적으로 빌드됩니다.

func startRecord(deviceInput: AVCaptureDeviceInput, recorder: some AVCaptureFileOutputRecordingDelegate, deviceOrientation: AVCaptureVideoOrientation) { ... }

아래와 같은 예시도 있습니다.

func prepareToUseDevice<T>(at index: Int, presenter: T) where T: UIViewController & AVCaptureVideoDataOutputSampleBufferDelegate { ... }
func prepareToUseDevice(at index: Int, presenter: some UIViewController & AVCaptureVideoDataOutputSampleBufferDelegate) { ... }

신기한 부분은 프로토콜에서 아래와 같이 정의했음에도 메소드 구현을 some을 포함한 형태로 구현했을 때 빌드가 된다는 점입니다. 반대의 경우도 빌드가 됩니다.

protocol StudioConfigurable {
    func prepareToUseDevice<T>(at index: Int, presenter: T) where T: UIViewController & AVCaptureVideoDataOutputSampleBufferDelegate
}

WWDC22의 예시

전체 코드는 아래와 같습니다.

protocol AnimalFeed {
    associatedtype CropType: Crop where CropType.Feed == Self
    static func grow() -> CropType
}

protocol Crop {
    associatedtype Feed: AnimalFeed where Feed.CropType == Self
    func harvest() -> Feed
}

protocol Animal {
    associatedtype Feed: AnimalFeed
    func eat(_ food: Feed)
}
struct Farm {
    func feed(_ animal: some Animal) {
        let crop = type(of: animal).Feed.grow()
        let produce = crop.harvest()
        animal.eat(produce)
    }
    
    func feedAll(_ animals: [any Animal]) {
        for animal in animals {
            feed(animal)
        }
    }
}

struct Cow: Animal {
    func eat(_ food: Hay) {}
}

struct Hay: AnimalFeed {
    static func grow() -> Alfalfa {
        Alfalfa()
    }
}

struct Alfalfa: Crop {
    func harvest() -> Hay {
        Hay()
    }
}

아래 구조체가 iOS 16부터 바꿀 수 있는 표현을 보여주고 있습니다.

struct Farm {
    func feed(_ animal: some Animal) {
        let crop = type(of: animal).Feed.grow()
        let produce = crop.harvest()
        animal.eat(produce)
    }
    
    func feedAll(_ animals: [any Animal]) {
        for animal in animals {
            feed(animal)
        }
    }
}

위 구조체 중 첫 번째 메소드는 아래 메소드와 같습니다.

struct Farm {
    func feed<T>(_ animal: T) where T: Animal {
        let crop = type(of: animal).Feed.grow()
        let produce = crop.harvest()
        animal.eat(produce)
    }
}

다음과 같이 선언할 수도 있습니다.

protocol Animal {
    
}

class Horse: Animal {
    
}

class Chicken: Animal {
    
}

var animal: some Animal = Chicken()

0개의 댓글