首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Swift中UIViewController的自定义初始化,在情节提要中设置接口

Swift中UIViewController的自定义初始化,在情节提要中设置接口
EN

Stack Overflow用户
提问于 2016-02-10 20:31:35
回答 13查看 71.6K关注 0票数 96

我在为UIViewController的子类编写自定义初始化时遇到了问题,基本上我希望通过viewController的初始化方法传递依赖项,而不是像viewControllerB.property = value那样直接设置属性

所以我为我的viewController定制了一个初始化,并调用了超级指定的初始化

代码语言:javascript
复制
init(meme: Meme?) {
        self.meme = meme
        super.init(nibName: nil, bundle: nil)
    }

视图控制器接口驻留在storyboard中,我还将自定义类的接口设置为我的视图控制器。Swift要求调用此init方法,即使您在此方法中没有执行任何操作。否则编译器会报错...

代码语言:javascript
复制
required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

问题是当我试图用MyViewController(meme: meme)调用我的自定义初始化时,它根本不会在我的viewController中初始化属性……

我正在尝试调试,我发现在我的viewController中,init(coder aDecoder: NSCoder)首先被调用,然后我的自定义初始化被调用。然而,这两个初始化方法返回不同self内存地址。

我怀疑我的viewController的初始化有问题,它总是返回带有init?(coder aDecoder: NSCoder)self,它没有实现。

有没有人知道如何正确地为你的viewController定制初始化?注意:我的viewController的界面是在storyboard中设置的

下面是我的viewController代码:

代码语言:javascript
复制
class MemeDetailVC : UIViewController {

    var meme : Meme!

    @IBOutlet weak var editedImage: UIImageView!

    // TODO: incorrect init
    init(meme: Meme?) {
        self.meme = meme
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func viewDidLoad() {
        /// setup nav title
        title = "Detail Meme"

        super.viewDidLoad()
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        editedImage = UIImageView(image: meme.editedImage)
    }

}
EN

回答 13

Stack Overflow用户

发布于 2016-09-09 21:55:30

正如上面的答案之一所指定的,您不能同时使用和自定义初始化方法和故事板。

但您仍然可以使用静态方法从情节提要实例化ViewController,并在其上执行其他设置。

它看起来像这样:

代码语言:javascript
复制
class MemeDetailVC : UIViewController {
    
    var meme : Meme!
    
    static func makeMemeDetailVC(meme: Meme) -> MemeDetailVC {
        let newViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "IdentifierOfYouViewController") as! MemeDetailVC
        
        newViewController.meme = meme
        
        return newViewController
    }
}

不要忘记在你的故事板中指定IdentifierOfYouViewController作为视图控制器标识符。您可能还需要在上面的代码中更改情节提要的名称。

票数 54
EN

Stack Overflow用户

发布于 2016-09-09 05:56:37

当你从故事板初始化时,你不能使用自定义初始化器,使用init?(coder aDecoder: NSCoder)是苹果设计故事板初始化控制器的方式。但是,有一些方法可以将数据发送到UIViewController

您的视图控制器的名称中有detail,所以我认为您是从另一个控制器获取的。在这种情况下,您可以使用prepareForSegue方法将数据发送到详细信息(这是Swift 3):

代码语言:javascript
复制
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "identifier" {
        if let controller = segue.destinationViewController as? MemeDetailVC {
            controller.meme = "Meme"
        }
    }
}

出于测试目的,我只使用了String类型的属性,而不是Meme。此外,请确保您传入了正确的段标识符("identifier"只是一个占位符)。

票数 29
EN

Stack Overflow用户

发布于 2017-12-18 14:53:45

正如@Caleb Kleveter所指出的,我们不能在从Storyboard进行初始化时使用自定义的初始化器。

但是,我们可以使用工厂/类方法来解决这个问题,该方法从Storyboard实例化视图控制器对象,并返回视图控制器对象。我认为这是一种很酷的方式。

注意:这不是问题的确切答案,而是解决问题的变通方法。

在MemeDetailVC类中创建类方法,如下所示:

代码语言:javascript
复制
// Considering your view controller resides in Main.storyboard and it's identifier is set to "MemeDetailVC"
class func `init`(meme: Meme) -> MemeDetailVC? {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: "MemeDetailVC") as? MemeDetailVC
    vc?.meme = meme
    return vc
}

用法:

代码语言:javascript
复制
let memeDetailVC = MemeDetailVC.init(meme: Meme())
票数 25
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35315404

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档