Search code examples
iosiphoneswiftipad

Class 'ProductDetailViewController' has no initializers


I am trying to create scrollable imageview. Currently using swift 4.0. While running I am getting "has no initializers" error. I am not sure what code brought this error. I am new to swift and I am unable to track what is going on.

Class 'ProductDetailViewController' has no initializers I am getting this error.

Can any one please tell me how to fix this error.

Entire view controller code is given below. Thanks in advance

import UIKit
import SwiftyJSON
class ProductDetailViewController: UIViewController,UIScrollViewDelegate {

    //Outlers
    @IBOutlet weak var scrollView: UIScrollView!

    //Global variables
    var productDict : JSON = []
    var arrayOfProductImageUrls :  Array<Any> = []
    var zoomScroll : UIScrollView

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        self.initialSetup()
        self.scrollViewSetup()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    }
    */




    //Mark: - Scrollview Setup

    func initialSetup() {
        self.scrollView.delegate = self
    }

    func scrollViewSetup() {

        let productsArray : Array = self.arrayOfProductImageUrls;
        self.scrollView.backgroundColor = UIColor.white

        var frame : CGRect = CGRectMake(0, 0, self.scrollView.frame.size.width, 360)

        for (index, value) in productsArray.enumerated() {

            //Imageview Setup
            let productImageView : UIImageView
            let width : NSInteger = Int(frame.width)
            productImageView.frame.origin.x = CGFloat(Int (width * index))
            productImageView.frame.origin.y = 0

            //Scrollview Setup
            zoomScroll.frame = frame;
            zoomScroll.backgroundColor = UIColor.clear
            zoomScroll.showsVerticalScrollIndicator = false
            zoomScroll.showsHorizontalScrollIndicator = false
            zoomScroll.delegate = self
            zoomScroll.minimumZoomScale = 1.0
            zoomScroll.maximumZoomScale = 6.0
            zoomScroll.tag = index
            zoomScroll.isScrollEnabled = true




            self.scrollView.addSubview(zoomScroll)


            //Setting image
            let imageUrl : URL =  (productsArray[index] as AnyObject).url
            productImageView.sd_setImage(with: imageUrl)

            if index < productsArray.count {

                productImageView.frame = zoomScroll.bounds
                productImageView.contentMode = UIViewContentMode.redraw
                productImageView.clipsToBounds = true
                productImageView.backgroundColor = UIColor.clear
                zoomScroll.addSubview(productImageView)

            }

            self.scrollView.contentSize = CGSizeMake(CGFloat(frame.origin.x) + CGFloat(width), productImageView.frame.size.height)

        }

    }


    //Mark : Custom methods
    func CGRectMake(_ x: CGFloat, _ y: CGFloat, _ width: CGFloat, _ height: CGFloat) -> CGRect {
        return CGRect(x: x, y: y, width: width, height: height)
    }


    func CGSizeMake(_ width: CGFloat, _ height: CGFloat) -> CGSize {
        return CGSize(width: width, height: height)
    }

}

Solution

  • @Saurabh Prajapati. Nice and quick catch.

    For more, The Swift Programming Language states

    Classes and structures must set all of their stored properties to an appropriate initial value by the time an instance of that class or structure is created. Stored properties cannot be left in an indeterminate state.

    You can set an initial value for a stored property within an initializer, or by assigning a default property value as part of the property’s definition.

    Let me explain more, the problem was with scrollView property that does not have a default value. As above mentioned, all variables in Swift must always have a value or nil (make it optional). When you make it optional, you allow it to be nil by default, removing the need to explicitly give it a value or initialize it.

    Here we are using ! optional so the default value will be nil

    class ViewController : UIViewController {
        @IBOutlet weak var scrollView: UIScrollView!
    }
    

    Setting nil as the default value

    class ViewController : UIViewController {
        @IBOutlet weak var scrollView: UIScrollView! = nil
    }
    

    Setting the default value, creating an object now it is not nil.

    class ViewController : UIViewController {
        @IBOutlet weak var scrollView: UIScrollView = UIScrollView()
    }
    

    But we can't-do like that, we are not setting the default value here.

    class ViewController : UIViewController {
        @IBOutlet weak var scrollView: UIScrollView
    }
    

    I hope it will help.