简体   繁体   中英

How can I define a Swift Protocol so that the implementation can be a property _or_ a method?

Here's what I want to do:

import Foundation
import UIKit

protocol PlayableMediaItem {
    func title() -> String
    func albumArt() -> UIImage
    func audioFileURL() -> URL
}


struct AudioTrack : Codable, PlayableMediaItem {
    var title: String
    var desc:String
    var albumArtDemoName:String
    var audioDemoFilename:String

    func albumArt() -> UIImage {
        let image = UIImage(named: albumArtDemoName)
        return image!
    }

    func audioFileURL() -> URL {
        return Bundle.main.url(forResource: audioDemoFilename, withExtension: "mp3")!
    }
}

But I get the error that AudioTrack doesn't conform to the PlayableMediaItem protocol because the title property isn't a method, it's a property.

How can I set this up so that title , albumArt , etc. can be implemented as either properties or methods, so long as they give me back the right type?

Some of my implementations of this might just be properties, while others are computed.

Just declare it as a property in the protocol, and use a computed property instead of using a method:

import Foundation
import UIKit

protocol PlayableMediaItem {
    var title: String { get } 
    var albumArt: UIImage { get }
    var audioFileURL: URL { get }
}


struct AudioTrack : Codable, PlayableMediaItem {
    var title: String
    var desc:String
    var albumArtDemoName:String
    var audioDemoFilename:String

    var albumArt: UIImage {
        let image = UIImage(named: albumArtDemoName)
        return image!
    }

    var audioFileURL: URL {
        return Bundle.main.url(forResource: audioDemoFilename, withExtension: "mp3")!
    }
}

Change your protocol to use properties instead of functions. That way implementing struct/class can decide to have it implemented as real property or computed one.

protocol PlayableMediaItem {
    var title: String { get }
    var albumArt: UIImage { get }
    var audioFileURL: URL { get }
}

Not entirely sure what you need, since it depends but maybe try making them variables instead of funcs and then on classes that implement the protocol you can manipulate their get/set of the var.

struct Square {
 var edge: Double = 0
 var area: Double {
get {
  return edge * edge
}
set {
  edge = sqrt(newValue)
}}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM