标签: protocol-oriented

Swift - 协议扩展 - 属性默认值

假设我有以下协议:

protocol Identifiable {
    var id: Int {get}
    var name: String {get}
}
Run Code Online (Sandbox Code Playgroud)

而且我有以下结构:

struct A: Identifiable {
    var id: Int
    var name: String
}

struct B: Identifiable {
    var id: Int
    var name: String
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我必须"符合"结构A和结构B中的可识别协议.但想象一下,如果我有N个结构需要符合这个协议......我不想'复制/粘贴' '一致性(var id:Int,var name:String)

所以我创建了一个协议扩展:

extension Identifiable {
    var id: Int {
        return 0
    }

    var name: String {
        return "default"
    }
}
Run Code Online (Sandbox Code Playgroud)

现在有了这个扩展,我可以创建一个符合Identifiable协议的结构,而不必实现这两个属性:

struct C: Identifiable {

}
Run Code Online (Sandbox Code Playgroud)

现在问题是我无法为id属性或name属性设置值:

var c: C = C()
c.id = 12 // Cannot assign to …
Run Code Online (Sandbox Code Playgroud)

ios swift protocol-oriented

55
推荐指数
2
解决办法
3万
查看次数

为什么传递给函数的协议默认值不会改变,即使函数在子类化时会改变?

我有一个协议,我为其分配了一些默认值:

protocol HigherProtocol {
    var level: Int { get }
    
    func doSomething()
}

extension HigherProtocol {
    var level: Int { 10 }
    
    func doSomething() {
        print("Higher level is \(level)")
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我有另一个协议,它符合更高级别的协议,但具有不同的默认值和函数实现:

protocol LowerProtocol: HigherProtocol {}

extension LowerProtocol {
    var level: Int { 1 }
    
    func doSomething() {
        print("Lower level is \(level)")
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我创建一个符合 HigherProtocol 的类,然后创建一个符合较低级别协议的子类:

class HigherClass: HigherProtocol {}

class LowerClass: HigherClass, LowerProtocol {}
Run Code Online (Sandbox Code Playgroud)

然而,当我实例化这个较低的类时,它显示了一些奇怪的行为:

let lowerClass = LowerClass()

lowerClass.level // is 1

lowerClass.doSomething() // Prints "Lower level …
Run Code Online (Sandbox Code Playgroud)

subclassing swift protocol-oriented

5
推荐指数
1
解决办法
110
查看次数

为什么不直接扩展UIView或UIViewController?

我用这段代码看到了这个问题:

protocol Flashable {}

extension Flashable where Self: UIView 
{
    func flash() {
        UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn, animations: {
            self.alpha = 1.0 //Object fades in
        }) { (animationComplete) in
            if animationComplete == true {
                UIView.animate(withDuration: 0.3, delay: 2.0, options: .curveEaseOut, animations: {
                    self.alpha = 0.0 //Object fades out
                    }, completion: nil)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

而且我想知道为什么我们不只是直接扩展UIView?或者在类似的情况下延伸UIViewController为什么用a扭转它where Self:

  • 是这样我们增加了意图,当其他开发人员来时,他们会看到这个类符合Flashable,Dimmable等吗?
  • 我们的UIView还有单独的有意义的扩展吗?而不是UIView或UIViewController的不同unNamed扩展?
  • POP有关于此主题的特定Apple指南吗?我见过开发人员这样做,但不知道为什么......

protocols swift swift-extensions protocol-oriented

3
推荐指数
1
解决办法
418
查看次数

无法对不可变值使用变异成员:“self”是不可变的

我不明白为什么我会收到此错误。SomeController是一个类,而不是一个结构,并且它不是不可变的。有解决办法吗?

class SomeController: APIFetchable {

    let baseUrl = "https://jsonplaceholder.typicode.com"
    let defaultSession =  URLSession(configuration: .default)
    var dataTask: URLSessionTask?

    func fetchDataFromAPI(atPath path: String, _ callback: ()-> Void){
        fetchDataAtPath(path) { data, error in  /*Error on this line -> "Cannot use mutating member on immutable value: 'self' is immutable"*/

        }
    }

}


protocol APIFetchable {
    var baseUrl: String {get}
    var defaultSession: URLSession {get}
    var dataTask: URLSessionTask? {get set}

    mutating func fetchDataAtPath(_ path: String,  _ callback: @escaping (Data?, Error?)-> Void)
}

extension APIFetchable …
Run Code Online (Sandbox Code Playgroud)

swift protocol-oriented swift4

2
推荐指数
1
解决办法
5546
查看次数

为什么我的默认属性值仍然显示为Init()中的参数?

我有一个描述需要测试的海水参数的协议:

protocol Parameter {

    var name: String { get }
    var unit: Unit { get }
    var value: Double { get }

}
Run Code Online (Sandbox Code Playgroud)

我有一个结构Calcium符合,符合Parameter:

struct Calcium: Parameter {

    var name: String = "Calcium"
    var unit: Unit = UnitDispersion.partsPerMillion
    var value: Double

}
Run Code Online (Sandbox Code Playgroud)

由于nameunit参数Calcium都有默认值,为什么我需要在init方法中提供它们?我不应该只需要提供一个值value吗?

我正在尝试理解面向协议的编程,并且非常感谢这里的一些指导.

在此输入图像描述

protocols swift protocol-oriented

1
推荐指数
1
解决办法
37
查看次数