Custom Class UIView - not changed - swift

Why in the code below, text changes as value, but there is no change in UIVIew. How do I refresh the data in a custom class? The value changes but does not refresh in the view. I have no ideas anymore.
ViewController.swift:
let SB = StatusBar()
SB.update()
StatusBar.swift:
class StatusBar: UIView {
#IBOutlet var view: UIView!
#IBOutlet weak var Status: UITextField!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
}
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
func update() {
Status.text = "ok"
print(Status.text)
print("status updated.")
}
func xibSetup() {
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [UIView.AutoresizingMask.flexibleWidth, UIView.AutoresizingMask.flexibleHeight]
addSubview(view)
}
func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of:self))
let nib = UINib(nibName: "StatusBar", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
}

You are not calling update(). In xibSetup(), add update()

Related

Call to IBOutlet in custom UIView from another class

I am looking for a way to refer to the IBOutlet variable in a custom class UIView, from another class. I found layoutSubviews, but each change only works on the first call, and not on each subsequent call. Thanks for help!
ViewController class:
var SB = StatusBar()
SB.update(1)
SB.update(2)
SB.update(3)
StatusBar class:
class StatusBar: UIView {
#IBOutlet var view: UIView!
#IBOutlet weak var label: UILabel!
var ActualStatus: Int!
required init?(coder: NSCoder) {
super.init(coder: coder)
xibSetup()
}
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
func update(status) {
ActualStatus = status
self.layoutSubviews()
}
override func layoutSubviews() {
super.layoutSubviews()
label.text = ActualStatus
}
func xibSetup() {
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [UIView.AutoresizingMask.flexibleWidth, UIView.AutoresizingMask.flexibleHeight]
addSubview(view)
}
func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of:self))
let nib = UINib(nibName: "StatusBar", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
}
Result: label.text is 1, change only works on the first call

Button on subview untouchable after add to view program

I try to add a subview to a view, but after added, the button on subview is untouchable. I have check the status of button, user interaction is enable. and after add subview, the UI of subview are show up correctly.
The subview class:
class ErrorInfoView: UIView {
#IBOutlet var containerView: UIView!
#IBOutlet weak var messageLabel: UILabel!
var callback: (()->())?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
func commonInit() {
Bundle.main.loadNibNamed("ErrorInfoView", owner: self, options: nil)
containerView.frame = self.bounds
containerView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
containerView.backgroundColor = UIColor.clear
addSubview(containerView)
}
func configure(message: String, callback: #escaping ()->()) {
self.messageLabel.text = message
self.callback = callback
}
#IBAction func pressRetryButton(_ sender: UIButton) {
self.callback?()
}
}
The parent view:
let errorView = ErrorInfoView(frame: self.tableViewContainer.frame)
errorView.configure(message: error) {
// do something, but not be called
}
self.tableViewContainer.addSubview(errorView)
self.tableViewContainer.bringSubviewToFront(errorView)
errorView.translatesAutoresizingMaskIntoConstraints = false
let horizontalConstraint = errorView.centerXAnchor.constraint(equalTo: self.tableViewContainer.centerXAnchor)
let verticalConstraint = errorView.centerYAnchor.constraint(equalTo: self.tableViewContainer.centerYAnchor)
self.tableViewContainer.addConstraints([horizontalConstraint, verticalConstraint])

iOS Charts Marker View

I created a custom MarkerView from a .xib but it's always not centered in the proper set.
final class ChartMarkerView: MarkerView, ViewLoadable {
#IBOutlet weak var laValue: UILabel!
override required init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
}
func setUI() {
}
public override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
laValue.text = String(entry.y)
layoutIfNeeded()
}
}
protocol ViewLoadable {
var nibName: String { get }
}
extension ViewLoadable where Self: UIView {
var containerView: UIView? { return subviews.first }
var nibName: String { return String(describing: type(of: self)) }
func loadViewFromXib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: nibName, bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil).first as! UIView
return view
}
func xibSetup() {
let view = loadViewFromXib()
view.frame = bounds
view.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleBottomMargin, .flexibleTopMargin]
view.autoresizesSubviews = true
backgroundColor = .clear
addSubview(view)
}
}
Turns out I just need to calculate the offset of the MarkerView and set it when loading the view:
offset.x = -self.frame.size.width / 2.0
offset.y = -self.frame.size.height - 7.0

Could not cast value of type UIView to [CustomView] using Xib

I've seen a number of similar questions, but many aren't up-to-date, and none have fixed my issue.
I have a custom Xib and class, CardView. When I try to instantiate it in code, I get Could not cast value of type 'UIView' to 'CardView'.
Class is as follows:
class CardView: NibView {
#IBOutlet var contentView: UIView!
#IBOutlet weak var wordLabel: UILabel!
#IBOutlet weak var flipButton: UIButton!
#IBOutlet weak var playButton: UIButton!
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
Bundle.main.loadNibNamed("CardView", owner: self, options: nil)
addSubview(contentView)
contentView.frame = self.bounds
contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
}
override func awakeFromNib() {
super.awakeFromNib()
}
}
and NibView is a custom superclass and looks like:
class NibView: UIView {
var view: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
// Setup view from .xib file
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
// Setup view from .xib file
xibSetup()
}
}
private extension NibView {
func xibSetup() {
backgroundColor = UIColor.white
view = loadNib()
// use bounds not frame or it'll be offset
view.frame = bounds
// Adding custom subview on top of our view
addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[childView]|",
options: [],
metrics: nil,
views: ["childView": view]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[childView]|",
options: [],
metrics: nil,
views: ["childView": view]))
}
}
extension UIView {
/** Loads instance from nib with the same name. */
func loadNib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nibName = type(of: self).description().components(separatedBy: ".").last!
let nib = UINib(nibName: nibName, bundle: bundle)
return nib.instantiate(withOwner: self, options: nil).first as! UIView
}
}
Here is a screenshot of my file inspector showing that I set the File's Owner custom class to CardView, which seems to be a stumbling block for many
Finally, I try to instantiate the CardView as follows: CardView().loadNib() as! CardView
In case someone still having this problem, I have the same problem and I think we follow same tutorial.
You have called loadNib() in your xibSetup(). I think you don't have to call it again.
So instead of using
let myCardView = CardView().loadNib() as! CardView
I just use
let myCardView = CardView()
In your UIViewController, when you create an instance of your CardView, instead of casting it like CardView().loadNib() as! CardView, you call the function object_setClass(_, _) to avoid that error (from Xcode 9).
So it should be like:
let myCardView = CardView().loadNib
object_setClass(myCardView, CardView.self)
view.addSubview(myCardView)
Old question, but in case anyone's here:
My problem was that the view subclass was fileprivate. IB doesn't like that apparently.
For me loading xib programmatically in this way doesn’t work. I had to remove File owner’s class name and set that to the class name of first view. And then I had to set outlets to the components which I’m going to use.
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
}
override init(frame: CGRect) {
super.init(frame: frame)
}
Added to custom view class after outlets. For you it's CardView. Then I loaded that view class like
let viewCard = Bundle.main.loadNibNamed("CardView", owner: self, options: nil)?.first as! CardView
view.addSubview(viewCard)

Xib, Label text Change

How do I work with a Label that hangs on a xib?
lblName.text = "Label Text"
I am getting error associated with
unexpectedly found nil while unwrapping an Optional value
You should update your custom View class in the following way.
First of all, open View.xib file set File's Owner custom class to View like the image in given below
after set UILabel IBOutlets like the image given below
After that open View.swift file and paste the code given below
class View: UIView {
private var view: UIView!
#IBOutlet weak var name: UILabel!
#IBOutlet weak var firstname: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
}
//FIXME:- Set up
func xibSetup() {
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
addSubview(view)
}
func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "View", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
}
Now you can variable of View class in ViewController.