답변:
protocol MyProtocol {
func doSomething()
}
extension MyProtocol {
func doSomething() {
/* return a default value or just leave empty */
}
}
struct MyStruct: MyProtocol {
/* no compile error */
}
장점
Objective-C 런타임이 필요하지 않습니다 (적어도 명시 적으로는 아님). 즉, 구조체, 열거 형 및 비 NSObject
클래스를 준수 할 수 있습니다 . 또한 강력한 제네릭 시스템을 활용할 수 있습니다.
이러한 프로토콜을 준수하는 유형을 만날 때는 항상 모든 요구 사항이 충족되는지 확인할 수 있습니다 . 항상 구체적인 구현이거나 기본 구현입니다. "인터페이스"또는 "계약"이 다른 언어로 작동하는 방식입니다.
단점
Void
요구 사항이 아닌 경우 적절한 기본값을 가져야 하지만 항상 가능하지는 않습니다. 그러나이 문제점이 발생하면 해당 요구 사항에 실제로 기본 구현이 없어야하거나 API 디자인 중에 실수를 한 것입니다.
적어도 특별한 반환 값으로 그 문제를 해결하지 않고 는 기본 구현과 전혀 구현을 구분할 수 없습니다 . 다음 예제를 고려하십시오.
protocol SomeParserDelegate {
func validate(value: Any) -> Bool
}
방금 반환하는 기본 구현을 제공하면 true
언뜻보기에 괜찮습니다. 이제 다음 의사 코드를 고려하십시오.
final class SomeParser {
func parse(data: Data) -> [Any] {
if /* delegate.validate(value:) is not implemented */ {
/* parse very fast without validating */
} else {
/* parse and validate every value */
}
}
}
이러한 최적화를 구현할 수있는 방법은 없습니다. 대리인이 메소드를 구현하는지 여부를 알 수 없습니다.
이 문제를 극복 할 수있는 여러 가지 방법이 있지만 (선택적 클로저, 서로 다른 작업을위한 다른 대리자 개체를 사용하여),이 예는 문제를 명확하게 나타냅니다.
@objc optional
.@objc protocol MyProtocol {
@objc optional func doSomething()
}
class MyClass: NSObject, MyProtocol {
/* no compile error */
}
장점
단점
모든 준수 유형이 Objective-C와 호환되도록 요구 하여 프로토콜의 기능 을 심각하게 제한합니다 . 즉, 상속받은 클래스 만 NSObject
이러한 프로토콜을 준수 할 수 있습니다. 구조체, 열거 형, 관련 유형이 없습니다.
선택적으로 적합한 메소드를 구현 하거나 구현하는지 확인하여 선택적 메소드가 구현되는지 항상 확인해야 합니다. 선택적 메소드를 자주 호출하는 경우 많은 상용구가 발생할 수 있습니다.
respondsToSelector
?
optional func doSomething(param: Int?)
Swift 2 이상에서는 프로토콜의 기본 구현을 추가 할 수 있습니다. 이것은 프로토콜에서 새로운 선택적인 방법을 만듭니다.
protocol MyProtocol {
func doSomethingNonOptionalMethod()
func doSomethingOptionalMethod()
}
extension MyProtocol {
func doSomethingOptionalMethod(){
// leaving this empty
}
}
선택적 프로토콜 메소드를 작성하는 것은 좋은 방법은 아니지만 프로토콜 콜백에서 구조체를 사용할 수 있습니다.
나는 여기에 작은 요약을 썼다 : https://www.avanderlee.com/swift-2-0/optional-protocol-methods/
선택적 수정 자 및 @objc 속성 을 사용하여 선택적 요구 사항 프로토콜을 정의 하는 방법에 대한 답변 이 있으므로 프로토콜 확장을 사용하여 선택적 프로토콜을 정의하는 방법에 대한 샘플을 제공합니다.
아래 코드는 Swift 3. *입니다.
/// Protocol has empty default implementation of the following methods making them optional to implement:
/// `cancel()`
protocol Cancelable {
/// default implementation is empty.
func cancel()
}
extension Cancelable {
func cancel() {}
}
class Plane: Cancelable {
//Since cancel() have default implementation, that is optional to class Plane
}
let plane = Plane()
plane.cancel()
// Print out *United Airlines can't cancelable*
프로토콜 확장 메소드는 Objective-C 코드로 호출 할 수 없으며 Swift 팀은이를 수정하지 않습니다. https://bugs.swift.org/browse/SR-492
신속한 특정 유형을 사용하는 경우 프로토콜을 "@objc"로 표시하는 것과 관련된 다른 답변은 작동하지 않습니다.
struct Info {
var height: Int
var weight: Int
}
@objc protocol Health {
func isInfoHealthy(info: Info) -> Bool
}
//Error "Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C"
신속하게 작동하는 선택적 프로토콜을 선언하려면 함수를 func 대신 변수로 선언하십시오.
protocol Health {
var isInfoHealthy: (Info) -> (Bool)? { get set }
}
그런 다음 다음과 같이 프로토콜을 구현하십시오.
class Human: Health {
var isInfoHealthy: (Info) -> (Bool)? = { info in
if info.weight < 200 && info.height > 72 {
return true
}
return false
}
//Or leave out the implementation and declare it as:
//var isInfoHealthy: (Info) -> (Bool)?
}
그런 다음 "?"를 사용할 수 있습니다. 기능 구현 여부 확인
func returnEntity() -> Health {
return Human()
}
var anEntity: Health = returnEntity()
var isHealthy = anEntity.isInfoHealthy(Info(height: 75, weight: 150))?
//"isHealthy" is true
다음은 위임 패턴이있는 구체적인 예입니다.
프로토콜 설정 :
@objc protocol MyProtocol:class
{
func requiredMethod()
optional func optionalMethod()
}
class MyClass: NSObject
{
weak var delegate:MyProtocol?
func callDelegate()
{
delegate?.requiredMethod()
delegate?.optionalMethod?()
}
}
델리게이트를 클래스로 설정하고 프로토콜을 구현하십시오. 선택적 메소드를 구현할 필요가 없음을 참조하십시오.
class AnotherClass: NSObject, MyProtocol
{
init()
{
super.init()
let myInstance = MyClass()
myInstance.delegate = self
}
func requiredMethod()
{
}
}
한 가지 중요한 점은 선택적 방법이 선택적이며 "?"가 필요하다는 것입니다. 전화 할 때. 두 번째 물음표를 언급하십시오.
delegate?.optionalMethod?()
에서 스위프트 3.0
@objc protocol CounterDataSource {
@objc optional func increment(forCount count: Int) -> Int
@objc optional var fixedIncrement: Int { get }
}
시간을 절약 할 수 있습니다.
@objc
모든 회원에게 왜 필요한 이유 가 있습니까?
required
플래그로 메소드를 시도 했지만 오류가 발생했습니다 : required
'init'선언에만 사용할 수 있습니다.
optional
각 방법 전에 키워드 를 추가해야합니다 .@objc
합니다.
Antoine의 답변의 메커니즘을 설명하려면 :
protocol SomeProtocol {
func aMethod()
}
extension SomeProtocol {
func aMethod() {
print("extensionImplementation")
}
}
class protocolImplementingObject: SomeProtocol {
}
class protocolImplementingMethodOverridingObject: SomeProtocol {
func aMethod() {
print("classImplementation")
}
}
let noOverride = protocolImplementingObject()
let override = protocolImplementingMethodOverridingObject()
noOverride.aMethod() //prints "extensionImplementation"
override.aMethod() //prints "classImplementation"
선택적 프로토콜 메소드를 구현할 수있는 방법 을 묻기 전에 왜 구현해야하는지 묻어 야한다고 생각합니다.
우리가 빠른 프로토콜을 고전적인 객체 지향 프로그래밍에서 인터페이스 로 생각한다면 , 선택적 메소드는 그다지 의미가 없으며 아마도 기본 구현을 만들거나 프로토콜을 프로토콜 세트로 분리하는 것이 더 나은 해결책 일 것입니다 (아마도 상속 관계가있을 수 있습니다) 프로토콜에서 가능한 방법 조합을 나타냅니다.
자세한 내용은 https://useyourloaf.com/blog/swift-optional-protocol-methods/를 참조 하십시오 .이 문제에 대한 훌륭한 개요를 제공합니다.
원래 질문에서 약간 벗어난 주제이지만 Antoine의 아이디어를 바탕으로 누군가에게 도움이 될 것이라고 생각했습니다.
프로토콜 확장이있는 구조체에 대해 계산 된 속성을 선택적으로 만들 수도 있습니다.
프로토콜의 속성을 선택적으로 만들 수 있습니다
protocol SomeProtocol {
var required: String { get }
var optional: String? { get }
}
프로토콜 확장에서 더미 계산 속성 구현
extension SomeProtocol {
var optional: String? { return nil }
}
그리고 이제 선택적 속성이 구현되었거나 구현되지 않은 구조체를 사용할 수 있습니다
struct ConformsWithoutOptional {
let required: String
}
struct ConformsWithOptional {
let required: String
let optional: String?
}
또한 내 블로그의 Swift 프로토콜에서 선택적 속성 을 수행하는 방법을 작성 했으며 Swift 2 릴리스를 통해 변경 사항이있을 경우 계속 업데이트됩니다.
다음은 신속한 클래스에만 해당되는 간단한 예제이며 구조 또는 열거 형에는 해당되지 않습니다. 선택적인 프로토콜 방법에는 두 가지 수준의 옵션 연결이 있습니다. 또한 프로토콜을 채택한 클래스는 선언에 @objc 속성이 필요합니다.
@objc protocol CollectionOfDataDelegate{
optional func indexDidChange(index: Int)
}
@objc class RootView: CollectionOfDataDelegate{
var data = CollectionOfData()
init(){
data.delegate = self
data.indexIsNow()
}
func indexDidChange(index: Int) {
println("The index is currently: \(index)")
}
}
class CollectionOfData{
var index : Int?
weak var delegate : CollectionOfDataDelegate?
func indexIsNow(){
index = 23
delegate?.indexDidChange?(index!)
}
}
delegate?.indexDidChange?(index!)
시겠습니까?
protocol CollectionOfDataDelegate{ func indexDidChange(index: Int) }
다음 과 같은 선택적이지 않은 메소드를 갖도록 프로토콜을 작성했다면 , 물음표없이 호출 할 것입니다 : delegate?.indexDidChange(index!)
프로토콜에서 메소드에 대한 선택적 요구 사항을 설정할 때, 그에 맞는 Type은 그 메소드를 구현하지 않을 수 있습니다 이므로 ?
구현을 확인하는 데 사용되며 , 없는 경우 프로그램이 중단되지 않습니다. @Unheilig
weak var delegate : CollectionOfDataDelegate?
(약한 참조를 보장?)
delegate?
사용법에 대한 설명을 답변에 추가 할 수 있습니까 ? 그 정보는 앞으로 다른 사람들을 위해 실제로 속해야합니다. 나는 이것을 공표하고 싶지만 그 정보는 실제로 답에 있어야합니다.
순식간에 신속하게하고 싶다면 가장 좋은 방법은 Swift 유형의 구조체 와 같은 Swift 유형을 반환하는 경우 기본 구현 particullary를 제공하는 것입니다
예 :
struct magicDatas {
var damagePoints : Int?
var manaPoints : Int?
}
protocol magicCastDelegate {
func castFire() -> magicDatas
func castIce() -> magicDatas
}
extension magicCastDelegate {
func castFire() -> magicDatas {
return magicDatas()
}
func castIce() -> magicDatas {
return magicDatas()
}
}
모든 기능 을 정의하지 않고 프로토콜을 구현할 수 있습니다.
신속한 프로토콜에서 선택적 방법을 생성 할 수있는 두 가지 방법이 있습니다.
1-첫 번째 옵션은 @objc 속성을 사용하여 프로토콜을 표시하는 것입니다. 이것은 클래스에서만 채택 할 수 있음을 의미하지만 개별 메소드를 다음과 같이 선택적인 것으로 표시합니다.
@objc protocol MyProtocol {
@objc optional func optionalMethod()
}
2-더 빠른 방법 :이 옵션이 더 좋습니다. 이와 같이 아무것도하지 않는 선택적 메소드의 기본 구현을 작성하십시오.
protocol MyProtocol {
func optionalMethod()
func notOptionalMethod()
}
extension MyProtocol {
func optionalMethod() {
//this is a empty implementation to allow this method to be optional
}
}
Swift에는 확장이라는 기능이있어 선택적으로 원하는 메소드에 기본 구현을 제공 할 수 있습니다.
하나의 옵션은 옵션 함수 변수로 저장하는 것입니다.
struct MyAwesomeStruct {
var myWonderfulFunction : Optional<(Int) -> Int> = nil
}
let squareCalculator =
MyAwesomeStruct(myWonderfulFunction: { input in return input * input })
let thisShouldBeFour = squareCalculator.myWonderfulFunction!(2)
Optional
Protocol
신속하게 정의하려면 해당 프로토콜 내에서 선언 및 / 선언 @objc
전에 키워드 를 사용해야 합니다. 다음은 프로토콜의 선택적 속성 샘플입니다.Protocol
attribute
method
@objc protocol Protocol {
@objc optional var name:String?
}
class MyClass: Protocol {
// No error
}
@optional
메서드 나 속성 앞에을 넣습니다 .
@optional
올바른 키워드조차 아닙니다. 입니다 optional
. 클래스 와 프로토콜을 @objc
속성으로 선언해야 합니다.