Разве в Swift расширение протокола допускает функциональные тела? - PullRequest
0 голосов
/ 13 октября 2018

Я прошёл учебное пособие и заметил, что автор расширил их протокол под названием Activity и написал тело функции в своем коде.Это компилируется, однако у меня сложилось впечатление, что протоколы показывают только сигнатуры методов или, если он реализует тело, то это будет мутирующая функция.Приведенный ниже код не использует мутирование в одной из своих функций, но он все еще работает и работает!Может кто-нибудь объяснить явления или подтвердить, что расширения протокола могут иметь тела методов?

import CareKit
import SwiftyJSON

enum ActivityType: String {
        case Intervention
        case Assessment
}

enum ScheduleType: String {
    case Weekly
    case Daily

}

enum StepFormat : String {
    case Scale
    case Quantity
}

protocol Activity {

    var identifier : String  { get set}
    var groupIdentifier : String  { get set}
    var title : String  { get set}
    var colour : UIColor?  { get set}
    var text : String  { get set}
    var startDate : Date  { get set}
    var schedule : [NSNumber]  { get  set}
    var scheduleType : ScheduleType  { get set}
    var instructions : String?   { get set}
    var imageURL : NSURL?   { get set}
    var activityType: ActivityType  { get set}
    var medication : Medication?  { get set}

    init()
    init(json: JSON)
    func createCareKitActivity() -> OCKCarePlanActivity

}

extension Activity {

    //  A mutating function to allow Acticities or Assessments to intialiser base properties
    mutating func parseActivityFields(json: JSON) {
        self.identifier = json["identifier"].string!
        self.groupIdentifier = json["group_identifier"].string!
        self.title = json["title"].string!
        self.text = json["text"].string!

        let colourString = json["color"].string!
        self.colour = UIColor.colorWithString(colourString)

        if let instructionString = json["instructions"].string {
            self.instructions = instructionString
        }

        if let imageString = json["imageURL"].string {
            let componentsOfString = imageString.components(separatedBy: ".")

            if let pathForResource = Bundle.main.path(forResource: componentsOfString[0], ofType: componentsOfString[1]){
                self.imageURL = NSURL(fileURLWithPath: pathForResource)
            }
        }

        self.startDate = dateFromString(string: json["startdate"].string!)!
        self.scheduleType = ScheduleType(rawValue: json["scheduletype"].string!)!

        self.schedule = json["schedule"].string!.components(separatedBy: ",").map ( {
            NSNumber(value: Int32($0)!)
        })

        if let medication = json["medication"].string,
            let medicationImageString = json["medicationimage"].string {

            let componentsOfString = medicationImageString.components(separatedBy: ".")
            let pathForResource = Bundle.main.path(forResource: componentsOfString[0], ofType: componentsOfString[1])

            self.medication = Medication.init(medication: medication, imageURL: NSURL.init(fileURLWithPath: pathForResource!))
        }

    }

    init(json: JSON) {

        self.init()

        self.parseActivityFields(json: json)

    }


    func createCareKitActivity() -> OCKCarePlanActivity{

        //creates a schedule based on the internal values for start and end dates
        let startDateComponents = NSDateComponents(date: self.startDate, calendar: NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)! as Calendar)

        let activitySchedule: OCKCareSchedule!

        switch self.scheduleType {
        case .Weekly :
            activitySchedule = OCKCareSchedule.weeklySchedule(withStartDate: startDateComponents as DateComponents, occurrencesOnEachDay: self.schedule)

        case .Daily:
            activitySchedule = OCKCareSchedule.dailySchedule(withStartDate: startDateComponents as DateComponents, occurrencesPerDay: self.schedule[0].uintValue)

        }

        let activity = OCKCarePlanActivity.intervention(
            withIdentifier: identifier,
            groupIdentifier: nil,
            title: title,
            text: text,
            tintColor: colour,
            instructions: instructions,
            imageURL: imageURL as? URL,
            schedule: activitySchedule,
            userInfo: ["medication": medication], optional: false)

        return activity

    }
}

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

In Swift, does a protocol extension allow function bodies?

Да.Это действительно удобный способ добавить определенную функциональность только к экземплярам какого-либо протокола.Подумайте об этом:

protocol Flying {
    func useWings()
}

extension Flying {
    func fly() {}
}

class Animal {}
class Bird: Animal {}

extension Bird: Flying {
    func useWings() {}
}

let bird = Bird()
bird.fly()

Здесь также есть некоторая логика.Если что-то может использовать крылья, то оно также, вероятно, может летать.Поэтому, когда мы расширяем Bird, чтобы реализовать Flying, поскольку он имеет useWings - он также может летать.

The code below doesn't use mutating on one of its functions but it still runs and WORKS! Can someone explain the phenomena

Ключевое слово Mutating говорит, что функция будет мутировать значение, которое онаназывается на.Вы должны сказать это явно, если ваш протокол не является классом (protocol Some: class {}).createCareKitActivity() не изменяет себя, поэтому вам не нужно указывать mutating

0 голосов
/ 13 октября 2018

В Swift расширения позволяют вам предоставлять реализации протоколов по умолчанию.
В соответствии с документацией Swift по протоколам,

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

Источник: Swift Documentation

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...