ios - titletextattributes - Как определить дополнительные методы в протоколе Swift?




uinavigationbar title font (10)

В Swift 3.0

@objc protocol CounterDataSource {
    @objc optional func increment(forCount count: Int) -> Int
    @objc optional var fixedIncrement: Int { get }
}

Это сэкономит ваше время.

Возможно ли это в Свифт? Если нет, тогда есть обходное решение?


В Swift 2 и далее можно добавлять стандартные реализации протокола. Это создает новый способ использования дополнительных методов в протоколах.

protocol MyProtocol {
    func doSomethingNonOptionalMethod()
    func doSomethingOptionalMethod()
}

extension MyProtocol {
    func doSomethingOptionalMethod(){ 
        // leaving this empty 
    }
}

Это не очень хороший способ создания дополнительных методов протокола, но дает вам возможность использовать структуры в обратных вызовах протокола.

Я написал небольшое резюме здесь: http://www.avanderlee.com/swift-2-0/optional-protocol-methods/


Другие ответы здесь, связанные с маркировкой протокола, как «@objc», не работают при использовании типов, специфичных для swift.

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

Немного от темы из оригинального вопроса, но она строит идею Антуана, и я подумал, что это может помочь кому-то.

Вы также можете сделать вычисляемые свойства необязательными для структур с расширением протокола.

Вы можете сделать свойство по протоколу опциональным

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 для определения необязательного протокола требований, я приведу пример о том, как использовать расширения протокола, определить необязательный протокол.

Ниже приведен код 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


Чистый подход 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()
    }
}

Чтобы проиллюстрировать механику ответа Антуана:

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/ , что дает отличный обзор по этому вопросу.


Вот конкретный пример с шаблоном делегирования.

Настройка протокола:

@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 :

@objc protocol MyProtocol {

    @objc optional func doSomething()

}

class MyClass : MyProtocol {

    // no error

}

В противном случае протоколы Swift ведут себя как интерфейсы на других языках OO, где должны быть реализованы все методы, определенные в интерфейсах.





swift-extensions