2

scroll view - layout programmatically - swift 3

Dear friends: I hope someone could revise this project and help me before my brain been burned. Thanks in advance.

The task: Horizontal Scroll - Layout an array of 4 images, square of 240 x 240 and 20 of spacing. The constraints for the scroll view set directly in the storyboard, but the images subviews had been added programmatically using Visual Format Language. Content size for scroll suppose done by this constraints.

What I have done: Set the array of images, create de ImageView programmatically and add the array using a for in loop. Create the constraints using the visual format. A way to do this can be found in this article: http://www.apeth.com/iOSBook/ch20.html.

Here the link to the project in GitHub https://github.com/ricardovaldes/soloScrollEjercicio

Constraints for the ScrollView added directly in the storyboard.

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var myScroll: UIScrollView!

    var carsArray = [UIImage]()
    var constraints = [NSLayoutConstraint]()

    override func viewDidLoad() {
        super.viewDidLoad()

        carsArray = [#imageLiteral(resourceName: "fasto1"), #imageLiteral(resourceName: "fasto2"), #imageLiteral(resourceName: "fasto3"), #imageLiteral(resourceName: "fasto4")]

        var const = [NSLayoutConstraint]()
        var views: [String: UIView]
        var previous: UIImageView? = nil

        for index in 0..<carsArray.count{
            let newImageView = UIImageView()
            newImageView.image  = carsArray[index]
            newImageView.translatesAutoresizingMaskIntoConstraints = false
            myScroll.addSubview(newImageView)
            self.myScroll.setNeedsLayout()


            views = ["newImageView": newImageView, "myScroll": myScroll]

            if previous == nil{
                const.append(contentsOf: NSLayoutConstraint.constraints(withVisualFormat: "H:|[newImageView(240)]",  metrics: nil, views: views))
            }
            else{
                const.append(contentsOf: NSLayoutConstraint.constraints(withVisualFormat: "H:[previous]-20-[newImageView(240)]", metrics: nil, views: ["newImageView": newImageView, "previous": previous!]))
            }

            previous = newImageView

            const.append(contentsOf: NSLayoutConstraint.constraints(withVisualFormat: "H:[previous]|", metrics: nil, views: ["previous": newImageView]))

            const.append(contentsOf: NSLayoutConstraint.constraints(withVisualFormat: "V:|[newImageView(240)]|", metrics: nil, views: views))

        }
        NSLayoutConstraint.activate(const)
    }
}

Even though I have tried a lot of combinations I have the same error:

2018-04-29 21:24:34.347466-0500 soloScrollEjercicio[12002:1665919] [LayoutConstraints] Unable to simultaneously satisfy constraints.

rmaddy
  • 314,917
  • 42
  • 532
  • 579

1 Answers1

0

each loop round, you add a right side pin constraint to scroll view for every new added imageView, but there is 20 points between each other.

 |-previous-20-newOne-|                                ** second round loop **
                     -20-newOne'-|                     ** third round loop  **

this breaks imageView width(240) constraint

one way deal with it: only add right side pin constraint to the last imageView.

enter image description here

enter image description here

scroll view constraint in your main storyboard also has a break.

+-------------------+
|          |        |
|-scroll view (240)-|

the bottom one with vertical spacing to super view should not be there. it would break the scroll view height(240), so delete it will be fine.

maybe you should try:

  • set it's constraint priority to 999, or some other value not equal to 1000
  • uncheck installed box
  • delete it

enter image description here


and now, your scroll view should be OK.

enter image description here


p.s. I found your reference book is based on iOS 6? in the year 2018, starts from iOS 10 or iOS 11 may be a better choice.

happy hacking :)

vg0x00
  • 588
  • 4
  • 11
  • Thank you for your quick response. Where exactly did you put the right side pin? If I put it after the "previous = newImageView" still obtain the same error:'Unable to parse constraint format: previous is not a key in the views dictionary. H:[previous]-20-| – acidosulfurico50 Apr 30 '18 at 06:08
  • not add a new one, but insert a "condition filter" in each loop, to make it only add right side pin constraint on the last image view. I post a full pic snapshot, may gives a little help. :) – vg0x00 Apr 30 '18 at 06:21
  • Great help. vg0x00. I do really thank you. It works perfectly. By the way, this pariticularly approach for the arrays is not present in other comments and questions in stackoverflow. I think will be very helpful for others. – acidosulfurico50 Apr 30 '18 at 06:45
  • nice :))) if it works, accept this answer, wo-hoo... – vg0x00 Apr 30 '18 at 06:53
  • I am new in stack. where exactly should I accept this answer. Where should I click? – acidosulfurico50 Apr 30 '18 at 06:56