【问题标题】:How to return a custom object in a swift convenience initializer?如何在 swift 便利初始化程序中返回自定义对象?
【发布时间】:2015-10-19 17:51:36
【问题描述】:

我正在尝试做这样的事情:

public extension UIImage {
    public convenience init(whatever: Int) {
        UIGraphicsBeginImageContextWithOptions(...)

        //...

        let image = UIGraphicsGetImageFromCurrentContext()
        UIGraphicsEndImageContext()

        return image // <- impossible
    }
}

但这是不可能的,因为“nil”是初始化器的唯一有效返回...我该怎么做?

例如,Objtive-C 方法 [UIImage imageNamed:] 是一个类方法(它可以在 Objective-C 中返回它想要的任何内容),它被映射到 swift 初始化器 UIImage(named:)。

【问题讨论】:

    标签: objective-c swift uiimage initialization convenience-methods


    【解决方案1】:

    您想要的是类工厂方法,而不是初始化程序。 Foundation/Cocoa 中的大多数工厂方法都会自动桥接到初始化器,但如果您想要的无法通过init 完成,您可以添加一个新的类方法:

    public extension UIImage {
        class func imageWithWhatever(whatever: Int) -> UIImage {
            UIGraphicsBeginImageContextWithOptions(...)
    
            //...
    
            let image = UIGraphicsGetImageFromCurrentContext()
            UIGraphicsEndImageContext()
    
            return image
        }
    }
    

    【讨论】:

    • 在 Swift 中不能返回不同的对象有点遗憾。我有这个框架,在故事板中定义了这个复杂的视图控制器。我希望能够覆盖init() 甚至创建一个自定义初始化程序以编程方式实例化视图控制器,并使用其子视图/插座等进行所有设置。但唯一的方法是使用工厂方法...
    【解决方案2】:

    这是因为你返回的是一个新对象,而不是 self。 init 的重点是创建你的对象的结构,而不是一个新的,所以如果你想把它作为一个方便的 init 来做,你需要这样做:

    public extension UIImage {
        public convenience init?(whatever: Int) {
            defer {
                UIGraphicsEndImageContext()
            }
            UIGraphicsBeginImageContextWithOptions(...)
    
            //...
            guard let currentContext = UIGraphicsGetCurrentContext() else { return nil }
            guard let image = currentContext.makeImage() else { return nil }
    
            self.init(cgImage:image)
        }
    }
    

    也许您想要创建一个执行您所要求的类函数,而不是方便的 init:

    public class func createImage(whatever: Int) -> UIImage? {
        defer {
            UIGraphicsEndImageContext()
        }
        UIGraphicsBeginImageContextWithOptions(...)
    
        //...
        guard let currentContext = UIGraphicsGetCurrentContext() else { return nil }
        guard let cgImage = currentContext.makeImage() else { return nil }
        let image = UIImage(cgImage: cgImage)
    
        return image
    }
    

    抱歉,这不是 100% 的代码,但这基本上是它的要点

    【讨论】:

    • 需要注意的是,在调用self.init(...)之后,还可以在函数结束前修改self,如self.foo = Foo()。在UIImage 的情况下不是非常有用,但问题标题没有指定它需要。
    • @arsenius 注意在这种情况下根本不重要,你只能在初始化后操作类属性,应该是给定的
    • “你可以在初始化后操作属性”是我的观点。你不能做let image = UIImage()...return image,但你可以修改self,它涵盖了许多便利初始化器的用例。该线程上发生的 OP 或其他人可能没有意识到这一点。
    • 在这方面修改自我是没有意义的,你只是在增加混乱。坚持所问的问题,人们正在寻找关于 SO 的简明答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2013-02-10
    • 1970-01-01
    相关资源
    最近更新 更多