Ios 如何使用同一类针对每个目标执行不同的功能?扩展及;协议让我失望

Ios 如何使用同一类针对每个目标执行不同的功能?扩展及;协议让我失望,ios,swift,Ios,Swift,简单的场景:我有一个基本的ViewController,它有一个我想在子类中选择性重写的方法。我想在子类ViewController的扩展中进行覆盖 这不起作用: class BaseViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() overrideStyles() } func overrideStyles() {

简单的场景:我有一个基本的ViewController,它有一个我想在子类中选择性重写的方法。我想在子类ViewController的扩展中进行覆盖

这不起作用:

class BaseViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        overrideStyles()
    }

    func overrideStyles() {
        // do nothing here. Optionally overridden as needed
    }
}

class ViewController: BaseViewController {
}

// this is in another file that is to a specific target
extension ViewController {
    override func overrideStyles() {
        print("YAY!")
    }
}
它也不适用于协议:

protocol OverridesStyles {
    func overrideStyles()
}

extension OverridesStyles {
    func overrideStyles() {
        print("default method that does nothing")
        // do nothing, this makes the method optional
    }
}

class BaseViewController: UIViewController, OverridesStyles {
    override func viewDidLoad() {
        super.viewDidLoad()

        overrideStyles()
    }
}

// this is in another file that is to a specific target
extension ViewController {
    func overrideStyles() {
        print("YAY!")
    }
}
我不能对整个ViewController类进行子类化,因为它是情节提要中的类,并且我不能对每个目标使用不同的情节提要


还有别的办法吗?我的想法是,我可以有不同的目标,每个目标有不同的扩展,因为overrideStyles方法可能会根据目标引用不同的UI元素


谢谢。

文档给出了答案,这是一条规则:

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

我无法解释原因,但重写子类扩展中的方法似乎只有在需要重写 基类中的方法也在扩展中定义

以下是一个独立的示例:

class A : NSObject {
    override init() {
        super.init()
        foo()
        bar()
    }

    func foo() {
        print("foo from A called")
    }
}

extension A {
    func bar() {
        print("bar from A called")
    }
}

class B : A { }

extension B {
    override func foo() {
        print("foo from B called")
    }
    override func bar() {
        print("bar from B called")
    }
}

let b = B() // foo from A called, bar from B called
可以看到,从子类
B

按预期调用,但基类
A

中的
foo()
方法正常。。。我找到了这个问题的一个有趣的答案,它实现了我想要的。将OverrideStyles协议应用于BaseViewController将不允许我对ViewController类进行协议扩展。(好吧,它会允许的,但它不起作用)

但是,将OverrideStyles协议应用于ViewController类可以让我成功地进行协议扩展。因此,似乎不能对子类进行协议扩展,而只能对同一个类进行协议扩展

总之,这是可行的:

protocol OverridesStyles {
    func overrideStyles()
}

extension OverridesStyles {
    func overrideStyles() {
        print("default method that does nothing")
        // do nothing, this makes the method optional
    }
}

class ViewController: BaseViewController, OverridesStyles {
    override func viewDidLoad() {
        super.viewDidLoad()

        overrideStyles()
    }
}

// this is in another file that is to a specific target
extension ViewController {
    func overrideStyles() {
        print("YAY!")
    }
}

我也有同样的问题,如果我使用prototype选项,它会抱怨函数不在主类中,但是如果我将其添加到主类中作为基类,它会抱怨“无效的重新声明…”,因为它认为同一函数有两个声明

试试这个:

// Main class file
class TestViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        overrideStyles()
    }
}

// In a separate file with Target set to one Target
extension TestViewController {
    func overrideStyles() {
        print("default method that does nothing")
        // do nothing, this makes the method optional
    }
}

// In another separate file with Target set to another Target
extension TestViewController {
    func overrideStyles() {
        print("YAY!")
    }
}
我发现在为目标构建时,如果没有定义该目标的扩展,并且主视图控制器中没有提示您添加会破坏该目标的函数,那么它会很好地抱怨。这也意味着您可以在单个故事板中很好地使用TestViewController,该故事板以您希望的任何目标为目标。因此,您现在有1个故事板,其中1个大容量代码作为基础,还有一个只包含变体的函数。在我的工作版本中,这是用来更改iAction上的操作的,效果很好

@IBAction func continueTapped() {
    continueAction()
}

我的想法是,我可以有不同的目标,每个目标有不同的扩展,因为overrideStyles方法可以根据目标引用不同的UI元素。为什么不呢?:class ViewController:BaseViewController{override func overrideStyles(){super.overrideStyles()//如果你想打印(“耶!”)},应该可以。@SherM4n不,我不能这样做。因为故事板中必须使用ViewController类。我不能为每个目标设置不同的故事板。@Aronbratcher我不明白为什么故事板会出现在表中,但是,基本上,如果viewcontroller继承自baseviewcontroller,则可以重写其方法并在内部执行任何您想要的操作。根据您的需要,这两个视图控制器在不同或相同的故事板中。我有一个通过故事板实例化的ViewController类。如果我想以不同的方式覆盖它,我不能子类化,因为如果我子类化,那么故事板引用需要指定新的类。