标签: swift-protocols

Swift协议带有"where self"子句

除了具有协议扩展的语法之外:

protocol P {}
extension P where Self : UIView {}
Run Code Online (Sandbox Code Playgroud)

...我偶然发现你可以在协议本身使用相同的where子句:

protocol P where Self : UIView {}
Run Code Online (Sandbox Code Playgroud)

请注意,这是一样的where子句限制一个通用的协议,并没有自己做P上的通用协议.

我的实验似乎表明,这里只能使用冒号,冒号之后的东西必须是类或协议(可能是通用的).

我变得很好奇:这是怎么逃避我的注意的?所以我去寻找它何时出现的证据.在Swift 3.0中,前一种语法是合法的,但不是后者.在Swift 3.3中,两者都是合法的.所以后一种语法必须在Swift 3.2之类的东西中悄然引入.我说"悄悄地",因为我在发行说明中找不到任何关于它的内容.

第二种语法是什么?它看起来只是一种方便的方法来确保没有其他类型可以采用这个协议吗?Swift标头似乎没有使用它.

where swift swift-protocols

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

仅当符合特定协议时,才对类进行Swift扩展

嗨那里=)我刚刚面临一个设计问题,我需要(基本上)做以下事情:

我要注入一些代码上viewWillAppear:任何UIViewController符合协议的子类MyProtocol.在代码中解释:

protocol MyProtocol
{
    func protocolFunction() {
        //do cool stuff...
    }
}

extension UIViewController where Self: MyProtocol //<-----compilation error
{
    public override class func initialize()
    {
        //swizzling stuff switching viewWillAppear(_: Bool) with xxx_viewWillAppear(animated: Bool)
    }

    //  MARK: - Swizzling

    func xxx_viewWillAppear(animated: Bool)
    {
        self.xxx_viewWillAppear(animated)

        //invoke APIs from  
        self.protocolFunction() // MyProtocol APIs
        let viewLoaded = self.isViewLoaded // UIViewController APIs

    }
}
Run Code Online (Sandbox Code Playgroud)

这里的主要问题是我需要UIVIewController扩展中的两件事:

  1. 调用两者MyProtocolUIViewControllerAPI
  2. 覆盖UIViewController方法initialize() …

uiviewcontroller ios swift swift-extensions swift-protocols

20
推荐指数
2
解决办法
6250
查看次数

协议扩展中的"自我"是什么?

我看到了很多以下格式的例子

extension Protocolname where Self: UIViewController
Run Code Online (Sandbox Code Playgroud)

什么是where Self协议扩展.我找不到关于此的文档.

protocols swift swift-extensions swift-protocols

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

类型CCC不符合协议'NSObjectProtocol'

我不明白为什么我的代码不起作用.这里是:

class Test: NSURLSessionDataDelegate {

    func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {

        if(error == nil) {
            print("Hallo")
        } else {
            print(error?.userInfo)
        }
    }

    func createRequest() {

        let dictionary = [
            "mailAddress":"foo@example.com",
            .....
        ]

        let nsData: NSData?
        do {
            nsData = try NSJSONSerialization.dataWithJSONObject(dictionary, options: NSJSONWritingOptions(rawValue:0))
        } catch _ {
            nsData = nil
        }

        let defaultConfigObject = NSURLSessionConfiguration.defaultSessionConfiguration()
        let defaultSession = NSURLSession(configuration: defaultConfigObject, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
        let url = NSURL(string: "http:...")!
        let urlRequest = NSMutableURLRequest(URL: url)
        urlRequest.HTTPMethod = "POST" …
Run Code Online (Sandbox Code Playgroud)

swift swift-protocols nsobjectprotocol

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

协议内的嵌套类型

可以在协议中声明嵌套类型,如下所示:

protocol Nested {

    class NameOfClass {
        var property: String { get set }
    }

}
Run Code Online (Sandbox Code Playgroud)

Xcode说"Type not allowed here",所以,如果我想创建一个需要嵌套类型的协议,这是不可能的,或者我可以用其他方式做到这一点?

protocols swift swift-protocols

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

SwiftUI:ViewModifier,其中内容是图像

我收到一个错误“Type 'PlayButtonModifier' does not conform to protocol 'ViewModifier' ”,我不明白为什么,更重要的是 - 如何正确地做。

我只是尝试创建一个ViewModifierfor an Image,以便我可以.resizable()在它上面使用例如,它仅在Image

ViewModifier协议中,有一个TypealiasforContent定义。我天真的想法是这应该有效:

struct PlayButtonModifier: ViewModifier {
    typealias Content = Image

    func body(content: Content) -> some View {
        content
    }
}
Run Code Online (Sandbox Code Playgroud)

嗯,不。太容易了。结构的隐式类型别名也会发生同样的事情:

struct PlayButtonModifier: ViewModifier {
    func body(content: Image) -> some View {
        content
    }
}
Run Code Online (Sandbox Code Playgroud)

同样的错误。

这里有什么问题?怎么会是正确的?

swift swift-protocols swiftui

18
推荐指数
2
解决办法
4154
查看次数

泛型和协议类型函数参数之间的实际差异是什么?

给定没有任何关联类型的协议:

protocol SomeProtocol
{
    var someProperty: Int { get }
}
Run Code Online (Sandbox Code Playgroud)

这两个函数在实践中有什么区别(意思不是"一个是通用的而另一个不是")?它们是否生成不同的代码,它们具有不同的运行时特征吗?当一个或多个协议变得非常重要时,这些差异是否会发生变化?(因为编译器可能内联这样的东西)

func generic<T: SomeProtocol>(some: T) -> Int
{
    return some.someProperty
}

func nonGeneric(some: SomeProtocol) -> Int
{
    return some.someProperty
}
Run Code Online (Sandbox Code Playgroud)

我主要询问编译器的不同之处,我理解两者的语言级含义.基本上,确实nonGeneric意味着一个恒定的代码大小但速度较慢的动态调度,而不是generic每个类型传递的代码大小增加,但是使用快速静态调度?

generics swift swift-protocols

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

将协议方法标记为已弃用

对于实现协议的人,如何使协议方法显示为已弃用?我尝试使用@available如下所示,但在实现协议方法时Xcode中没有显示警告.

protocol TestDelegate {
    @available(*, deprecated, message: "Don't use this anymore")
    func myMethod() -> Bool
}

extension ViewController: TestDelegate {
    func myMethod() -> Bool {
        return true
    }
}
Run Code Online (Sandbox Code Playgroud)

deprecation-warning swift swift-protocols

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

即使不是nil,IBOutlet也会与EXC_BAD_ACCESS崩溃

在UIViewController(rolePageController)中,我配置另一个UIViewController(drawerController)并从角色页面传递2个UIViews,该页面将成为drawerController配置的一部分.一旦drawerController尝试从rolePageController访问IBOutlet视图,它就会崩溃EXC_BAD_ACCESS(代码= EXC_I386_GPFLT).

在第一个VC(rolePageController)中,这里是IBOutlets:

@IBOutlet var rolePageDrawerView: UIView!
@IBOutlet var rolePageContentView: UIView!
Run Code Online (Sandbox Code Playgroud)

在rolePageController.viewDidLoad()中,我调用了抽屉控件.configureDrawer(...):

override func viewDidLoad() {
    super.viewDidLoad()

    //other stuff happens here

    let drawerController = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateViewController(withIdentifier: "drawerController") as! DrawerViewController
    drawerController.configureDrawer(drawerContainerView: self.rolePageDrawerView, overlaidView: self.rolePageContentView)

    //other stuff here
}
Run Code Online (Sandbox Code Playgroud)

DrawerViewController协议定义为:

protocol DrawerViewController where Self: UIViewController {
    func configureDrawer(drawerContainerView: UIView, overlaidView: UIView)
}
Run Code Online (Sandbox Code Playgroud)

这是configureDrawer(...)func的代码:

private var drawerParentView: UIView!
private var overlaidByDrawerView: UIView!


func configureDrawer(drawerContainerView: UIView, overlaidView: UIView) {
    self.drawerParentView = drawerContainerView
    self.overlaidByDrawerView = overlaidView
}
Run Code Online (Sandbox Code Playgroud)

在调试器中注意到,调用的drawerController实例与接收调用的self实例不匹配.这是将被调用的实例的地址:

在此输入图像描述

这是我进入呼叫时实例的地址:

在此输入图像描述

当我进入呼叫时,呼叫前抽屉控制器的地址不是自己的地址.这绝不应该发生.

我创建了一个简化的项目,通过https://github.com/ksoftllc/DynamicStackBufferOverflow重现崩溃. …

exc-bad-access uiviewcontroller ios swift swift-protocols

17
推荐指数
2
解决办法
656
查看次数

在ViewController和ContainerViewController之间传递数据

我正在开发一个应用程序,需要在view和containerView之间传递数据.我需要从两个视图发送数据和接收数据.

让我解释一下:

我可以通过协议更改Label Master(触摸容器按钮),但我无法更改标签容器(触摸主按钮).发生的事情是Master通过以下方式与容器连接.但是没有跟随Container链接到Master.

我试图添加但是segue,但它有效.

在此输入图像描述

主视图控制器:

import UIKit

protocol MasterToContainer {
    func changeLabel(text:String)
}

class Master: UIViewController, ContainerToMaster {

    @IBOutlet var containerView: UIView!

    var masterToContainer:MasterToContainer?

    @IBOutlet var labelMaster: UILabel!


    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "containerViewSegue" {
            let view = segue.destinationViewController as? Container
            view!.containerToMaster = self
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func button_Container(sender: AnyObject) {
        masterToContainer?.changeLabel("Nice! It's work!")
    }


    func changeLabel(text: String) {
        labelMaster.text = text …
Run Code Online (Sandbox Code Playgroud)

segue uistoryboardsegue swift swift-protocols swift2

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