-1

I have been trying to initialise a Codable struct using storyboard on the ViewController but it doesn't work.

Any idea on how to fix this issue?

Thanks in advance.

Here's what I tried on View Controller:

var images: ImageRequest

init(images: ImageRequest)
{
    self.images = images
}

Code error above:

Error: 'required' initializer 'init(coder:)' must be provided by subclass of 'UIViewController'

init(images: ImageRequest)
{
    self.images = images
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

Code error above:

'super.init' isn't called on all paths before returning from initializer

init(images: ImageRequest)
{
    self.images = images
    super.init(nibName: nil, bundle: nil)
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

The code above crashes. Error message:

Thread 1: Fatal error: init(coder:) has not been implemented

Here's what I tried on the Struct:

public struct ImageRequest: Codable {
    public var albumId: Int
    public var id: Int
    public var title: String
    public var url: URL
    public var thumbnailUrl: URL

    public init( albumId: Int, id: Int, title: String, url: URL, thumbnailUrl: URL) {
        self.albumId = 0
        self.id = 0
        self.title = ""
        self.url = URL(string: "")!
        self.thumbnailUrl = URL(string: "")!
    }
}
public struct ImageRequest: Codable {
    public var albumId: Int
    public var id: Int
    public var title: String
    public var url: URL
    public var thumbnailUrl: URL

    public init( albumId: Int, id: Int, title: String, url: URL, thumbnailUrl: URL) {
        self.albumId = albumId
        self.id = id
        self.title = title
        self.url = url
        self.thumbnailUrl = thumbnailUrl
    }
}
TylerP
  • 9,600
  • 4
  • 39
  • 43
Tech UK
  • 37
  • 6
  • “The code above crashes." Any error message when crashing? What you are trying to do in fact, is how initialize a ViewController inside a Storyboard with a custom parameter, no? See this: https://stackoverflow.com/questions/35315404/custom-init-for-uiviewcontroller-in-swift-with-interface-setup-in-storyboard – Larme May 13 '20 at 14:27
  • Yes. That's the error message: Thread 1: Fatal error: init(coder:) has not been implemented. I need to use that struct model in the ViewController, which will receive data from the api. – Tech UK May 13 '20 at 14:32

2 Answers2

0

You might be using storyboards and the method init?(coder: gets called when you try to create this view controller. And inside the init?(coder: you have given a fatal error that causes the error. You need to use the custom initializer that you have created and not use the storyboard provied init?(coder: initializer.

Here is the gist of code you need. But, you will have to make modifications to make it work according to your requirements.

class ViewController: UIViewController {

    var someProperty: String

    init(property: String) {
        someProperty = property
        super.init(nibName: nil, bundle: nil)

        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let viewController = storyboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController

        view = viewController.view
    }

    required init?(coder: NSCoder) {
        someProperty = ""
        super.init(coder: coder)
    }
}
Frankenstein
  • 15,732
  • 4
  • 22
  • 47
  • If I try to use the custom initializer the Xcode complains as I mentioned in my post: Error: 'required' initializer 'init(coder:)' must be provided by subclass of 'UIViewController' – Tech UK May 13 '20 at 14:41
  • I have added a small gist of code. But, it just a helper to understand how cumbersome it could get. Best case scenario would be to use the normal method of instantiating the VC and setting the required variables. – Frankenstein May 13 '20 at 14:50
  • Indeed. It gets messy. I tried that code and gave me this error: Property 'self.someProperty' not initialized at super.init call When you say normal method of instantiating the VC, which method do you mean that would work in my case? Thanks – Tech UK May 13 '20 at 14:56
  • You could remove that error by just providing a default value to your property. I have edited my code to fix that, I missed that line. I have given the method to use to instantiateViewController in the above solution. Use that method in the other VC and set your property value. – Frankenstein May 13 '20 at 15:02
  • It works if it string but the type is ImageRequest, and how will I give a default value to someProperty of type ImageRequest? – Tech UK May 13 '20 at 15:07
  • I also tried this: var someProperty = ImageRequest(), but it gives this error: Missing argument for parameter 'from' in call Insert 'from: <#Decoder#>' – Tech UK May 13 '20 at 15:12
0

A view controller in a storyboard is always initialized with init?(coder:). You can't pass any parameters to that initializer other than the coder that iOS passes.

So, you're going to have to devise another method to initialize images. Possible options

  1. Initialize it in init?(coder:).
  2. Declare it as an optional and initialize it in viewDidLoad()
  3. If the view controller is reached via segue, declare it as an optional and assign a value to it in the source VC's prepareForSegue(_:sender:) method.

The method you choose is very much dependent on your app's architecture and on where the data for ImageRequest comes from.

Rudedog
  • 4,323
  • 1
  • 23
  • 34