Custom NSView with NSStackView - swift

I am trying to implement NSStackView with always the same custom view. So I have define my xib file, linked everything inside my class, associated the class, ... but I am sure I am missing something because the content inside the view don't appear. Thx very much for your help.
My storyboard:
My xib file:
The result when I run the below code:
My file is like :
class CustomView: NSView, NSTableViewDelegate, NSTableViewDataSource {
#IBOutlet weak var segmentControlOutlet: NSSegmentedControl!
#IBOutlet weak var tableViewOutlet: NSTableView!
}
class ViewController: NSViewController, NSStackViewDelegate {
#IBOutlet weak var stackViewOutlet: NSStackView!
override func viewDidLoad() {
super.viewDidLoad()
stackViewOutlet.delegate = self
let newView = CustomView()
stackViewOutlet.addArrangedSubview(newView)
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}

I have found the answer, you need to initiate properly the view. To do so :
class CustomView: NSView, NSTableViewDelegate, NSTableViewDataSource {
#IBOutlet var viewOutlet: NSView!
#IBOutlet weak var segmentControlOutlet: NSSegmentedControl!
#IBOutlet weak var tableViewOutlet: NSTableView!
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
Bundle.main.loadNibNamed("CustomView", owner: self, topLevelObjects: nil)
addSubview(viewOutlet)
viewOutlet.frame = self.bounds
viewOutlet.autoresizingMask = [.height, .width]
}
required init?(coder: NSCoder) {
super.init(coder: coder)
Bundle.main.loadNibNamed("CustomView", owner: self, topLevelObjects: nil)
addSubview(viewOutlet)
viewOutlet.frame = self.bounds
viewOutlet.autoresizingMask = [.height, .width]
}
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here.
}
}
Please take car that when you load the nib name, "CustomView" is the name of your xib file ;)

Related

I can't present a segue to another VC from a UIView class

I have a UIView class which i set it up as a pop-up that user needs to write a price and press a button to pay that amount, The problem is I can't set up the button to make a segue to another VC which I will use to make the payment.
I am getting errors which doesn't confront to the UIView Class because there is no method matching...
Code of popUpView class:
class popUpView: UIView, UITextFieldDelegate {
#IBOutlet weak var popUpViewInterface: UIView!
#IBOutlet weak var infoLabelPopUp: UILabel!
#IBOutlet weak var closeButtonPopUp: UIButton!
#IBOutlet weak var priceButtonPopUp: UIButton!
#IBOutlet weak var priceInfoPopUp: UILabel!
#IBOutlet weak var priceTextFieldPopUp: UITextField!
#IBOutlet weak var payNowPopUp: UIButton!
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup(frame:CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
}
func xibSetup(frame: CGRect){
let view = loadXib()
view.frame = frame
addSubview(view)
popUpViewInterface.layer.cornerRadius = 10
}
func loadXib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "popUpView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil).first as? UIView
return view!
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
priceTextFieldPopUp.resignFirstResponder()
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
priceTextFieldPopUp.resignFirstResponder()
return true
}
func cornerRadiusSetUp() {
let radius = 5
priceTextFieldPopUp.layer.cornerRadius = CGFloat(radius)
}
#IBAction func payNowToWebView(_ sender: Any) { // This is where the segue needs to happen but I am getting different kind of errors.
let myColor = UIColor.red
priceTextFieldPopUp.layer.borderColor = myColor.cgColor
priceTextFieldPopUp.layer.borderWidth = 1.0
}
}

how to add UIView with code? Without using storyboard

I am a beginner and am only able to add elements via storyboard.
Now I would like to know how to add UIView code to the screen without using a storyboard.
I need to place it at the very top, full width of the screen, replacing the NavigationBar with a UIView
import UIKit
class ChatsNavBar: UIView {
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var statusLabel: UILabel!
#IBOutlet weak var imageUser: UIImageView!
#IBOutlet weak var backButton: UIButton! {
didSet {
backButton.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
#IBOutlet weak var navView: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
let bundle = Bundle(for: ChatsNavBar.self)
bundle.loadNibNamed("ChatsNavBar", owner: self, options: nil)
navView.translatesAutoresizingMaskIntoConstraints = false
addSubview(nameLabel)
addSubview(navView)
addSubview(statusLabel)
addSubview(imageUser)
addSubview(backButton)
nameLabel.frame = self.bounds
nameLabel.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
#IBAction func backAction(_ sender: Any) {
}
}
class ChatsViewController: MessagesViewController {
init(user: MUser, chat: MChat) {
self.user = user
self.chat = chat
super.init(nibName: nil, bundle: nil)
title = "\(chat.friendUsername) \(chat.friendUserSurname)"
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
configureMessageInputBar()
let navController = UIView()
Here is how you can place it over entire screen
let viewOverLay = ChatsNavBar()
navigationController.view.addSubview(viewOverLay)
viewOverLay.frame = navigationController.navigationBar.bounds

How to load Custom Created view from XIB file and add to StackView

I have XIB file in which there is class of type UIView, and I wont to load that XIB in root ViewController:
import UIKit
class ViewController: UIViewController {
// MARK: - Variables
// MARK: - IBOutlets
#IBOutlet private weak var mainStackView: UIStackView!
// MARK: - LifeCycle Methods
override func viewDidLoad() {
super.viewDidLoad()
if let view = CustomView.instanceFromNib() {
let view = CustomView.instanceFromNib() as! CustomView
mainStackView.addArrangedSubview(view)
mainStackView.addArrangedSubview(view)
mainStackView.addArrangedSubview(view)
}
}
}
import Foundation
import UIKit
class CustomView: UIView {
static let id = "CustomView"
#IBOutlet weak var backgroundImageView: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
}
static func instanceFromNib() -> UIView {
return UINib(nibName: "UserReview", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! UIView
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
this class is not key value coding-compliant for the key backgroundImageView.'
Did you File owner for Xib file ?? assign CustomView class to Xib File's Owner

swift delegate showing nil

I have created a .xib and adding this xib to another view. I want to add a delegate method in that .xib file. Here is my code :
.xib file
import UIKit
protocol CustomCheckBoxWithCrossDelegate {
func deleteCustomCheckbox(itemToDelete: String)
}
class CustomCheckBoxWithCross: UIView {
#IBOutlet weak var radioButton: UIButton!
#IBOutlet weak var checkboxLbl: UILabel!
#IBOutlet weak var checkboxCrossBtn: UIButton!
var blockIndexForTheCrossButton: Int = 0
var delegate: CustomCheckBoxWithCrossDelegate!
override init(frame: CGRect) {
super.init(frame: frame)
loadViewFromNib ()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadViewFromNib ()
}
func loadViewFromNib() {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: "CustomCheckBoxWithCross", bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
view.frame = bounds
view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
self.addSubview(view);
}
#IBAction func crossBtnTapped(sender: AnyObject) {
print("Delegate --> \(delegate)")
delegate!.deleteCustomCheckbox("hello")
}
}
But in "crossBtnTapped" method I am getting nil value for that delegate.
can anyone please tell me what I am doing wrong?
You must have the instance of CustomCheckBoxWithCross in your other class, where you have implemented the protocol. Set delegate property of CustomCheckBoxWithCross instance to self in that file.
I ran to this error several times before, add if delegate is not nil condition.
#IBAction func crossBtnTapped(sender: AnyObject) {
if delegate != {
delegate!.deleteCustomCheckbox("hello")
}
}

Where to set UiTextField delegate method in custom UiView

Error occurs when I set UITextField delegate.
My code is:
import UIKit
class UserAlertVC: UIView , UITextFieldDelegate {
/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
}
*/
override init(frame: CGRect) {
super.init(frame: frame)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
self.addBehavior()
}
func addBehavior (){
print("Add all the behavior here")
userNameTxtField.delegate = self
passwordTxtField.delegate = self
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
return true
}
func textFieldDidBeginEditing(textField: UITextField) {
}
#available(tvOS 10.0, *)
func textFieldDidEndEditing(textField: UITextField, reason: UITextFieldDidEndEditingReason) {
}
#IBAction func actionOnCancel(sender: UIButton) {
self .removeFromSuperview()
}
#IBAction func actionOnProceed(sender: UIButton) {
self .removeFromSuperview()
UserAlertVC.showAlertForUser()
}
#IBOutlet var userNameTxtField: UITextField!
#IBOutlet var passwordTxtField: UITextField!
static func showAlertForUser() {
let alert = NSBundle.mainBundle().loadNibNamed("KeyboardViewController", owner: self, options: nil)!.last as! UIView
let windows = UIApplication.sharedApplication().windows
let lastWindow = windows.last
alert.frame = UIScreen.mainScreen().bounds
lastWindow?.addSubview(alert)
}
}
Error message is:
fatal error: unexpectedly found nil while unwrapping an Optional value
I have used Custom Alert View using XIB.pls suggest any solution.
Firstly take a look at life cycle of the view. Depending on this it is possible to highlight that method awakeFromNib is quite suitable because:
The nib-loading infrastructure sends an awakeFromNib message to each
object recreated from a nib archive, but only after all the objects in
the archive have been loaded and initialized. When an object receives
an awakeFromNib message, it is guaranteed to have all its outlet and
action connections already established.
Make sure to put an #IBOutlet for the .Xib content view, also you need to add the Nib code. Last, make sure in your ViewController you set your UIView Outlet to be UserAlertVC and you add the awakeFromNib method. Please find attached the code. Let me know if you need further help.
Here is the code related to the .xib file.
import UIKit
class UserAlertVC: UIView, UITextFieldDelegate {
//MARK: - Outlets
#IBOutlet var contentView: UIView!
#IBOutlet var userNameTxtField: UITextField!
#IBOutlet var passwordTxtField: UITextField!
//MARK: - Loads
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
commonInit()
}
//MARK: - Functions
func commonInit() {
Bundle.main.loadNibNamed("UserAlertVC", owner: self, options: nil)
userNameTxtField.delegate = self
passwordTxtField.delegate = self
contentView.translatesAutoresizingMaskIntoConstraints = false
addSubview(contentView)
// add constraints programmatically
}
// add the rest of your code
}
Here is the code related to the ViewController.
class ViewController: UIViewController {
//MARK: - Outlets
#IBOutlet weak var userAlertVC: UserAlertVC!
//MARK: - Loads
override func viewDidLoad() {
super.viewDidLoad()
}
override func awakeFromNib() {
super.awakeFromNib()
}
}