我想在我的类中嵌套一个协议来实现委托模式,如下所示:
class MyViewController : UIViewController {
protocol Delegate {
func eventHappened()
}
var delegate:MyViewController.Delegate?
private func myFunc() {
delegate?.eventHappened()
}
}
Run Code Online (Sandbox Code Playgroud)
但是编译器不会允许它:
声明仅在文件范围内有效
我可以通过MyViewControllerDelegate在类范围之外声明来轻松地使它工作.
我的问题是为什么会有这样的限制?
我在Swift上为owner/ownee方案建模:
class Owner<T: Ownee> {
// ...
}
protocol Ownee {
var owner: Owner<Self> { get }
}
Run Code Online (Sandbox Code Playgroud)
然后我有一对班级教授/学生遵守上面的建模类型:
class Professor: Owner<Student> {
// ...
}
class Student: Ownee {
let professor: Professor
var owner: Owner<Student> { // error here (see below)
return professor
}
init(professor: Professor) {
self.professor = professor
}
}
Run Code Online (Sandbox Code Playgroud)
但是我var owner在Student类中的定义上得到以下错误:
协议'Ownee'要求'所有者'不能被非最终类('学生')满足,因为它在非参数非结果类型位置使用'Self'
我试图理解这个错误的原因是什么,为什么让Student最终的类会修复它,如果有一些解决方法能够以不同的方式对它进行建模,而不是让这个类最终.我已经搜索了这个错误,但到目前为止还没有找到太多.
我想在Swift中为(例如)两个值的元组编写扩展.例如,我想写这个swap方法:
let t = (1, "one")
let s = t.swap
Run Code Online (Sandbox Code Playgroud)
这s将是(String, Int)有价值的类型("one", 1).(我知道我可以很容易地实现一个swap(t)函数,但这不是我感兴趣的.)
我可以这样做吗?我似乎无法在extension声明中写出正确的类型名称.
另外,我想答案是一样的,我可以让2元组采用给定的协议吗?
当我尝试定义actor符合 a 的an 时protocol,Xcode 给出错误Actor-isolated instance method 'foo()' cannot be used to satisfy nonisolated protocol requirement。nonisolated我可以实现我认为我不想做的功能。我需要吗?如果我这样做的话我会失去什么?
这是导致错误的示例代码:
protocol Fooable {
func foo() -> Int
}
actor Bar: Fooable { // Error: Actor-isolated instance method...
func foo() -> Int {
return 42
}
}
Run Code Online (Sandbox Code Playgroud) 我尝试为UIView编写一个静态方法,它从nib实例化该类的视图.方法应该是通用的,并且适用于每个UIView子类.另外,我想保存类型信息 - 例如,在此代码中
let myView = MyView.loadFromNib()
Run Code Online (Sandbox Code Playgroud)
编译器推断出myView有MyView类.经过几次试验,我决定使用协议扩展,否则我将无法访问Self内部方法体.
看起来这应该工作:
protocol NibLoadable {
static func loadFromNib(name: String?) -> Self
}
extension NibLoadable where Self: UIView {
static func loadFromNib(name: String? = nil) -> Self {
let nibName = name ?? "\(self)"
let nib = UINib(nibName: nibName, bundle: nil)
return nib.instantiateWithOwner(nil, options: nil)[0] as! Self
}
}
extension UIView: NibLoadable {}
Run Code Online (Sandbox Code Playgroud)
但事实并非如此.我收到编译错误
Method 'loadFromNib' in non-final class 'UIView' must return `Self` to conform to …Run Code Online (Sandbox Code Playgroud) 我想创建一个如下所示的协议:
protocol Parser {
func parse() -> ParserOutcome<?>
}
enum ParserOutcome<Result> {
case result(Result)
case parser(Parser)
}
Run Code Online (Sandbox Code Playgroud)
我想让解析器返回特定类型的结果或另一个解析器.
如果我在使用相关联的类型Parser,那么我不能使用Parser的enum.如果我在parse()函数上指定泛型类型,那么我不能在没有泛型类型的实现中定义它.
我怎样才能做到这一点?
使用泛型,我可以写这样的东西:
class Parser<Result> {
func parse() -> ParserOutcome<Result> { ... }
}
enum ParserOutcome<Result> {
case result(Result)
case parser(Parser<Result>)
}
Run Code Online (Sandbox Code Playgroud)
这样,a Parser将由结果类型参数化.parse()可以返回Result类型的结果,或者输出类型结果的任何类型的解析器Result,或者由同一Result类型参数化的另一个解析器.
然而,对于相关类型,据我所知,我将始终有一个Self约束:
protocol Parser {
associatedtype Result
func parse() -> ParserOutcome<Result, Self>
}
enum ParserOutcome<Result, P: Parser where P.Result == …Run Code Online (Sandbox Code Playgroud) 我有一个协议,Address它继承自另一个协议Validator,并Address满足Validator扩展中的要求.
还有另一个协议,FromRepresentable它有一个associatedType(ValueWrapper)要求Validator.
现在,如果我尝试使用Addressas associatedType,那么它不会编译.它说,
推断类型'Address'(通过匹配要求'valueForDetail')无效:不符合'Validator'.
这种用法是非法的吗?我们是不是应该能够使用Address的地方Validator,因为所有Addresses都是Validator.
下面是我正在尝试的一段代码.
enum ValidationResult {
case Success
case Failure(String)
}
protocol Validator {
func validate() -> ValidationResult
}
//Address inherits Validator
protocol Address: Validator {
var addressLine1: String {get set}
var city: String {get set}
var country: String {get set}
}
////Fulfill Validator protocol requirements in extension
extension …Run Code Online (Sandbox Code Playgroud) 我正在玩协议以及如何符合它们.
protocol Human {
var height: Int {get set}
}
struct boy : Human {
var height: Int {return 5} // error!
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试学习不同的方法来实现set和get.但是上面的代码会引发以下错误:
类型'男孩'不符合协议'人'
但是写下面的内容不会有任何错误:
struct boy : Human {
var height = 5 // no error
}
Run Code Online (Sandbox Code Playgroud)
当你也可以设置一个变量时,我不明白其中的区别,也不知道究竟需要实现什么.我查看了不同的问题和教程,但他们只是写作并没有任何更深入的解释.
编辑: 确保你在这里看到Imanou的答案.它极大地解释了不同的场景.
最近,我一直在使用Swift开发多个面向协议的应用程序框架,并注意到协议扩展中有一些(看似)奇怪的静态函数行为,特别是从元类型调用扩展函数的情况.
我最初发现这些行为的方式是对一个错误进行故障排除,其中一个对象的类型以一种看似不可能的方式发生了变化.我追查了问题并最终确定这是因为在静态函数中,Self并且self可能存在不同的类型(注意:我已经分别称这些为"Big S Self"和"Little s self").我将用我在游乐场中掀起的一些简单的例子来证明这一点:
class SomeBaseClass: SomeProtocol {}
class SomeChildClass: SomeBaseClass {}
protocol SomeProtocol {}
extension SomeProtocol {
static private func getName() -> String {
return "\(self): \(type(of: self))"
}
static func ambiguousName() -> String {
return getName()
}
static func littleName() -> String {
return self.getName()
}
static func bigName() -> String {
return Self.getName()
}
}
let child: SomeBaseClass.Type = SomeChildClass.self // SomeChildClass.Type
print(child.ambiguousName()) // "SomeChildClass: SomeBaseClass.Type\n"
print(child.littleName()) // "SomeChildClass: SomeBaseClass.Type\n"
print(child.bigName()) …Run Code Online (Sandbox Code Playgroud) 我想知道什么是最好的做法,当我想要一些功能公开,一些内部使用协议时我.
我写的AudioManager在斯威夫特3包装AVPlayer作为一个框架.
我想要一些方法是公共的,所以例如使用AudioManager的ViewController可以访问一些方法,但是一些方法不会暴露在框架之外
- >即使用访问修饰符internal而不是public.
我正在用协议驱动设计编写框架,几乎每个部分都应该有一个协议.
因此协议正在与框架内的协议进行通信.
例如,主类 - AudioManager有一个AudioPlayer,并且应该能够internal在其上调用一些函数,
例如,pause(reason:)但该方法应该internal在框架之外暴露.
这是一个例子.
internal enum PauseReason {
case byUser
case routeChange
}
// Compilation error: `Public protocol cannot refine an internal protocol`
public protocol AudioPlayerProtocol: InternalAudioPlayerProtocol {
func pause() // I want
}
internal protocol InternalAudioPlayerProtocol {
func pause(reason: PauseReason) // Should only be accessible within the framework
}
public class AudioPlayer: …Run Code Online (Sandbox Code Playgroud)