标签: protocol-extension

尾随where子句用于扩展非泛型类型

我有以下代码:

func registerNotification(name:String, selector:Selector)
{
    NSNotificationCenter.defaultCenter().addObserver(self, selector: selector, name: name, object: nil)
}

func registerKeyboardNotifications()
{
    let isInPopover = navigationController?.popoverPresentationController != nil
    let ignore = isInPopover && DEVICE_IS_IPAD
    if !ignore {
        registerNotification(UIKeyboardWillShowNotification, selector: Selector("keyboardWillShow:"))
        registerNotification(UIKeyboardWillHideNotification, selector: Selector("keyboardWillHide:"))
    }
}
Run Code Online (Sandbox Code Playgroud)

在延伸UIViewController.许多viewcontroller重用此代码来注册键盘通知.但是使用Swift 2.2会产生警告.我喜欢新的#selector语法,但不知道在这种情况下如何实现它.

我认为正确的解决方案是制定协议并UIViewController仅针对符合该协议的实例进行扩展.我的代码到目前为止:

@objc protocol KeyboardNotificationDelegate
{
    func keyboardWillShow(notification: NSNotification)
    func keyboardWillHide(notification: NSNotification)
}

extension UIViewController where Self: KeyboardNotificationDelegate
{
    func registerKeyboardNotifications()
    {
        let isInPopover = navigationController?.popoverPresentationController != nil
        let ignore = isInPopover && DEVICE_IS_IPAD …
Run Code Online (Sandbox Code Playgroud)

ios swift swift2 protocol-extension swift2.2

32
推荐指数
2
解决办法
7331
查看次数

Swift使协议扩展成为通知观察者

我们考虑以下代码:

protocol A {
    func doA()
}

extension A {
  func registerForNotification() {
      NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardDidShow:"), name: UIKeyboardDidShowNotification, object: nil)
  }

  func keyboardDidShow(notification: NSNotification) {

  }
}
Run Code Online (Sandbox Code Playgroud)

现在看一下实现A的UIViewController子类:

class AController: UIViewController, A {
   override func viewDidLoad() {
      super.viewDidLoad()
      self.registerForNotification()
      triggerKeyboard()
   }

   func triggerKeyboard() {
      // Some code that make key board appear
   }

   func doA() {
   }
}
Run Code Online (Sandbox Code Playgroud)

但令人惊讶的是,这会因错误而崩溃:

keyboardDidShow:]:无法识别的选择器发送到实例0x7fc97adc3c60

那么我应该在视图控制器本身中实现观察者吗?不能留在延期?

以下事情已经尝试过.

制作A类协议.将keyboardDidShow添加到协议本身作为签名.

protocol A:class {
   func doA()
   func keyboardDidShow(notification: NSNotification)
}
Run Code Online (Sandbox Code Playgroud)

ios swift swift2 protocol-extension

24
推荐指数
2
解决办法
6751
查看次数

扩展现有协议以使用默认工具实现另一个协议

是否可以通过扩展将协议合规性添加到不同的协议?

例如,我们希望A符合B:

protocol A {
  var a : UIView {get}
}

protocol B {
  var b : UIView {get}
}
Run Code Online (Sandbox Code Playgroud)

我想给B类的对象提供B的默认实现(合规性)

// This isn't possible
extension A : B {
  var b : UIView {
    return self.a
  }
}
Run Code Online (Sandbox Code Playgroud)

动机是在需要B的情况下重用A的对象而不创建我自己的"桥"

class MyClass {
  func myFunc(object : A) {
    ...
    ...
    let view = object.a 
    ... do something with view ...

    myFunc(object)      // would like to use an 'A' without creating a 'B'
  }

  func myFunc2(object : B) {
    ...
    ... …
Run Code Online (Sandbox Code Playgroud)

protocols swift protocol-extension

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

协议扩展中的Swift属性观察者?

考虑以下:

protocol ViewControllable: class {
  typealias VM: ViewModellable
  var vm: VM! { get }
  func bind()
}

extension ViewControllable {
  var vm: VM! {
    didSet {
      bind()
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试观察vm属性并bind在注入时调用它.但这不会编译错误说:

扩展名可能不包含存储的属性

这是有道理的,因为协议不能强制执行属性storedcomputed.

这可能在没有介绍的情况下完成class inheritance吗?

换句话说,我可以观察协议扩展内属性的变化吗?

swift swift2 protocol-extension

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

可以在Objective-c中访问的协议的扩展上定义Swift方法

是否可以从Objective-C调用Swift中协议扩展中定义的方法?

例如:

protocol Product {
    var price:Int { get }
    var priceString:String { get }
}

extension Product {
    var priceString:String {
        get {
            return "$\(price)"
        }
    }
}

class IceCream : Product {
    var price:Int {
        get {
            return 2
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

实例的价格字符串IceCream是'$ 2'并且可以在Swift中访问,但是该方法在Objective-C中不可见.编译器抛出错误'No visible @interface for'FlowCream'声明选择器......'.

在我的配置中,如果方法是直接在Swift对象的实现中定义的,那么一切都按预期工作.即:

protocol Product {
    var price:Int { get }
    var priceString:String { get }
}

class IceCream : Product {
    var price:Int {
        get {
            return 2
        }
    } …
Run Code Online (Sandbox Code Playgroud)

protocols objective-c swift protocol-extension

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

非final类中的方法必须返回`Self`以符合协议

当实现Self在协议扩展中返回的静态协议函数时,在扩展中的函数的实现中出现错误(在没有上下文的情况下显示的最小简化方案):

import Foundation

protocol P {
    static func f() -> Self
    static func g() -> Self
}

extension P {
    static func f() -> Self { // Method 'f()' in non-final class 'NSData' must return `Self` to conform to protocol 'P'
        return g()
    }
}

extension NSData: P {
    static func g() -> Self {
        return self.init()
    }
}
Run Code Online (Sandbox Code Playgroud)

更换SelfP上发生错误的行使编译器段错误(SIG 11)(这似乎输送类型不匹配错误的有效的方式).

改变的申报f()返回P,以及更换SelfP的错误行,结果在编译成功,但失去式精密(并且需要力向下转换在每次调用点,再加上记录了Self详细要求).

是否有任何其他解决方法可以解决此问题,并且不会丢失通用返回类型?

编辑 …

interface swift swift2 protocol-extension

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

ObjC协议的协议扩展

我有一个Objective-C协议,主要用于Objective-C对象和一个或两个Swift对象.

我想在Swift中扩展协议并添加2个函数.一个用于注册通知,另一个用于处理通知.

如果我添加这些

func registerForPresetLoadedNotification() {
    NSNotificationCenter.defaultCenter().addObserver(self as AnyObject,
                                                     selector: #selector(presetLoaded(_:)),
                                                     name: kPresetLoadedNotificationName,
                                                     object: nil)
}

func presetLoaded(notification: NSNotification) {

}
Run Code Online (Sandbox Code Playgroud)

我在#selector上收到错误 Argument of '#selector' refers to a method that is not exposed to Objective-C

如果我然后标记presetLoaded,因为@objc我得到一个错误@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes

我也无法将协议扩展标记为@objc

当我将Objective-C协议创建为Swift协议时,我得到了同样的错误.

有没有办法实现这个适用于使用该协议的Objective-C和Swift类?

swift protocol-extension

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

在协议扩展中添加目标操作失败

我有一组视图控制器,它们有一个菜单栏按钮.我为那些viewControllers创建了一个协议来采用.此外,我已经扩展了协议以添加默认功能.

我的协议看起来像,

protocol CenterViewControllerProtocol: class {

    var containerDelegate: ContainerViewControllerProtocol? { get set }

    func setupMenuBarButton()
}
Run Code Online (Sandbox Code Playgroud)

并且,扩展看起来像这样,

extension CenterViewControllerProtocol where Self: UIViewController {

    func setupMenuBarButton() {
        let barButton = UIBarButtonItem(title: "Menu", style: .Done, target: self, action: "menuTapped")
        navigationItem.leftBarButtonItem = barButton
    }

    func menuTapped() {
        containerDelegate?.toggleSideMenu()
    }
}
Run Code Online (Sandbox Code Playgroud)

我的viewController采用协议 -

class MapViewController: UIViewController, CenterViewControllerProtocol {

    weak var containerDelegate: ContainerViewControllerProtocol?

    override func viewDidLoad() {
        super.viewDidLoad()

        setupMenuBarButton()
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到了很好的显示按钮,但是当我点击它时,应用程序崩溃了

[AppName.MapViewController menuTapped]: unrecognized selector sent to instance 0x7fb8fb6ae650
Run Code Online (Sandbox Code Playgroud)

如果我在ViewController中实现该方法,它可以正常工作.但我要复制符合协议的所有viewControllers中的代码.

我在这里做错了什么?提前致谢.

ios swift protocol-extension

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

在Swift中扩展通用整数类型

所以我试图用一些方便的函数来扩展Swift的整数类型,但是我还不清楚我应该扩展哪些协议.

作为一个例子,假设我想实现一个用于钳位值的函数(如果它小于最小值,则将其设置为该值,否则如果它大于最大值则将其设置为该值).我的第一个想法是做这样的事情:

extension Int {
    func clamp(minimum:Int, maximum:Int) {
        if self < minimum { return minimum }
        if self > maximum { return maximum }
        return self
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个简单的例子,但它说明了问题; 如果我现在想要调用它,UInt那么我自然也不能,所以我必须添加一个等价物UInt,但这对于UInt16等等不适用.

我认为我可以在链上向上扩展一些东西,然后使用泛型,但是IntegerType似乎无法扩展协议.

那么,是否有更合适的地方可以放置我的扩展程序?

protocols swift swift2 protocol-extension

9
推荐指数
2
解决办法
1894
查看次数

如果在协议扩展中定义静态方法,如何在协议上调用静态方法?

protocol Car {
    static func foo() 
}

struct Truck : Car {

}

extension Car {
    static func foo() {
        print("bar")
    }
}

Car.foo() // Does not work  
// Error: Car does not have a member named foo

Truck.foo() // Works
Run Code Online (Sandbox Code Playgroud)

Xcode Car.foo()正确地自动填充,所以我要问的是它是否是一个不能编译的错误(说它没有一个名为foo()的成员).如果在协议扩展中定义静态方法,可以直接在协议上调用静态方法吗?

protocols swift swift2 protocol-extension

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