Why is my SurperView unresponsive when I remove a UIView SubView? - ios

I made a subview appear on my iOS app when a button is pressed. Then, I call a custom UIView from its class, menuView, and display that UIView on my main storyboard
The menuView appears fine on my Main Storyboard, but once I remove the subview, my SuperView (original view for main class for main view controller) is unresponsive, and I can't interact with anything.
What's wrong?
My Custom "menuView" UIView Class:
import UIKit
#IBDesignable class menuView: UIView {
var view:UIView!
#IBOutlet weak var label: UILabel!
func loadViewFromNib() -> UIView {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: "menuView", bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
return view
}
func xibSetup() {
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
addSubview(view)
}
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
xibSetup()
}
}
Main View Controller Class:
var myMenuView:menuView!
#IBOutlet weak var menuButtonOutlet: UIBarButtonItem!
#IBAction func buttonPressed(sender: AnyObject) {
if menuButtonOutlet.title == "Menu" {
if (myMenuView != nil) {
self.myMenuView.view.removeFromSuperview()
}
self.myMenuView = menuView(frame: self.view.bounds)
self.myMenuView.alpha = 0.75
self.view.addSubview(myMenuView)
menuButtonOutlet.title = "Back"
} else {
self.myMenuView.view.removeFromSuperview()
menuButtonOutlet.title = "Menu"
}
}

Short answer:
self.myMenuView.view.removeFromSuperview()
should become
self.myMenuView.removeFromSuperview()
in both places you have this line in buttonPressed.
Explanation:
Your myMenuView is a container in which you place the view you instantiate from your xib. In buttonPressed you remove only this inner(xib) view inside myMenuView and not myMenuView itself. Thus myMenuView remains on screen and swallows all the touches.

Related

how to load another xib file from another xib file on pressing button in swift

I am using two xib files of UIView. I want to show Custominfoview on pressing button from first xib view which is FirstView. I am little confused here how to do that. My codes is below please tell me how to do that. I have searched a lot but nothing found. I have attached a picture in link which is I exactly want.
class CustominfoView: UIView {
#IBOutlet var mainCustomView: UIView!
#IBOutlet weak var infotextLbl: UILabel!
// MARK:-
// MARK:- Methods
// MARK: UIView Methods
required init(coder aDecoder : NSCoder) {
super.init(coder :aDecoder)!
setup()
}
override init(frame : CGRect) {
super.init(frame: frame)
setup()
}
func setup() {
let view = loadViewFromXib()
view.frame = bounds
// view.autoresizingMask = UIViewAutoresizing.flexibleWidth | UIViewAutoresizing.flexibleHeight
view.layer.cornerRadius = 12
view.layer.borderColor = UIColor.red.cgColor
view.layer.borderWidth = 2
addSubview(view)
}
func loadViewFromXib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "CustominfoView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
}
class FirstView: UIView {
#IBOutlet var mainCustomView: UIView!
#IBOutlet weak var infotextLbl: UILabel!
// MARK:-
// MARK:- Methods
// MARK: UIView Methods
required init(coder aDecoder : NSCoder) {
super.init(coder :aDecoder)!
setup()
}
override init(frame : CGRect) {
super.init(frame: frame)
setup()
}
func setup() {
let view = loadViewFromXib()
view.frame = bounds
// view.autoresizingMask = UIViewAutoresizing.flexibleWidth | UIViewAutoresizing.flexibleHeight
view.layer.cornerRadius = 12
view.layer.borderColor = UIColor.red.cgColor
view.layer.borderWidth = 2
addSubview(view)
}
func loadViewFromXib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "CustominfoView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
#IBAction func infoBtnpressed(_ sender: UIButton) {
print("Pressed")
}
}
}
Just add customInfoView as a subview on top of the first view using addSubview.
(button pressed)
let customInfoView = CustomInfoView()
self.addSubview(customInfoView)
And then when you need to dismiss it simply remove it from the parent.
You can do something like this :
#IBAction func infoBtnpressed(_ sender: UIButton) {
print("Pressed")
let customInfoView = CustomInfoView(frame: CGRect(x: 100, y: 100, width: 200, height: 200) )
self.addSubView(customInfoView)
}
In CGRect pass the frame value as desired. Also you should declare the customInfoView as global so that you can remove it easily.

Cannot cast my custom UIView subclass created from XIB to the class I need (only UIView)

What I've done is:
1) Created a .xib file TranslationInfoWindow.xib:
2) Created TranslationInfoWindow.swift file with the follow content:
import UIKit
class TranslationInfoWindow: UIView {
// MARK: - Initializers
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
// MARK: - Private Helper Methods
// Performs the initial setup.
private func setupView() {
let view = viewFromNibForClass()
view.frame = bounds
// Auto-layout stuff.
view.autoresizingMask = [
UIViewAutoresizing.flexibleWidth,
UIViewAutoresizing.flexibleHeight
]
// Show the view.
addSubview(view)
}
// Loads a XIB file into a view and returns this view.
private func viewFromNibForClass() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil).first as! UIView
return view
}
#IBOutlet weak var avatarImageView: RoundedImageView!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var usersLabel: UILabel!
}
3) Here I try to initialise my custom view:
func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView? {
// FIXME: There is a UIView but it doesn't want to be casted in TranslationInfoWindow
if let infoWindow = Bundle.main.loadNibNamed(
"TranslationInfoWindow", owner: view, options: nil)?.first as? TranslationInfoWindow {
return infoWindow
} else {
return nil
}
}
Now if I try to run the project I have the following error:
What am I doing wrong?
UPDATE:
Here's the hierarchy of xib:
In Interface Builder, did you change the class name in the Identity Inspector (3rd from left) tab from UIView to your custom class name?
You should set the correct class of TranslationInfoWindow.xib to be type TranslationInfoWindow in IB .

Loading iOS view dynamically from xib file

Ive been searching for a while for a simple example on how to reuse views from xib files in my storyboard but all i find was outdated or dosen't solve my problem
the situation is that I has simple:
I have a viewController in my storyboard
I dragged to it two view from the library
I had created a myCustomView.xib and myCustomView.swift file (they are empty now)
I have I button on viewController (so the tree (two view and one button) are setting together on the viewController in the storyboard)
the question is: I want one view to be loaded dynamically on app launch and the other one to be loaded on button click
an other question: how can I connect myCustomView to that viewController
thank you
I've implemented an extension for UIView:
extension UIView {
static func createInstance<T: UIView>(ofType type: T.Type) -> T {
let className = NSStringFromClass(type).components(separatedBy: ".").last
return Bundle.main.loadNibNamed(className!, owner: self, options: nil)![0] as! T
}
}
In this way, wherever you can load your custom view in this way:
func override viewDidLoad() {
super.viewDidLoad()
let customView = UIView.createInstance(ofType: CustomView.self)
self.view.addSubview(customView)
}
Add bellow code in your custom view class
class MyCustomView: UIView {
#IBOutlet var contentView: UIView! // take view outlet
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
}
func xibSetup() {
contentView = loadViewFromNib()
// use bounds not frame or it'll be offset
contentView!.frame = bounds
//Make the view stretch with containing view
contentView!.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
// Adding custom subview on top of our view (over any custom drawing > see note below)
addSubview(contentView!)
layoutIfNeeded()
}
override func layoutIfNeeded() {
super.layoutIfNeeded()
print("layoutIfNeeded")
}
func loadViewFromNib() -> UIView! {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
}
Add this class as superclass view in storyboard.

Label in custom view not updating

I have created a custom UIView in xib with class InfoPopUpView. I add it to my viewController. It works well and the Custom Class xib is set in the File's Owner.
I can set the titleLbl variable in my first viewcontroller no problem.
My problem appears when I in another viewcontroller want to use the InfoPopUpView again but with a different title...
The title does not change/update. It is as if InfoPopUpView remembers the last title I set and dont care for changing it..
How can I initialise? the titleLbl variable in the InfoPopUpView Class so that I can change it later?
Any help is very much appreciated - thank you !
ViewController
var popUpView: InfoPopUpView!
popUpView = InfoPopUpView(frame: CGRectMake(0, 0, 300, 268))
popUpView.titleLbl.text = "MyFirstTitle"
view.addSubview(popUpView)
Custom Class
class InfoPopUpView: UIView {
var view: UIView!
#IBOutlet weak var okBtn: UIButton!
#IBOutlet weak var titleLbl: UILabel!
#IBOutlet weak var textView: UITextView!
#IBAction func didTapOkBtn(sender: AnyObject) {
NSNotificationCenter.defaultCenter().postNotificationName("popUpController", object: nil)
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
func setup() {
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
addSubview(view)
}
func loadViewFromNib() -> UIView {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: "InfoPopUpView", bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
return view
}
}

How to load custom UIView from xib using Swift 2?

The task is to create custom UIView that loads UI from .xib file using Swift. How do I do that?
I tried to do that using the code:
import UIKit
#IBDesignable class CustomView: UIView {
var view: UIView!
#IBOutlet weak var label: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
}
func xibSetup() {
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
addSubview(view)
}
func loadViewFromNib() -> UIView {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: "CustomView", bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
return view
}
}
It runs, but crashes with EXC_BAD_ACCESS and shows me the message:
warning: could not load any Objective-C class information. This will significantly reduce the quality of type information available.
Actually, I need to translate code given here http://qnoid.com/2013/03/20/How-to-implement-a-reusable-UIView.html to Swift 2.0, but I have no idea how to do this.
Try
let yourView = NSBundle.mainBundle().loadNibNamed("youViewNibName", owner: self, options: nil).first as! YourView
Do it in your ViewController class, then you can access the view in required init with coder, where you should call xibSetup().
Is it correct, that your class is called CustomView and you're loading CustomView.xib where the class for the view in xib is CustomView?
If that is so you probably do not understand what you're doing

Resources