Make UITableViewCell editable - ios

Given the Detail View in Apple's tutorial, how do I make the cells in the detail view editable? Not just to add or delete cells, but to modify the text in the cell value (right label in the cell)?

in both your UI and your code, change the UILabel objects to UITextField, hook them up the same way. they will allow editing of text in those fields.
you will then also have to hook up your viewController to fetch them when the user changes them (via delegate setup) and set up your model to accept the data from your delegate implementation.
good luck.

There's a pod for that: https://github.com/fulldecent/FDTextFieldTableViewCell
Here's the relevant code:
self.detailTextLabel?.isHidden = true
self.contentView.viewWithTag(3)?.removeFromSuperview()
self.textField.tag = 3
self.textField.translatesAutoresizingMaskIntoConstraints = false
self.contentView.addSubview(self.textField)
self.addConstraint(NSLayoutConstraint(item: self.textField, attribute: .leading, relatedBy: .equal, toItem: self.contentView, attribute: .leading, multiplier: 1, constant: 50))
self.addConstraint(NSLayoutConstraint(item: self.textField, attribute: .top, relatedBy: .equal, toItem: self.contentView, attribute: .top, multiplier: 1, constant: 8))
self.addConstraint(NSLayoutConstraint(item: self.textField, attribute: .bottom, relatedBy: .equal, toItem: self.contentView, attribute: .bottom, multiplier: 1, constant: -8))
self.addConstraint(NSLayoutConstraint(item: self.textField, attribute: .trailing, relatedBy: .equal, toItem: self.contentView, attribute: .trailing, multiplier: 1, constant: -16))
self.textField.textAlignment = .right

Related

BottomLayoutGuide iOS 10 vs iOS 11

Good day!
I have a trouble with placing a bannerView in my app.
Its a static TableViewController, and the bannerView is supposed to be at the bottom of the screen. I did everything as it is said in Google Mobile SDK.
func positionBannerViewFullWidthAtBottomOfView(_ bannerView: UIView) {
view.addConstraints([
NSLayoutConstraint(item: bannerView,
attribute: .leading,
relatedBy: .equal,
toItem: view,
attribute: .leading,
multiplier: 1,
constant: 0),
NSLayoutConstraint(item: bannerView,
attribute: .trailing,
relatedBy: .equal,
toItem: view,
attribute: .trailing,
multiplier: 1,
constant: 0),
NSLayoutConstraint(item: bannerView,
attribute: .bottom,
relatedBy: .equal,
toItem: bottomLayoutGuide,
attribute: .top,
multiplier: 1,
constant: 0)
]
)
This is how it loads now, slightly below the view:
My guess problem is in the last Constraint, bottomLayoutGuide seems to be leading somewhere when it should not. When I remove last constraint it appears right below NavigationBar.
This problem does not occur on iOS 11+, only on previous versions.

When added to a view, the constraint's items must be descendants of that view (or the view itself).

Here is my following code:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
headerView.backgroundColor = UIColor.white
let headerLabel = UILabel(frame: CGRect(x: 30, y: 0, width:
tableView.bounds.size.width, height: tableView.bounds.size.height))
headerLabel.font = UIFont().robotoMedium(withFontSize: 10)
headerLabel.textColor = CustomColor.lightGrey.color
headerLabel.text = "Travel Shops"
headerLabel.sizeToFit()
headerView.addSubview(headerLabel)
headerLabel.translatesAutoresizingMaskIntoConstraints = false
headerLabel.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .trailing, relatedBy: .equal, toItem: tableView, attribute: .trailing, multiplier: 1, constant: 0))
headerLabel.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .leading, relatedBy: .equal, toItem: tableView, attribute: .leading, multiplier: 1, constant: 0))
headerLabel.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .top, relatedBy: .equal, toItem: self.topLayoutGuide, attribute: .bottom, multiplier: 1, constant: 0))
headerLabel.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 131))
return headerView
}
But the application crashes with the following:
When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView(UIConstraintBasedLayout) _viewHierarchyUnpreparedForConstraint:] to debug.
headerLabel is child view of headerView and headerView is child of TableView in the hierarchy that is why this message is shown you need add the constraints to headerView which is the headerLabel.superView instead of UITableView which is headerLabel.superView.superView
Change your code
headerLabel.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .trailing, relatedBy: .equal, toItem: headerView, attribute: .trailing, multiplier: 1, constant: 0))
headerLabel.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .leading, relatedBy: .equal, toItem: headerView, attribute: .leading, multiplier: 1, constant: 0))
headerLabel.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .top, relatedBy: .equal, toItem: self.topLayoutGuide, attribute: .bottom, multiplier: 1, constant: 0))
headerLabel.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 131))
by this one
headerLabel.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .trailing, relatedBy: .equal, toItem: tableView, attribute: .trailing, multiplier: 1, constant: 0))
headerLabel.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .leading, relatedBy: .equal, toItem: headerView, attribute: .leading, multiplier: 1, constant: 0))
headerLabel.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .top, relatedBy: .equal, toItem: headerView, attribute: .bottom, multiplier: 1, constant: 0))
headerLabel.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 131))
Hope this helps

Xcode adds duplicate constraints?

In code I added 4 constraints. But when I run the app, in UI debugger, it shows additional 6 constraints? It should be all clear with these 4 I added. I don't know what I'm doing wrong?
let leftConstr = NSLayoutConstraint(item: image, attribute: .leading, relatedBy: .equal, toItem: cell.contentView, attribute: .leading, multiplier: 1.0, constant: 0.0)
let bottomConstr = NSLayoutConstraint(item: image, attribute: .bottom, relatedBy: .equal, toItem: cell.contentView , attribute: .bottom, multiplier: 1.0, constant: 0.0)
let highthConstr = NSLayoutConstraint(item: image, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 15)
let widthConstr = NSLayoutConstraint(item: image, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 50)
cell.contentView.addConstraints([highthConstr, widthConstr, bottomConstr, leftConstr])
Here is the screenshot of my UI debugger
Maybe you can try to add this line of code before :
image.translatesAutoresizingMaskIntoConstraints = false

Move Ad Banner down below Status Bar using NSLayoutConstraint Swift

In Swift, I am trying to add a Google Smart Ad Banner using NSLayoutConstraints at the top of the view, but below the status bar by 14 points. I've been trying for ages now with various different attributes and top or topLayoutGuide.
Link to Image
let xConstraint = NSLayoutConstraint(item: bannerView, attribute: .centerX,
relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1, constant: 0)
let pinTop = NSLayoutConstraint(item: bannerView, attribute: .top,
relatedBy: .equal, toItem: self.topLayoutGuide, attribute: .top, multiplier: 1, constant: 14)
self.view.addSubview(bannerView)
self.view.addConstraint(xConstraint)
self.view.addConstraint(pinTop)
You’re pinning the banner to the top of the topLayoutGuide, but what you really want is the bottom of the topLayoutGuide, so that it will start below the status bar:
let pinTop = NSLayoutConstraint(item: bannerView,
attribute: .top,
relatedBy: .equal,
toItem: self.topLayoutGuide,
attribute: .bottom,
multiplier: 1,
constant: 14)

UITextField autolayout with margins programmatically

I'm new to AutoLayout and would like to display my UITextField at 100% width with a consistent 15px left and right margin, like so:
Typically I would do this using CGRect, setting the width to the containing view's width minus 30px, then offset the left side by 15px:
searchTextField.frame = CGRectMake(15, 0, view.frame.width - 30, 50)
But I'd like to learn AutoLayout for this sort of thing, since it's the way to go these days. I should note that I am doing everything programmatically -- no Storyboards here.
I'd love it if someone could help me out!
Update
Wow! Thank you for all the responses. I believe all of them would achieve what I'm trying to do, but there can only be one :)
Usually I use for this cocoapod that is dealing with constraints, but if you need pure apple solution documentation states:
You have three choices when it comes to programmatically creating
constraints: You can use layout anchors, you can use the
NSLayoutConstraint class, or you can use the Visual Format Language.
Approach with NSLayoutConstraints in your case would be:
NSLayoutConstraint(item: textField, attribute: .Leading, relatedBy: .Equal, toItem: parentView, attribute: .LeadingMargin, multiplier: 1.0, constant: 15.0).active = true
NSLayoutConstraint(item: textField, attribute: .Trailing, relatedBy: .Equal, toItem: parentView, attribute: .TrailingMargin, multiplier: 1.0, constant: -15.0).active = true
NSLayoutConstraint(item: textField, attribute: .Top, relatedBy: .Equal, toItem: parentView, attribute: .TopMargin, multiplier: 1.0, constant: 50.0).active = true
Remember that if you don't have any constraints in the view, they would be added automatically and you'll have to deal with them and conflicts that would be created by adding new constraints on runtime. To avoid this you could either create textField manually and add it to the view or set constraints with low priority in the Interface Builder .
Assuming the parent of the text field is view, do this after view.addSubview(searchTextField):
NSLayoutConstraint.activateConstraints([
searchTextField.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor, constant: 15),
searchTextField.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor, constant: -15),
])
Use this code:
let topConstraint = NSLayoutConstraint(item: textField, attribute: NSLayoutAttribute.Top, relatedBy: .Equal, toItem: self.view, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0)
let trailingConstraint = NSLayoutConstraint(item: textField, attribute: NSLayoutAttribute.Trailing, relatedBy: .Equal, toItem: self.view, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 15)
let leadingConstraint = NSLayoutConstraint(item: textField, attribute: NSLayoutAttribute.Leading, relatedBy: .Equal, toItem: self.view, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 15)
let heightConstraint = NSLayoutConstraint(item: textField, attribute: NSLayoutAttribute.Height, relatedBy: .Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 50)
self.view.addConstraint(topConstraint )
self.view.addConstraint(trailingConstraint)
self.view.addConstraint(leadingConstraint)
self.view.addConstraint(heightConstraint)
Set the constraints in storyboard.
Click on the text field then click on in the bottom left. From there you can choose constraints like that.
To use Auto Layout, you need to define constraints for your text field.Here, I have created four constraints(Leading, Trailing, Top and Height) related to its superview.
func addLabelConstraints(superView:UIView) {
let leading = NSLayoutConstraint(item: searchTextField, attribute: .Leading, relatedBy: .Equal, toItem: superView, attribute: .Leading, multiplier: 1, constant: 15)
superview!.addConstraint(leading)
let trailing = NSLayoutConstraint(item: searchTextField, attribute: .Trailing, relatedBy: .Equal, toItem: superView, attribute: .Trailing, multiplier: 1, constant: 15)
superView.addConstraint(trailing)
let top = NSLayoutConstraint(item: searchTextField, attribute: .Top, relatedBy: .Equal, toItem: superView, attribute: .Top, multiplier: 1, constant: 0)
superView.addConstraint(top)
let height = NSLayoutConstraint(item: searchTextField, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .Height, multiplier: 0, constant: 50)
superView.addConstraint(height)
}

Resources