Challenge "Programmatic ViewController" Solution

In case someone needs help with this, here is my solution:

[code]class ImageViewController: NSViewController {

var image : NSImage?

private lazy var imageView : NSImageView = {
    let iv = NSImageView()
    iv.translatesAutoresizingMaskIntoConstraints = false
    iv.imageScaling = .ScaleProportionallyUpOrDown
    iv.bind(NSValueBinding, toObject: self, withKeyPath: "image", options: nil)
    return iv
    }()

override func viewDidLoad() {
    super.viewDidLoad()
    setupConstraints()
}

override func loadView() {
    // The XIB would define the initial size
    let initialFrame = NSRect(x: 0, y: 0, width: 500, height: 300)
    
    view = NSView(frame: initialFrame)
    view.addSubview(imageView)
}

func setupConstraints() {
    
    let views = ["imageView" : imageView]
    let horizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("|[imageView]|", options: [], metrics: nil, views: views)
    let verticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("V:|[imageView]|", options: [], metrics: nil, views: views)
    
    view.addConstraints(verticalConstraints)
    view.addConstraints(horizontalConstraints)
}

deinit {
    imageView.unbind(NSValueBinding)
}

}[/code]

1 Like

Thank you for this! I did have one issue with it, the view was going exactly to the edge of the window. After playing with different constraints, I came up with this:

import Cocoa

class ImageViewController: NSViewController {
  var image: NSImage?
  let imageView = NSImageView()

  override func viewDidLoad() {
    super.viewDidLoad()
    setupConstraints()
  }

  override func loadView() {
    let initialFrame = NSRect(x: 0, y: 0, width: 480, height: 272)

    view = NSView(frame: initialFrame)
    imageView.image = image
    imageView.imageScaling = .ScaleProportionallyUpOrDown

    view.addSubview(imageView)
  }

  func setupConstraints() {
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.topAnchor.constraintEqualToAnchor(view.topAnchor, constant: 20).active = true
    imageView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor, constant: -20).active = true
    imageView.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor, constant: 20).active = true
    imageView.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor, constant: -20).active = true
  }
}

I also am not a big fan of bindings or the autolayout visual format, so others can compare a few things here.