标签: swift-protocols

嵌套在类中的Swift协议

我想在我的类中嵌套一个协议来实现委托模式,如下所示:

class MyViewController : UIViewController {

    protocol Delegate {
        func eventHappened()
    }

    var delegate:MyViewController.Delegate?

    private func myFunc() {
        delegate?.eventHappened()
    }
}
Run Code Online (Sandbox Code Playgroud)

但是编译器不会允许它:

声明仅在文件范围内有效

我可以通过MyViewControllerDelegate在类范围之外声明来轻松地使它工作.
我的问题是为什么会有这样的限制?

swift swift-protocols

15
推荐指数
2
解决办法
6904
查看次数

Swift协议要求,只能通过使用最终类来满足

我在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 ownerStudent类中的定义上得到以下错误:

协议'Ownee'要求'所有者'不能被非最终类('学生')满足,因为它在非参数非结果类型位置使用'Self'

我试图理解这个错误的原因是什么,为什么让Student最终的类会修复它,如果有一些解决方法能够以不同的方式对它进行建模,而不是让这个类最终.我已经搜索了这个错误,但到目前为止还没有找到太多.

oop generics swift swift-protocols

15
推荐指数
4
解决办法
2850
查看次数

我可以在Swift中扩展元组吗?

我想在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元组采用给定的协议吗?

tuples swift swift-extensions swift-protocols

14
推荐指数
2
解决办法
4171
查看次数

我如何遵守与演员的协议?

当我尝试定义actor符合 a 的an 时protocol,Xcode 给出错误Actor-isolated instance method 'foo()' cannot be used to satisfy nonisolated protocol requirementnonisolated我可以实现我认为我不想做的功能。我需要吗?如果我这样做的话我会失去什么?

这是导致错误的示例代码:

protocol Fooable {
    func foo() -> Int
}

actor Bar: Fooable { // Error: Actor-isolated instance method...
    func foo() -> Int {
        return 42
    }
}
Run Code Online (Sandbox Code Playgroud)

actor swift swift-protocols

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

自我,协议扩展和非最终类

我尝试为UIView编写一个静态方法,它从nib实例化该类的视图.方法应该是通用的,并且适用于每个UIView子类.另外,我想保存类型信息 - 例如,在此代码中

let myView = MyView.loadFromNib()
Run Code Online (Sandbox Code Playgroud)

编译器推断出myViewMyView类.经过几次试验,我决定使用协议扩展,否则我将无法访问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)

protocols swift swift-extensions swift-protocols

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

具有泛型类型的协议功能

我想创建一个如下所示的协议:

protocol Parser {
    func parse() -> ParserOutcome<?>
}

enum ParserOutcome<Result> {
    case result(Result)
    case parser(Parser)
}
Run Code Online (Sandbox Code Playgroud)

我想让解析器返回特定类型的结果或另一个解析器.

如果我在使用相关联的类型Parser,那么我不能使用Parserenum.如果我在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)

generics types associated-types swift swift-protocols

13
推荐指数
2
解决办法
4743
查看次数

无法在Swift中的另一个协议中使用协议作为关联类型

我有一个协议,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)

ios associated-types swift swift-protocols

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

如何符合协议的变量'set&get?

我正在玩协议以及如何符合它们.

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的答案.它极大地解释了不同的场景.

protocols getter-setter ios swift swift-protocols

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

为什么Self和self有时会在静态函数中引用不同的类型?

最近,我一直在使用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)

swift swift-protocols swift3

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

具有内部函数和属性的Swift公共协议

我想知道什么是最好的做法,当我想要一些功能公开,一些内部使用协议时我.

我写的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)

access-modifiers ios swift swift-protocols swift3

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