Can't add NSLayoutConstraints programmatically in Swift (no effect) - ios

I've created a custom UIView subclass in Swift with a corresponding .xib file but am having trouble adding Auto Layout constraints during initialization. The view itself loads just fine, but adding layout constraints seems to have no effect on the view's layout, regardless of whether I add these constraints within init or viewDidMoveToSuperview or viewDidMoveToWindow, and even if I call setNeedsUpdateConstraints() / layoutIfNeeded() immediately after.
I can do this quite easily in Objective-C, so hopefully this is a very simple fix, but I can't figure out what I am doing wrong.
Here is my code:
var isLoading = false
class CustomSubview: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
private lazy var view: UIView! = { [unowned self] in
let bundle = NSBundle(forClass: self.dynamicType)
let nibName = String(CustomSubview.self)
let nib = UINib(nibName: nibName, bundle: bundle)
return nib.instantiateWithOwner(self, options: nil)[0] as! UIView
}()
private func setup() {
if (isLoading) {
return
}
isLoading = true
// self.view.frame = self.bounds // this works but I want to use Auto Layout
// self.view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight] // this works but I want to use Auto Layout
self.translatesAutoresizingMaskIntoConstraints = false // no effect
addSubview(self.view)
let views = Dictionary(dictionaryLiteral: ("view", self.view))
let horizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("H:|[view]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)
self.addConstraints(horizontalConstraints)
NSLayoutConstraint.activateConstraints(horizontalConstraints) // this seems to do nothing
let verticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("V:|[view]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)
self.addConstraints(verticalConstraints)
NSLayoutConstraint.activateConstraints(verticalConstraints) // this seems to do nothing
self.setNeedsUpdateConstraints()
self.layoutIfNeeded()
isLoading = false
}
}

I've reworked your class a bit to make it look a bit cleaner. I've omitted the loading Bool. Also I have no experience in creating views from a XIB file I pretty much left it almost untouched.
var isLoading = false
class CustomSubview: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
private lazy var customView: UIView = {
let bundle = NSBundle(forClass: self.dynamicType)
let nibName = String(CustomSubview.self)
let nib = UINib(nibName: nibName, bundle: bundle)
let customView = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
customView.translatesAutoresizingMaskIntoConstraints = false
return customView
}()
private func setup() {
if (isLoading) {
return
}
isLoading = true
addSubview(self.customView)
let views = ["customView": customView]
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[customView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views))
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[customView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views))
isLoading = false
}
}
As for your aspect ratio constraint, you can set multiple constraint for your aspect ratio and set the active of those to true / false to switch between them.

Related

Button on UIView does not respond unless I specify the correct CGRect

I am trying to implement a simple UIView that will show at the bottom of the screen when internet connection is lost and will have a dismiss button. My UIView class looks something like this.
import UIKit
class ConnectionLostAlertUIView: UIView {
#IBOutlet var view: UIView!
var viewConstraints: [NSLayoutConstraint] = []
override init(frame: CGRect) {
super.init(frame: frame)
Bundle.main.loadNibNamed("ConnectionLostAlertView", owner: self, options: nil)
self.addSubview(self.view)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
Bundle.main.loadNibNamed("ConnectionLostAlertView", owner: self, options: nil)
self.addSubview(self.view)
}
override func didMoveToSuperview() {
view.translatesAutoresizingMaskIntoConstraints = false
let bottomConstraint = view.bottomAnchor.constraint(equalTo: self.superview!.bottomAnchor)
let leftConstraint = view.leadingAnchor.constraint(equalTo: self.superview!.leadingAnchor)
let rightConstraint = view.trailingAnchor.constraint(equalTo: self.superview!.trailingAnchor)
viewConstraints = [bottomConstraint, leftConstraint, rightConstraint]
NSLayoutConstraint.activate(viewConstraints)
}
#IBAction func dismissButton(_ sender: Any) {
Logger.log(message: "Dismiss button was pressed", event: .d)
self.isHidden = true
}
And I add this UIView to my UIViewController by doing the following
var ConnectionLostAlert: ConnectionLostAlertUIView!
ConnectionLostAlert = ConnectionLostAlertUIView(frame: CGRect.zero)
self.view.addSubview(ConnectionLostAlert)
Well, I can use actual values for CGRect instead of zero but the problem is that after the constraints are added in my UIView, the button in my UIView stops responding. It works just fine if I actually set some CGRect coordinates and not use constraints in the UIView. Is there a better way to do what I am trying to achieve that will still allow me to handle the button event inside the UIView?
The problem is you are adding constraints from the inner view i.e view to the superview skipping the main view (ConnectionLostAlertUIView) that is actually being added to the super view.
What you should do instead is to add constraints between view and self first. Then when self(ConnectionLostAlertUIView) is added to the superview, add the constraints with super view then.
Do something like this:
#IBOutlet var view: UIView!
var viewConstraints: [NSLayoutConstraint] = []
override init(frame: CGRect) {
super.init(frame: frame)
Bundle.main.loadNibNamed("ConnectionLostAlertView", owner: self, options: nil)
self.addSubview(self.view)
view.translatesAutoresizingMaskIntoConstraints = false
let bottomConstraint = view.bottomAnchor.constraint(equalTo: self.bottomAnchor)
let leftConstraint = view.leadingAnchor.constraint(equalTo: self.leadingAnchor)
let rightConstraint = view.trailingAnchor.constraint(equalTo: self.trailingAnchor)
viewConstraints = [bottomConstraint, leftConstraint, rightConstraint]
NSLayoutConstraint.activate(viewConstraints)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
Bundle.main.loadNibNamed("ConnectionLostAlertView", owner: self, options: nil)
self.addSubview(self.view)
}
override func didMoveToSuperview() {
self.translatesAutoresizingMaskIntoConstraints = false
let bottomConstraint = self.bottomAnchor.constraint(equalTo: self.superview!.bottomAnchor)
let leftConstraint = self.leadingAnchor.constraint(equalTo: self.superview!.leadingAnchor)
let rightConstraint = self.trailingAnchor.constraint(equalTo: self.superview!.trailingAnchor)
viewConstraints = [bottomConstraint, leftConstraint, rightConstraint]
NSLayoutConstraint.activate(viewConstraints)
}
#IBAction func dismissButton(_ sender: Any) {
Logger.log(message: "Dismiss button was pressed", event: .d)
self.isHidden = true
}

iOS - How to initialize custom UIView with specific Frame from NIB

I am wondering what is the cleanest way to initialize a custom UIView with a specific frame.
The UIView is designed from a XIB file.
Here is my implementation :
class CustomView : UIView {
#IBOutlet var outletLabel: UILabel!
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
public override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
private func setupView() {
// Set text for labels
}
}
Here is how I want to initialize it in my ViewController :
let screenSize: CGRect = UIScreen.main.bounds
let screenWidth = screenSize.width
let frame = CGRect(x: 0, y: 0, width: screenWidth - 50, height: 70)
let customView = CustomView.init(frame: frame)
But it is not working, I have a white UIView without any outlets.
And if I do this instead :
// Extension to UIView to load Nib
let customView : CustomView = UIView.fromNib()
I can see my view from XIB file, with its width/height used in the Interface Builder.
What is I want to load the view from XIB file BUT with specific frame ?
Am I missing something about initialization ?
You can have a NibLoading class like:
// NibLoadingView.swift
//source:https://gist.github.com/winkelsdorf/16c481f274134718946328b6e2c9a4d8
import UIKit
// Usage: Subclass your UIView from NibLoadView to automatically load a xib with the same name as your class
#IBDesignable
class NibLoadingView: UIView {
#IBOutlet weak var view: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
nibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
nibSetup()
}
private func nibSetup() {
backgroundColor = .clear
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.translatesAutoresizingMaskIntoConstraints = true
addSubview(view)
}
private func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of:self))
let nib = UINib(nibName: String(describing: type(of:self)), bundle: bundle)
let nibView = nib.instantiate(withOwner: self, options: nil).first as! UIView
nibView.anchorAllEdgesToSuperview()
return nibView
}
}
extension UIView {
func anchorAllEdgesToSuperview() {
self.translatesAutoresizingMaskIntoConstraints = false
if #available(iOS 9.0, *) {
addSuperviewConstraint(constraint: topAnchor.constraint(equalTo: (superview?.topAnchor)!))
addSuperviewConstraint(constraint: leftAnchor.constraint(equalTo: (superview?.leftAnchor)!))
addSuperviewConstraint(constraint: bottomAnchor.constraint(equalTo: (superview?.bottomAnchor)!))
addSuperviewConstraint(constraint: rightAnchor.constraint(equalTo: (superview?.rightAnchor)!))
}
else {
for attribute : NSLayoutAttribute in [.left, .top, .right, .bottom] {
anchorToSuperview(attribute: attribute)
}
}
}
func anchorToSuperview(attribute: NSLayoutAttribute) {
addSuperviewConstraint(constraint: NSLayoutConstraint(item: self, attribute: attribute, relatedBy: .equal, toItem: superview, attribute: attribute, multiplier: 1.0, constant: 0.0))
}
func addSuperviewConstraint(constraint: NSLayoutConstraint) {
superview?.addConstraint(constraint)
}
}
Then your view will subclass the NibLoadingClass like:
class YourUIView: NibLoadingView {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Set your XIB class in File's Owner like:
In this case it will be YourUIView
Then instantiate it:
let myView = YourUIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width-60, height: 170))
You can create custom class like this...
import UIKit
class CustomView: UIView {
class func mainView() -> CustomView {
let nib = UINib(nibName: "nib", bundle: nil)
let view = nib.instantiate(withOwner: self, options: nil).first as! CustomView
return view
}
override init(frame: CGRect) {
super.init(frame: frame)
let view = CustomView.mainView()
view.frame = frame
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Initialize view where you want...
let view = CustomView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.backgroundColor = UIColor.blue
self.view.addSubview(view)

Swift: Adding Taps to Custom Views

I would like to add taps to views which subclasses another view, but my current approach does not get invoked, ie the seatNumber does not get printed when my seats are tapped as coded in the handleTap function. I have adapted my approach from the following this post and this. My code thus far:
//My viewController
class ViewController: UIViewController, UIScrollViewDelegate {
let scrollView = UIScrollView()
let cinema: CinemaView = {
let v = CinemaView()
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
let seat1 = SeatView()
seat1.isVacant = false
seat1.seatNumber = "2A"
let seat2 = SeatView()
seat2.isVacant = true
seat2.seatNumber = "3B"
cinema.seats = [seat1, seat2]
let tap = UITapGestureRecognizer(target: seat1, action: #selector(handleTap))
seat1.addGestureRecognizer(tap)
seat1.isUserInteractionEnabled = true
view.addSubview(scrollView)
scrollView.addSubview(cinema)
}
#objc func handleTap(_ seat: SeatView) {
if let seatNumber = seat.seatNumber {
print("\(seatNumber) is tapped")
} else {
print("Seat tapped")
}
}
//My custom cinemaView
class CinemaView: UIView {
var seats = [SeatView]() {
didSet {
for v in self.subviews {
v.removeFromSuperview()
}
var seatRect = CGRect(x: 0, y: 0, width: 20, height: 20)
for seat in seats {
self.addSubview(seat)
seat.frame = seatRect
seatRect.origin.x += seatRect.size.width + 8
}
}
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
//My Custom seatView
class SeatView: UIView {
var isVacant: Bool = true
var seatNumber: String?
override init(frame: CGRect) {
super.init(frame: frame)
}
}
Note: some boilerplate codes have been omitted above to keep the code concise for this question.
My preferred approach is to add these taps inside the VC so that I can pass this info into another VC and push up to Firebase. Any advice would be much appreciated
EDIT: Added screenshot of UI
With the help of 3stud1ant3, I managed to figure out where went wrong.
After observing the view layout, the cinemaView was never added to the view even though the seatViews were added. By defining more constraints to cinemaView in viewDidLoad at the viewController and incorporating 3stud1ant3's code in the below answer post, the tap functions worked.
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
cinema.seats = [seatView1, seatView2]
view.addSubview(scrollView)
scrollView.addSubview(cinema)
let views = ["scrollView": scrollView, "v": cinema] as [String : Any]
let screenHeight = view.frame.height
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[scrollView(\(screenHeight / 2))]", options: NSLayoutFormatOptions(), metrics: nil, views: views))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[scrollView]|", options: NSLayoutFormatOptions(), metrics: nil, views: views))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-60-[v(50)]", options: NSLayoutFormatOptions(), metrics: nil, views: views))
//Previously, the below constraints were not added. Once these are added, the tap function works
cinema.leftAnchor.constraint(equalTo: scrollView.leftAnchor).isActive = true
cinema.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
cinema.widthAnchor.constraint(equalTo: scrollView.widthAnchor ,constant: 100).isActive = true
}

Import Nib View in Storyboard ViewController

Swift 3 - Xcode 8 - iOS10
I have a xib file with a UIView. I want import this view in my ViewController.
My Player.xib
And my Storyboard result :
And my Class:
#IBDesignable
class EmbedPlayerViewV2: UIView {
#IBOutlet weak var subTitleLbl: UILabel!
var view: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
loadViewFromNib()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadViewFromNib()
}
func loadViewFromNib() {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "Player", bundle: bundle)
self.view = nib.instantiate(withOwner: self, options: nil).first as! UIView
self.addSubview(self.view)
}
override func layoutSubviews() {
subTitleLbl.text = "LOADED"
// ...
}
// ...
}
I have solved my problem.
func loadViewFromNib() {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "Player", bundle: bundle)
self.view = nib.instantiate(withOwner: self, options: nil).first as! UIView
self.addSubview(view)
view.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
view.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
view.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
view.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
}
Tanks Aaron

subclass of a generic UIViewController subclass isn't available in InterfaceBuilder [duplicate]

This question already has answers here:
Xcode 7 Swift 2 impossible to instantiate UIViewController subclass of generic UITableViewController
(2 answers)
Closed 6 years ago.
I have a generic UIViewController subclass that expects a type that is a subclass of UIView and also implements a specific protocol. I have a subclass of that generic UIViewController subclass. I have a view controller in a story board with it's type set to MyKeyboardAwareScrollViewController (the subclass of the generic UIViewController subclass). When I run my program I get a message:
Unknown class _TtC19ExploreCodeCoverage35MyKeyboardAwareScrollViewController in Interface Builder file.
Any ideas why/how to fix?
A protocol:
protocol MyProtocol{
func widgets() -> Void
func activeView() -> UIView?
}
A Generic View Controller Subclass (that requires a type that is a UIView implementing the protocol MyProtocol):
class KeyboardAwareScrollViewController<T:UIView where T:MyProtocol>: UIViewController {
private let titleView: UIView
private let contentView: T
private weak var scrollView: UIScrollView?
private weak var titleViewContainer: UIView?
init(titleView:UIView, contentView: T){
self.titleView = titleView
self.contentView = contentView
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
self.titleView = aDecoder.decodeObjectOfClass(UIView.self, forKey: "titleView")!
self.contentView = aDecoder.decodeObjectOfClass(T.self, forKey: "contentView")!
super.init(coder: aDecoder)
}
override func viewWillAppear(animated: Bool) {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardShown:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardHidden:", name: UIKeyboardWillHideNotification, object: nil)
}
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func keyboardShown(notification: NSNotification){
let kbSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
if let scrollView = scrollView{
let insets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: kbSize.height, right: 0.0)
scrollView.contentInset = insets
scrollView.scrollIndicatorInsets = insets
if let activeField = self.contentView.activeView(){
let convertedFrame = scrollView.convertRect(activeField.superview!.bounds, fromView: activeField.superview!)
let offsetFrame = CGRectOffset(convertedFrame, 0.0, 19.0)
let frame = CGRectInset(offsetFrame, 0.0, 17.0)
scrollView.scrollRectToVisible(frame, animated: false)
}
}
}
func keyboardHidden(notification: NSNotification){
if let scrollView = scrollView{
let insets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)
scrollView.contentInset = insets
scrollView.scrollIndicatorInsets = insets
}
}
override func loadView() {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.brownColor()
let sv = UIScrollView()
sv.backgroundColor = UIColor.clearColor()
sv.opaque = false
sv.translatesAutoresizingMaskIntoConstraints = false
sv.alwaysBounceVertical = true
self.scrollView = sv
let titleContainer = buildTitleContainer(self.titleView)
view.addSubview(titleContainer)
view.addSubview(sv)
//peg scroll view to container.
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[scrollView]|", options:NSLayoutFormatOptions(rawValue: 0), metrics:nil, views: ["scrollView":sv]))
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|[scrollView]|", options:NSLayoutFormatOptions(rawValue: 0), metrics:nil, views: ["scrollView":sv]))
let contentViewWrapper = UIView()
contentViewWrapper.translatesAutoresizingMaskIntoConstraints = false
contentViewWrapper.addSubview(self.contentView)
contentViewWrapper.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|->=0-[contentView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["contentView": contentView]))
contentViewWrapper.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|[contentView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["contentView": contentView]))
sv.addSubview(contentViewWrapper)
let viewsDictionary = [
"scrollView": sv,
"view": view,
"contentViewWrapper": contentViewWrapper
]
//peg contentView to be at least as tall as view.
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[contentViewWrapper(>=view)]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewsDictionary))
//peg contentView to be equal to host view width
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|[contentViewWrapper(==view)]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewsDictionary))
//peg title container to width of container.
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|[titleContainer]|",
options:NSLayoutFormatOptions(rawValue: 0),
metrics: nil,
views: ["titleContainer":titleContainer]))
//title view height.
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[titleContainer][contentView]",
options:NSLayoutFormatOptions(rawValue: 0),
metrics: nil,
views: ["titleContainer":titleContainer, "contentView":self.contentView]))
self.view = view
self.titleViewContainer = titleContainer
}
func buildTitleContainer(titleView:UIView) -> UIView{
let titleContainer = UIView()
titleContainer.translatesAutoresizingMaskIntoConstraints = false
titleContainer.backgroundColor = UIColor.orangeColor()
titleContainer.addSubview(titleView)
titleContainer.setContentCompressionResistancePriority(1000.0, forAxis: .Vertical)
titleContainer.addConstraint(NSLayoutConstraint(item: titleView, attribute: .CenterY, relatedBy: .Equal, toItem: titleContainer, attribute: .CenterY, multiplier: 1.0, constant: 0.0))
titleContainer.addConstraint(NSLayoutConstraint(item: titleView, attribute: .CenterX, relatedBy: .Equal, toItem: titleContainer, attribute: .CenterX, multiplier: 1.0, constant: 0.0))
return titleContainer;
}
}
A UIView subclass that implements the protocol:
class MyContentView:UIView, MyProtocol, UITextFieldDelegate{
weak var myActiveView:UIView?
init(){
super.init(frame: CGRectZero)
self.backgroundColor = UIColor.clearColor()
self.opaque = false
self.translatesAutoresizingMaskIntoConstraints = false
let cells = Array(1...12).map{_ in cellView() }
var cellsDictionary: Dictionary<String, UIView> = [:], cellsVerticalFormat = "V:|-"
for (idx, cell) in cells.enumerate(){
self.addSubview(cell)
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|-[cell]-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["cell": cell]))
let cellKey = "cell\(idx)"
cellsDictionary[cellKey] = cell
cellsVerticalFormat = cellsVerticalFormat + "[\(cellKey)]-"
}
cellsVerticalFormat = cellsVerticalFormat + "|"
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(cellsVerticalFormat, options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: cellsDictionary))
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func cellView() -> UIView{
let result = UIView()
result.backgroundColor = UIColor.magentaColor()
result.translatesAutoresizingMaskIntoConstraints = false
let text = UITextField()
text.translatesAutoresizingMaskIntoConstraints = false
result.addSubview(text)
text.delegate = self
result.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|-[text]-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["text": text]))
result.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[text]-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["text": text]))
return result
}
func widgets() {
print("\(MyContentView.self) widgets")
}
func activeView() -> UIView? {
return myActiveView
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool{
myActiveView = textField.superview!
return true
}
func textFieldDidEndEditing(textField: UITextField) {
if myActiveView === textField.superview! {
myActiveView = nil
}
}
func textFieldShouldEndEditing(textField: UITextField) -> Bool {
return true
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return false
}
}
A KeyboardAwareViewController subclass:
class MyKeyboardAwareScrollViewController : KeyboardAwareScrollViewController<MyContentView>{
let myContentView: MyContentView = MyContentView()
let myTitleView: UILabel = {
let result = UILabel()
result.translatesAutoresizingMaskIntoConstraints = false
result.text = "Pretend This Says\nCohn-Reznick"
result.numberOfLines = 0
result.textAlignment = .Center
return result
}()
required init?(coder aDecoder: NSCoder) {
super.init(titleView: myTitleView, contentView:myContentView)
}
}
Answer is here: Xcode 7 Swift 2 impossible to instantiate UIViewController subclass of generic UITableViewController
TLDR; Objective-c and InterfaceBuilder can't "see" generic swift classes.

Resources