2017-12-13 1 views
1

스위프트 4에서는 특정 프로토콜을 따르는 현재 모듈 내의 모든 유형을 찾을 수 있습니까? 예를 들어 Swift에서는 특정 프로토콜을 준수하는 모듈에서 모든 유형을 찾을 수 있습니까?

, 나는이 프로토콜 및 이러한 클래스를 정의한 말 :

protocol Animal{} 
protocol Vehicle{} 
protocol Favorite{} 

class Dog : Animal{ 
} 

class Cat : Animal, Favorite{ 
} 

class Car : Vehicle{ 
} 

class Bicycle : Vehicle, Favorite{ 
} 

내가 Favorite를 구현하는 모든 유형을 찾고 싶어요. 이것은 C#에서 쉽게 할 수 있지만 Swift에서 할 수 있는지는 잘 모르겠습니다. 도움이된다면, 나는 아니,이 모듈 내부 클래스의 이름을 얻을 수 없습니다

+0

동적 프레임 워크에서 정의 된 특정 프로토콜을 준수하는 모든 클래스를 찾으려고합니다. 다른 말로하면 내가 아는 것은 프로토콜뿐입니다. 그것으로부터 상속받은 모든 인스턴스를 찾으려고합니다. 플러 거블 프레임 워크 작성에 대해 생각해보십시오. 프로토콜을 공개하고 이제 상속받는 모든 사람의 목록을 원합니다. 내가 생각할 수있는 유일한 것은 프로토콜을 수행하는 것이 아니라 기본 클래스 대신 기본 클래스를 소유하고 있기 때문에 누가 나를 인스턴스화했는지 추적 할 수 있습니다. 그것은 초기화되어야 할 것이다. 그것이 내가가는 방향이라고 생각하십시오. – MarqueIV

+0

@Hamish, 좋은 찾을! Objective-C에 액세스하는 것을 잊어 버렸습니다. 또한 Swift뿐만 아니라 NSObject 하위 클래스 일 필요가있는 특정 클래스에 대해서도 설명하므로 명확하게 작동합니다. 그 질문을 그렇게 표시 할 수 있도록 답변에 넣었습니까? – MarqueIV

답변

1

스위프트 (4)를 사용하고

  • 고양이
  • 자전거

.

0

당신은 당신의 코드에 의해 셀 수는, 코드 : 아래와 같이 계산 확장 프로토콜을 사용

protocol Animal{} 
protocol Vehicle{} 
protocol Favorite{ 
    func countImplement() 
} 

var totalImplement = 0 
extension Favorite { 
    func updateTotalImplement(){ 
    totalImplement += 1 
    } 
} 

class Dog : Animal{ 
} 

class Cat : Animal, Favorite{ 
    func countImplement(){ 
    this.updateTotalImplement() 
    } 
} 

class Car : Vehicle{ 
} 

class Bicycle : Vehicle, Favorite{ 
    func countImplement(){ 
    this.updateTotalImplement() 
    } 
} 
+0

문제는 유형이 무엇인지 알아야한다는 것입니다. 게다가 기존 클래스를 발견하려고 시도 할 때 작성하는 것이 아니라 내 경우에는 불가능한 유형을 추가해야합니다.요컨대, 프로토콜을 고수하는 모듈에서 모든 타입을 발견하는 함수를 작성하려고합니다. 단순히 유형을 정의하고 프로토콜을 구현하면 자동으로 발견됩니다. – MarqueIV

+0

Hamish의 답변으로 이동 :) –

2

나는 스위프트 현재 목표 - C 런타임에 '네이티브'(의존하지 가지고 있다고 생각하지 않습니다) 이러한 종류의 리플렉션을 수행하기위한 API

그러나 Apple 플랫폼을 사용하고있어 (따라서 Obj-C 상호 운용성이있는 경우) 클래스의 목록을 Obj-C 런타임에 등록한 다음 주어진 프로토콜. 후드 아래에서 Swift 클래스는 Obj-C 클래스 (Obj-C interop가있을 때) 위에 빌드되기 때문에 Swift 클래스 (심지어 NSObject을 상속받지 않는 클래스도 가능)에서 작동합니다.

다음을 수행 한 후 수
protocol Favorite : class {} 

, objc_copyClassList를 사용하여이 만 (구조 또는 열거되지 않음), 당신은 단지 클래스가 준수 할 수 있도록 당신의 프로토콜을 제한 할 수 있습니다 클래스 작동하기 때문에

:

여기에 우리가 유형 ( Favorite에 부합하는 대표 metatypes의 배열을 다시 얻기 위해 UnsafeBufferPointerflatMap(_:)를 호출하고
import Foundation 

protocol Animal {} 
protocol Vehicle {} 
protocol Favorite : class {} 

class Dog : Animal {} 
class Cat : Animal, Favorite {} 
class Car : Vehicle {} 
class Bicycle : Vehicle, Favorite {} 

/// Invokes a given closure with a buffer containing all metaclasses known to the Obj-C 
/// runtime. The buffer is only valid for the duration of the closure call. 
func withAllClasses<R>(
    _ body: (UnsafeBufferPointer<AnyClass>) throws -> R 
) rethrows -> R { 

    var count: UInt32 = 0 
    let classListPtr = objc_copyClassList(&count) 
    defer { 
    free(UnsafeMutableRawPointer(classListPtr)) 
    } 
    let classListBuffer = UnsafeBufferPointer(
    start: classListPtr, count: Int(count) 
) 

    return try body(classListBuffer) 
} 

let classes = withAllClasses { $0.flatMap { $0 as? Favorite.Type } } 
print(classes) // [Bicycle, Cat] 

즉 캐스트 할 수있는 사람 실존 메타 타입 Favorite.Type).

관련 문제