GVKun编程网logo

在子类中未调用Swift 3 ObjC可选协议方法(在子类的构造方法中,必须显示调用父类的构造方法)

13

本文的目的是介绍在子类中未调用Swift3ObjC可选协议方法的详细情况,特别关注在子类的构造方法中,必须显示调用父类的构造方法的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个

本文的目的是介绍在子类中未调用Swift 3 ObjC可选协议方法的详细情况,特别关注在子类的构造方法中,必须显示调用父类的构造方法的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解在子类中未调用Swift 3 ObjC可选协议方法的机会,同时也不会遗漏关于ios – Swift 3 ObjC可选协议方法未在子类中调用、ios – 使用Swift中的Comparable扩展@objc协议、ios – 在Swift的NSObject子类的初始化程序中调用super.init()、ios – 在子类内部实现协议方法的知识。

本文目录一览:

在子类中未调用Swift 3 ObjC可选协议方法(在子类的构造方法中,必须显示调用父类的构造方法)

在子类中未调用Swift 3 ObjC可选协议方法(在子类的构造方法中,必须显示调用父类的构造方法)

我有以下类层次结构:

class ScrollableViewController: UIViewController, UITableViewDelegate { // ... }

实现一种UITableViewDelegate协议方法,例如tableView:willDisplayCellAt:

SpecificScrollableViewController继承自的类中,ScrollableViewController不再调用新的可选协议方法,例如tableView(_:heightForRowAt:)

答案1

小编典典

tl; dr,您需要在函数声明之前添加其Objective-C声明,例如

@objc(tableView:heightForRowAtIndexPath:)func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {  // return stuff}

借助《Swift 3迁移指南》,我被告知这是一个解决方案,其中指出:

如果在声明符合性的类的子类中实现可选的Objective-C协议要求,则会看到警告,“实例方法’…’几乎与协议’…’的可选要求’…’相匹配”

•解决方法:@objc(objectiveC:name:)在实现可选要求之前,使用原始的Objective-C选择器添加一个属性。

我相当确定这是一个错误:当协议方法位于子类中时,允许检查选择器功能的运行时动态似乎未在Grand Swift重命名中正确桥接。使用Objective-
C名称前缀函数声明可以正确地将Swift桥接到Objective-C,并允许canPerformAction:withSender:从Objective-
C内部查询Swift 3重命名的方法

ios – Swift 3 ObjC可选协议方法未在子类中调用

ios – Swift 3 ObjC可选协议方法未在子类中调用

我有以下类层次结构:
class ScrollableViewController: UIViewController,UITableViewDelegate { // ... }

这实现了一个UITableViewDelegate协议方法,例如的tableView:willdisplayCellAt:

在我的类SpecificScrollableViewController中,它继承自ScrollableViewController,新的可选协议方法不再被调用.的tableView(_:heightForRowAt

总结

以上是小编为你收集整理的ios – Swift 3 ObjC可选协议方法未在子类中调用全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

ios – 使用Swift中的Comparable扩展@objc协议

ios – 使用Swift中的Comparable扩展@objc协议

我正在尝试使用Comparable扩展我的协议选项以使用简单的.sort()方法.

以下简短示例仅使用Equatable来显示错误.

@objc protocol Option: Equatable {
    var title: String { get }
    var enabled: Bool { get }
    var position: Int { get }
}

func ==(lhs: Option,rhs: Option) -> Bool {
    return lhs.position == rhs.position
}

Option协议必须标记为@objc或从NSObjectProtocol继承,因为它将与UIKit一起使用.

错误:

>

@objc protocol ‘Option’ cannot refine non-@objc protocol
‘Equatable’

>

Protocol ‘Option’ can only be used as a generic constraint
because it has Self or associated type requirements

你有什么建议如何解决这个问题?

解决方法

只能在Swift世界中生活,因此您无法将其扩展到Objective-C将使用的协议.尝试这样做会导致错误#1

具有Self要求的协议(即,协议声明中的至少一个方法包含Self)不能用作函数或变量声明的参数,仅作为泛型子句的参数,例如,func doSomething< T:Option>(参数:T).

从Option协议声明中删除Equatable,并在Option上声明== as generic将解决编译错误.至于排序,你也可以重载<运算符,并通过该运算符排序(无需实现Comparable):

@objc protocol Option {
    var title: String { get }
    var enabled: Bool { get }
    var position: Int { get }
}

func ==<T: Option>(lhs: T,rhs: T) -> Bool {
    return lhs.position == rhs.position
}

func <<T: Option>(lhs: T,rhs: T) -> Bool {
    return lhs.position < rhs.position
}

这允许您将符合协议的对象传递给UIKit,并在快速代码中对它们进行比较.

class A: NSObject,Option { .. }
class B: NSObject,Option { ... }

let a = A()
let b = B()
a == b  // compiles,and returns true if a and b have the same position
let c: [Option] = [a,b]
c.sort(<) // returns a sorted array by the `position` field

关于上面的排序代码的一个重要注意事项:如果你没有为c指定类型,那么编译器会将其类型推断为[NSObject],并且由于<的不明确性,排序调用将无法编译.操作符.您需要将c显式声明为[Option]以利用重载运算符.

ios – 在Swift的NSObject子类的初始化程序中调用super.init()

ios – 在Swift的NSObject子类的初始化程序中调用super.init()

我在 Swift中构建一个iOS应用程序,并绘制了Apple提供的 Lister示例项目.

Lister使用两个模型对象:List和ListItem.我发现他们都不会在初始化器中调用super.init(),即使它们是NSObject子类.

然而,在Lister的Objective-C版本中,两个模型对象(AAPLList和AAPLListItem)都调用[super init].

Swift编程语言清楚地表示:“指定的初始化程序必须从其直接超类调用指定的初始化程序”(初始化程序初始化器链接的规则1)

这里发生了什么?为什么这是一个异常,如果你不应该总是在一个子类中调用super.init(),那么什么规则适用?

解决方法

即使我在文档中找不到这个描述的地方,发生的情况是,默认超类初始化器在子类初始化器的末尾被调用,如果它是超类的唯一初始化器,并且没有被调用明确.

NSObject只有默认的初始化(init());您可以通过在不调用super.init()的构造函数中尝试引用self(例如.println(self)),在子类初始化器的末尾调用超类初始化器:您不允许这样做,因为那个阶段还没有完全初始化.

如果要在构造函数中使用自己的某个地方,则需要在该点完全构造对象,因此您需要在此之前手动调用super.init().

ios – 在子类内部实现协议方法

ios – 在子类内部实现协议方法

请考虑通过 Cocoapods包含的模块中的以下代码(我使用Eureka,但问题不应与此相关):
open class FormViewController : UIViewController {  
}

extension FormViewController : UITableViewDelegate {    
  func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    // some default implementation
  }

  /// some other UITableViewDelegate methods follow,but _NOT_ willdisplayCell
}

我试图继承FormViewController并为tableView添加一个实现(_:willdisplay:forRowAt :)(这是UITableViewDelegate的可选方法).此方法在原始FormViewController中没有实现:

import UIKit
import Eureka

class MyViewController: FormViewController {
    override func viewDidLoad() {
        let tableView = UITableView(frame: self.view.bounds,style: .grouped)
        tableView.delegate = self
        tableView.dataSource = self
        self.tableView = tableView
        self.view.addSubview(self.tableView!)

        super.viewDidLoad()

        form = Form()
        let section = Section()
        section.append(EmailRow(){
            $0.tag = "email"
            $0.title = "Email"
        })
        form += [section]
    }

    func tableView(_ tableView: UITableView,willdisplay cell: UITableViewCell,forRowAt indexPath: IndexPath) {
        print("NOT CALLED")
    }


    override func tableView(_ tableView: UITableView,didSelectRowAt indexPath: IndexPath) {
        print("will be called")
    }

    override func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        print("GETS CALLED")
        return super.tableView(tableView,cellForRowAt: indexPath)
    }
}

/// somewhere else:
self.navigationController?.pushViewController(MyViewController(),animated: true)

使用此设置,将调用tableView(_:cellForRowAt :)的覆盖版本(意味着正确设置了tableView.delegate).不会调用tableView(_:willdisplay:forRowAt :).只要我在Eureka中添加一个空白实现,我就可以覆盖该方法.

问题:为什么Swift在超类中没有默认实现时不使用该方法?

解决方法

我自己也注意到了这个问题,这对我来说似乎是一个错误.你有两个选择.

首先,您可以在扩展中实现委托方法,并在子类中覆盖它.这将确保调用该方法.

extension FormViewController : UITableViewDelegate {    
    func tableView(_ tableView: UITableView,forRowAt indexPath: IndexPath) {
        // you can leave the implementation blank if you want
    }
}

class MyViewController: FormViewController {
    override func tableView(_ tableView: UITableView,forRowAt indexPath: IndexPath) {
        print("CALLED!!")
    }
}

其次,您可以使用pre-Swift 3表示法声明该方法,它将起作用.这部分对我来说也是一个错误(或同一个bug的所有部分).我不推荐这个选项,因为它可能会在未来的Swift或Xcode版本中发生变化,并且通常会感觉很乱.

extension FormViewController : UITableViewDelegate {    
    // no willdisplayCell method
}

class MyViewController: FormViewController {
    func tableView(_ tableView: UITableView,willdisplayCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath) {
        print("CALLED!!")
    }
}

编辑:OP将UITableViewDelegate方法放在扩展中的事实不会导致问题.即使类本身对委托进行了decalres,问题仍然存在.

关于在子类中未调用Swift 3 ObjC可选协议方法在子类的构造方法中,必须显示调用父类的构造方法的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于ios – Swift 3 ObjC可选协议方法未在子类中调用、ios – 使用Swift中的Comparable扩展@objc协议、ios – 在Swift的NSObject子类的初始化程序中调用super.init()、ios – 在子类内部实现协议方法的相关信息,请在本站寻找。

本文标签: