Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/115.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 协议扩展不';似乎没有在消费者中强制执行变量?_Ios_Swift_Protocols - Fatal编程技术网

Ios 协议扩展不';似乎没有在消费者中强制执行变量?

Ios 协议扩展不';似乎没有在消费者中强制执行变量?,ios,swift,protocols,Ios,Swift,Protocols,你说 当然,当你使用Able时 如果你忘了“v”或“x” 这是一个错误。很好。 这样做: protocol Able: class { var v:UIView? { get set } var x:CGFloat { get set } } 一切都好。太好了 您必须指定“v”和“x”,并对它们进行初始化 但是。试试这个 class ScreenThing: UIViewController, Able { @IBOutlet var v: UIView? v

你说

当然,当你使用Able时

如果你忘了“v”或“x”

这是一个错误。很好。

这样做:

protocol Able: class {
    var v:UIView? { get set }
    var x:CGFloat { get set }
}
一切都好。太好了

您必须指定“v”和“x”,并对它们进行初始化

但是。试试这个

class ScreenThing: UIViewController, Able {
    @IBOutlet var v: UIView?
    var x: CGFloat = 0.0
}
Able现在有一个属性p

您可以在Able中的函数或ScreenThing中的函数中完美地使用p。太好了

然而

当你这样做的时候

var _H: UInt8 = 0

protocol Able: class {
}

extension Able where Self:UIViewController {

    var p:P {
    get {
        return objc_getAssociatedObject(self, &_H) as! P
        }
    set {
        objc_setAssociatedObject(self, &_H, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        __setter()
        }
    }
}
不会出现错误。

您可以忘记初始化“p”(它将崩溃)

实际上,您不必将“p”指定为变量(必须使用“v”和“x”)

为什么会这样

这似乎是个大问题

我是否需要做一些不同的事情,让编译器强制执行“p”,就像它通常强制协议中的变量一样


另一种看待这个问题的方式是: 鉴于我的上述代码:

有没有办法强制编译器在consumer类中需要“p”的初始值设定项

比如说

我试过这个

class ScreenThing: UIViewController, Able {
}
但这不起作用

(奇怪的是,它可以编译-实际上我不知道它到底在做什么!它似乎与扩展中的p“不同”了。但无论如何,它并不强制要求使用初始值设定项。)

简言之,在上面,我是否可以做或添加一些事情,使编译器强制我初始化伪属性,就像我在协议中放置属性(如“x”或“v”)时通常做的那样

?

  • 也许我必须在协议中添加一些普通属性(比如“pp”),并以某种方式使p与之相关??只是一个想法

(脚注——请参见以了解上述协议中所需的“:class”。)


回答我自己的问题: 我上面的困惑是,没有什么可以初始化的。扩展中的
var p:p
(带有get和set代码块)只是两个函数

没有什么需要初始化的

例如:在我的额外问题中,我问“如何强制一致性类在唤醒时初始化它?”这是毫无意义的。如果有什么问题的话,我们可以问:“如何强制一致性类确保在唤醒时‘使用那些函数’?——这与初始化无关


还请注意,我在计算变量中的具体示例代码碰巧(非最近)使用了一个未初始化的变量,这导致了混淆。

您不必在协议的采纳器中实现
p
,因为协议扩展提供了一个实现。这就是协议扩展

更简单的例子:

class ScreenThing: UIViewController, Able {
    var p:P
}

注意,(1)即使C不声明
greet
也会编译,(2)即使C不包含
greet
的实现也会运行。这是因为这是协议扩展的工作。

我不确定您希望编译器做什么-
p
不是协议要求(即使是,您已经将默认实现作为计算属性提供给它),那么,您希望编译器在
screenshing
中强制您实现什么呢?Swift是一种相对较新的语言,编译器在某些情况下充满了bug。我会提交一份bug报告,看看苹果有什么要说的。@JoeBlow你说的“get set成语”是一个,实际上只不过是一对方法,加上一些语法糖,使它们看起来像一个属性。不需要进行初始化,因为属性
p
没有存储空间(同样,只是美化的方法)。您必须初始化
v
x
,因为它们是存储属性,因此它们具有Swift可以强制执行的内存initialise@JoeBlow(续)Swift不会强制您初始化关联的对象,因为它是在Objective-C运行时实现的–由您来确保它有一个值(或者更好,你可以添加一些逻辑来处理
objc_getassociated object
返回
nil
)的情况。你的更新没有为我编译@JoeBlow–Swift抱怨没有初始值设定器(应该如此)。而且
p
一开始甚至不是协议要求;)@Hamish我的看法不同。对我来说,协议扩展材料是一项要求,但它也满足了要求。这是一个自我满足的要求!:)毕竟,如果在实际的协议中列出了
greet
,同样的事情也会发生。我的代码的第一行可以是
协议P{func greet()}
,但这不会改变任何东西;扩展提供了实现。是的–这实际上只是您答案的第一行,提示了您的评论(可能更多的是吹毛求疵),因为它在某种程度上暗示,如果协议扩展没有提供实现,然后,您必须在协议采纳者中实现
p
),但请注意,在实际的协议声明中包含需求本身有一些微妙之处(我相信您可能知道)。这样做,您就将其包括在一致性类型的协议见证表中,在调用作为协议类型的值的协议要求时,允许您动态调度。@matt-这是一个边缘案例,但是,如果建议人们在协议扩展中实现默认实现,而不显式地将该方法声明为协议的一部分,我会很谨慎。如果将此协议用作类型(这是一种常见模式),它将不会调用此默认实现的荣誉覆盖。有关此问题的示例,请参见。注意,这只是一个问题,如果您可能会覆盖默认实现,但我会小心不要显式声明需求。@Rob I d
protocol P {}
extension P {
    func greet() {print("hello")}
}
class C : P {}
C().greet()