Search code examples
iosswiftuiimageviewiboutletviewdidload

Why did UIImageView did not load properly using Swift


basically I want to create road where hero will move on before game starts, so user can see his first steps, but the problem is that when I post code in override func viewDidLoad it only load image appearance what I post in Main.storyboard not that code,using print it shows that images are in place them need to be, but that's not what I see on screen. In alternative, I place same code in @IBAction func play and after I press play button images load as them need to be.Here are code that I put in viewDidLoad:

@IBOutlet weak var hero: UIImageView!
@IBOutlet weak var bigroad: UIImageView!
@IBOutlet weak var road: UIImageView!
@IBOutlet weak var roadTwo: UIImageView!
@IBOutlet weak var play: UIButton!
override func viewDidLoad() {
     super.viewDidLoad()

     self.play.hidden = false
     self.hero.hidden = false
     self.bigroad.hidden = false
     self.road.hidden = false
     self.roadTwo.hidden = false

     self.hero.center.x = (width / 2) + 3
     self.hero.center.y = ((height / 2.5) + (height / 3.5)) - 46
     self.bigroad.center = CGPointMake(width / 2 , (height / 2.5) + (height / 3.5))
     self.road.center = CGPointMake(width / 2  + 39, (height / 2.5) + (height / 3.5) - 29)
     self.roadTwo.center = CGPointMake((width / 2 ) + 78, ((height / 2.5) + (height / 3.5)) - 58)

As I said, when I put his same code in @IBAction func play and when func play starts everything is in place. My question is why images didn't load in place were them need to be in viewDidLoad, but loads perfectly in play function? What Do I do wrong and how can I prevent my mistake?


Solution

  • You need to move your frame code to point, when all autolayout processes are finished. For example:

    var layedOut = false
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        if !layedOut {
            // perform your frame code
            self.hero.center.x = (width / 2) + 3
            self.hero.center.y = ((height / 2.5) + (height / 3.5)) - 46
            self.bigroad.center = CGPointMake(width / 2 , (height / 2.5) + (height / 3.5))
            self.road.center = CGPointMake(width / 2  + 39, (height / 2.5) + (height / 3.5) - 29)
            self.roadTwo.center = CGPointMake((width / 2 ) + 78, ((height / 2.5) + (height / 3.5)) - 58)
        }
    }
    

    Note that viewDidLayoutSubviews can be called multiple times, so you need catch point when all is already on screen and disable frame initialization code in this method, with flag for example

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        layedOut = true
    }
    
    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        layedOut = false
    }