首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Swift中,协议扩展是否允许函数体?

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

Stack Overflow用户
提问于 2018-10-13 11:23:59
回答 3查看 1.9K关注 0票数 2

我正在看一个教程,我注意到作者扩展了他们的名为Activity的协议,并在他们的代码中编写了函数体。这是编译的,但是我的印象是协议只显示方法签名,或者如果它实现了主体,那么它将是一个变异函数。下面的代码没有在它的一个函数上使用变异,但它仍然可以运行和工作!有人能解释这些现象或确认协议扩展可以有方法体吗?

代码语言:javascript
复制
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

    }
}
EN

回答 3

Stack Overflow用户

发布于 2018-10-13 11:38:57

在Swift中,扩展允许您为协议提供默认实现。

根据Swift关于协议的文档,

可以对

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

来源:Swift Documentation

票数 3
EN

Stack Overflow用户

发布于 2018-10-22 15:00:59

In Swift, does a protocol extension allow function bodies?

是。这是一种非常方便的方式,可以将特定的功能仅添加到某些协议的实例中。请考虑以下内容:

代码语言:javascript
复制
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

票数 1
EN

Stack Overflow用户

发布于 2020-10-10 03:39:33

代码语言:javascript
复制
Class -> Protocol -> Extension

Swift的protocol extension允许您的类通过附加或默认函数进行操作

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52789231

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档