在 Swift 中,协议扩展是否允许函数体?

Cos*_*ows 4 swift swift-extensions swift-protocols

我正在阅读一个教程,我注意到作者扩展了他们的称为 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

    }
}
Run Code Online (Sandbox Code Playgroud)

小智 7

在 Swift 中,扩展允许您提供协议的默认实现。
\n根据协议的 Swift 文档,

\n\n
\n

可以扩展协议以提供符合类型的方法、初始化器、下标和计算属性实现。这允许您定义协议本身的行为,而不是在每个类型的单独一致性或全局函数中定义行为。

\n
\n\n

来源:Swift 文档

\n