Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/94.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 扩展中的快速覆盖功能_Ios_Swift_Generics - Fatal编程技术网

Ios 扩展中的快速覆盖功能

Ios 扩展中的快速覆盖功能,ios,swift,generics,Ios,Swift,Generics,如果我有课: class Spaceship<FuelType> { function prepareForLiftoff() throws { //Start the countdown! } } 但此代码未编译,错误显示函数的重新声明无效,这很有意义 我的问题是:是否存在重写特定类的函数的方法?换句话说,我可以在某些条件下替换功能,如上面的示例,其中FuelType:CollectionType。如果没有,是否有其他解决方法或方法来实现该行为(可

如果我有课:

class Spaceship<FuelType> {
    function prepareForLiftoff() throws {
        //Start the countdown!
    }
}
但此代码未编译,错误显示函数的
重新声明无效
,这很有意义

我的问题是:是否存在重写特定类的函数的方法?换句话说,我可以在某些条件下替换功能,如上面的示例,其中
FuelType:CollectionType
。如果没有,是否有其他解决方法或方法来实现该行为(可能声明另一个协议,idk)

现在我想得更多了,我不得不说这是不可能的,因为什么能阻止某人重写任何标准库函数呢?

来自:

扩展可以向类型添加新功能,但不能覆盖现有功能

文档详细而准确地列出了允许扩展的功能

关于你的问题:

是否存在重写特定类的函数的方法


是的,它被称为子类化。

您可能希望尝试swizzling,而不是重写。例如,以下代码允许您运行自己的
视图将出现
<代码>Swift 3

extension UIViewController {
    open override class func initialize() {
        // make sure this isn't a subclass
        guard self === UIViewController.self else { return }
        DispatchQueue.once(token: "viewWillAppear") {
            let originalSelector = #selector(self.viewWillAppear(_:))
            let swizzledSelector = #selector(self.proj_viewWillAppear1(animated:))
            let originalMethod = class_getInstanceMethod(self, originalSelector)
            let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
            method_exchangeImplementations(originalMethod, swizzledMethod)
        }
    }

    func proj_viewWillAppear1(animated: Bool) {
        self.proj_viewWillAppear1(animated: animated)
        let viewControllerName = NSStringFromClass(type(of: self))
        print("viewWillAppear: \(viewControllerName)")
    }
}
更新20170621

public extension DispatchQueue {
    private static var _onceTracker = [String]()

    public class func once(file: String = #file, function: String = #function, line: Int = #line, block:(Void)->Void) {
        let token = file + ":" + function + ":" + String(line)
        once(token: token, block: block)
    }

    public class func once(token: String, block:(Void)->Void) {
        objc_sync_enter(self)
        defer { objc_sync_exit(self) }

        if _onceTracker.contains(token) {
            return
        }

        _onceTracker.append(token)
        block()
    }
}

公平地说,我已经祈祷过了。如何重写
结构的函数呢?@matt:你知道为什么可以在不同框架的扩展中重写吗?@MartinR和@matt:谢谢(我有点想知道为什么SR-3228作为SR-2935的复制品关闭,后者似乎是关于覆盖Objective-C方法的具体内容,但目前这对我来说并不重要。)嗨,我现在可以做这项工作了吗?没有DispatchQueue.once。thanks@ilan当然,你可以创建一个像我添加的那样的扩展,或者提出你自己的实现版本。一般来说,你不应该说我是@barndog。应该不惜一切代价避免Swizzling。从iOS 14开始,苹果很可能不允许在应用商店中使用Swizzling应用。我完全同意你们的观点,但我只是提供了一个解决方案来解决OP中的具体技术问题。一般来说,即使是子类也不应该被广泛使用,因为组合总是高于继承。但IMO stackoverflow并不是一个你把坚实的原则和面向协议的编程抛给别人,让他们学习如何正确编码的地方;提出了一个问题,给出了一个解决方案,就是这样。
public extension DispatchQueue {
    private static var _onceTracker = [String]()

    public class func once(file: String = #file, function: String = #function, line: Int = #line, block:(Void)->Void) {
        let token = file + ":" + function + ":" + String(line)
        once(token: token, block: block)
    }

    public class func once(token: String, block:(Void)->Void) {
        objc_sync_enter(self)
        defer { objc_sync_exit(self) }

        if _onceTracker.contains(token) {
            return
        }

        _onceTracker.append(token)
        block()
    }
}