Swift 프로토콜에서 선택적 메서드는 어떻게 선언합니까?
스위프트에서 가능한가요?그렇지 않은 경우 이를 수행할 수 있는 해결 방법이 있습니까?
1. 기본 구현 사용(권장)
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 */ } } }
이러한 최적화를 실장하는 방법은 없습니다.대리인이 메서드를 실장하고 있는지 아닌지는 알 수 없습니다.
이 문제를 해결하는 방법은 여러 가지가 있지만(선택적인 폐쇄, 여러 작업을 위해 다른 위임 개체를 사용), 이 예는 문제를 명확하게 보여줍니다.
사용법 2. 사용방법@objc optional
.
@objc protocol MyProtocol {
@objc optional func doSomething()
}
class MyClass: NSObject, MyProtocol {
/* no compile error */
}
이점
- 디폴트 실장은 필요 없습니다.옵션 메서드 또는 변수를 선언하기만 하면 바로 사용할 수 있습니다.
단점들
따라서 모든 적합한 유형이 Objective-C와 호환되도록 요구하여 프로토콜의 기능을 심각하게 제한합니다.즉, 다음에서 상속되는 클래스만
NSObject
이치노구조체도, 에넘도, 관련 유형도 없습니다.옵션의 메서드가 실장되어 있는지 여부를 항상 체크해야 합니다.옵션으로 콜을 하거나, 대응하는 타입이 실장하고 있는지 어떤지를 체크해야 합니다.옵션 메서드를 자주 호출하는 경우 많은 보일러 플레이트가 도입될 수 있습니다.
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 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?()
옵션 요구 프로토콜을 정의하기 위해 옵션 수식자와 @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" 표시를 포함하는 다른 답변은 swift-specific 유형을 사용하는 경우 작동하지 않습니다.
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"
swift에서 잘 작동하는 선택적 프로토콜을 선언하려면 함수를 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
Swift 3.0의 경우
@objc protocol CounterDataSource {
@objc optional func increment(forCount count: Int) -> Int
@objc optional var fixedIncrement: Int { get }
}
그러면 시간이 절약됩니다.
- 때 더해야 요.
optional
키워드를 지정합니다. - 단, 이 기능이 작동하려면 프로토콜에 @objc 속성이 표시되어야 합니다.
- 이는 또한 이 프로토콜이 클래스에는 적용 가능하지만 구조에는 적용되지 않음을 의미합니다.
swift protocol에서 옵션 메서드를 생성할 수 있는 방법은 두 가지가 있습니다.
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에는 옵션인 메서드에 기본 구현을 제공할 수 있는 확장이라는 기능이 있습니다.
프로토콜 상속을 통한 순수한 Swift 접근 방식:
//Required methods
protocol MyProtocol {
func foo()
}
//Optional methods
protocol MyExtendedProtocol: MyProtocol {
func bar()
}
class MyClass {
var delegate: MyProtocol
func myMethod() {
(delegate as? MyExtendedProtocol).bar()
}
}
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"
옵션인 프로토콜 방식을 어떻게 구현할 수 있는지 묻기 전에 왜 구현해야 하는지 물어봐야 한다고 생각합니다.
만약 우리가 swift protocols를 고전적인 객체 지향 프로그래밍의 인터페이스로 생각한다면, 선택적인 방법은 별로 의미가 없으며, 아마도 더 나은 해결책은 기본 구현을 만드는 것일 것이다.또는 프로토콜에서 가능한 메서드의 조합을 나타내기 위해 프로토콜을 프로토콜 집합(이들 간의 상속 관계 포함)으로 분리합니다.
자세한 내용은 https://useyourloaf.com/blog/swift-optional-protocol-methods/,을 참조하십시오.이 문제에 대한 개요는 다음과 같습니다.
원래 질문과는 조금 다른 주제지만 앙투안의 아이디어를 바탕으로 한 것이어서 누군가에게 도움이 될 것 같았습니다.
프로토콜 확장이 있는 구조물에 대해 계산된 속성을 선택적으로 만들 수도 있습니다.
프로토콜의 속성을 선택적으로 만들 수 있습니다.
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 protocol InterViewDelegate:class {
@objc optional func optfunc() // This is optional
func requiredfunc()// This is required
}
다음은 구조나 열거가 아닌 swift 클래스 전용의 매우 간단한 예입니다.프로토콜 메서드는 선택 사항이며, 두 가지 수준의 선택적 체인이 있습니다.또한 프로토콜을 채택하는 클래스에서는 선언에 @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!)
}
}
완전 스위프트로 하고 싶은 경우, 가장 좋은 방법은 Swift 타입의 structure와 같은 Swift 타입을 반환하는 경우 기본 구현 항목을 제공하는 것입니다.
예:
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()
}
}
모든 기능을 정의하지 않고 프로토콜을 구현할 수 있습니다.
우선 그 차이를 이해하자
첫 번째 예 - 다음과 같은 경우UITableViewDataSource
두 가지 메서드를 강제로 작성해야 합니다.그것이 swift way default protocol 입니다.
두 번째 예 - 글을 쓰는 경우UITableViewDelegate
빨간색 오류는 표시되지 않으므로 위임 방법을 모두 추가하십시오.어떤 방법을 사용할지는 당신에게 달려 있습니다.라고 부를 수 있다optional method
!
예를 들어 이것을 이해합시다.
First Swift Way 기본 프로토콜 접근법
class ContactModel{
var firstname: String?
var lastname: String?
}
protocol ContactDataSource: AnyObject{
func contactConfiguration(contact: ContactModel)
}
class ViewController: ContactDataSource{
func contactConfiguration(contact: ContactModel) {
print(contact)
}
}
두 번째 접근법 - 옵션 프로토콜
@objc
class UserModel: NSObject{
var firstname: String = ""
}
@objc protocol UserDataSource{
func contactConfiguration(user: UserModel)
@objc optional func userInfo(user: UserModel)
}
class ViewController: UserDataSource{
func contactConfiguration(user: UserModel) {
print(user)
}
}
주의: 옵션 protocal에서 볼 수 있는 경우 userInfo 메서드는 작성하지 않았기 때문에 사용자에게 달려 있습니다.즉, 클래스에 메서드를 추가하든 추가하지 않든 상관없습니다. - 프로토콜에서 선택적 메서드로 호출됩니다.
클래스 및 프로토콜은 @objc 속성을 사용하여 선언해야 하며 구조가 아닌 클래스에서만 작동합니다.
세 번째 접근법 - Extension을 사용하는 선택적 프로토콜
주의: Structure 또는 Class를 수강할 수 있습니다.
class UserModel{
var firstname: String = ""
}
또는
struct UserModel{
var firstname: String = ""
}
그리고.
protocol UserDataSource{
func contactConfiguration(user: UserModel)
}
extension UserDataSource{
func userInfo(user: UserModel){}
}
class myview: UserDataSource{
func contactConfiguration(user: UserModel) {
print(user)
}
}
옵션 함수 변수로 저장하는 것도 하나의 옵션입니다.
struct MyAwesomeStruct {
var myWonderfulFunction : Optional<(Int) -> Int> = nil
}
let squareCalculator =
MyAwesomeStruct(myWonderfulFunction: { input in return input * input })
let thisShouldBeFour = squareCalculator.myWonderfulFunction!(2)
protocol에서 함수를 정의하고 해당 프로토콜에 대한 확장을 만든 다음 옵션으로 사용할 함수에 대한 빈 구현을 만듭니다.
정의하려면Optional
Protocol
빨리 사용하세요.@objc
키워드 전Protocol
선언과attribute
/method
선언문을 작성해야 합니다.다음은 프로토콜의 Optional Property 샘플입니다.
@objc protocol Protocol {
@objc optional var name:String?
}
// 코드에 해당 프로토콜을 구현하려고 하면 해당 함수를 클래스에 포함시키지 않습니다.
class MyClass: Protocol {
// No error
}
또 다른 방법은 프로토콜 확장을 사용하는 것입니다. 프로토콜의 기본 구현을 제공할 수도 있습니다.그러면 그 프로토콜의 기능이 선택사항이 될 수 있습니다.
언급URL : https://stackoverflow.com/questions/24032754/how-does-one-declare-optional-methods-in-a-swift-protocol
'sourcetip' 카테고리의 다른 글
Excel의 VBA를 사용하여 모든 시트의 채우기 색상을 "채우지 않음"으로 설정합니다. (0) | 2023.04.23 |
---|---|
Bash로 $@가 뭐죠? (0) | 2023.04.18 |
새로운 WPF의 User Settings / Application Settings 와 동등합니다.NET 버전 (0) | 2023.04.18 |
WPF 창을 표시하지 않고 로드하는 방법 (0) | 2023.04.18 |
"경고: iPhone 앱에는 빌드 구성이 설정되어 있어도 armv6 아키텍처가 포함되어 있어야 합니다. (0) | 2023.04.18 |