IBDesignable UI is not showing in Xcode 9 with Swift - ios

I trying to using my custom xib files. But those UI are not showing in main view controller in xcode. But it show when run the app. I already added #IBDesignable in class. Here is what i did.
I created TestView.xib and added some design
I created TestView.swift
I updated fileOwner of TestView.xib with TestView in Custom Class
I added init code to testView.swift
Code inside TestView.swift
import UIKit
#IBDesignable class DetailView: UIView {
override init(frame: CGRect){
super.init(frame: frame)
self.setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
self.setup()
}
func setup() {
let view = Bundle.main.loadNibNamed("TestView", owner: self, options: nil)?.first as! UIView
view.frame = self.bounds
self.addSubview(view)
}
}
And Added on UIView in MainViewController and link to TestView with custom class name.
After that i run the app, I can see the UI from testView. Image of emulator and result
But my custom UI don't show in MainViewController in xcode Image of xcode view controller
How can i enable to see my custom UI in MainViewController ? Thanks

In InterfaceBuilder select your ViewController and choose "Editor-->Refresh all Views". Then your custom view should come up.
If something is wrong you can debug your IBDesignable class by setting breakpoints in your code and then choose "Editor-->Debug selected views".
prepareForInterfaceBuilder() only needs to be implemented if you need special design appearance in InterfaceBuilder.
Sometimes it is necessary to clean the project and build folder to get it to work:
Project->Clean
Project->(hold down options key)->Clean Build Folder

I just changed the setup function. It working now. Final Result Image - It showing UI in IB
func setup() {
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = UIViewAutoresizing(rawValue: UIViewAutoresizing.RawValue(UInt8(UIViewAutoresizing.flexibleWidth.rawValue) | UInt8(UIViewAutoresizing.flexibleHeight.rawValue)))
self.addSubview(view)
}
func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "TestView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}

Override two func below for live:
override open func prepareForInterfaceBuilder() {
layer.cornerRadius = cornerRadius
layer.borderWidth = borderWidth
}
override open func awakeFromNib() {
layer.cornerRadius = cornerRadius
layer.borderWidth = borderWidth
}

Related

Instantiating custom xib programmatically ends with infinite loop

I request apologies in advance in the case this question is very elemental or the answer is obvious.
I have a custom xib, that works very well when used with the storyboard interface builder. The custom xib is implemented like the classical samples you can find across the internet:
I have a CustomView.swift class
a CustomView.xib file.
The FileOwner of the CustomView.xib file is set to the CustomView.class. Then this xib file has a couple of outlets for the views used in the xib. Something like the following:
#IBDesignable
class CustomView: UIView {
#IBOutlet weak var view1: UIView!
#IBOutlet weak var view2: UIView!
required init?(coder aDecoder: NSCoder) {
//When loaded from storyboard.
super.init(coder: aDecoder)
commonInit()
}
override init(frame: CGRect) {
//When loaded from code
super.init(frame: frame)
commonInit()
}
func commonInit() {
if let view = Bundle.main.loadNibNamed(self.nibName, owner: self, options: nil)?.first as? UIView {
view.frame = self.bounds
self.addSubview(view)
view.autoresizingMask = [.flexibleHeight, .flexibleWidth]
}
}
func renderViews()
//A lot of stuff is done here.
}
}
As said, this works very well when using the Storyboard designer to insert the custom xib in the layout of an UIController. But I need to use the same xib on another place, and I need to instantiate and insert it programmatically in a container view multiple times.
I tried different approaches to instantiate the xib and add it as a subview of another view, for example:
class AnotherView: UIView
(...)
func instantiateXib(){
let view = CustomView()
self.addSubView(view)
}
}
or
class AnotherView: UIView
(...)
func instantiateXib(){
let nib = UINib(nibName: "CustomView", bundle: nil).instantiate(withOwner: nil, options: nil)
let view = nib.first as! CustomView
self.addSubView(view)
}
}
or many other ways that I found across the internet, but all of them end with an infinite loop, because the method init?(coder aDecoder: NSCoder) of the xib, calls the commonInit method that instantiates again an instance of the xib, and so on.
I suspect the solution is obvious, but I'm struggling to find it.
May you point me in the right direction? Thank you in advance!

How to make #IBAction from a custom view in storyboard?

I added a custom view, that has a button, to my viewController. I want to make an #IBAction from that button to my viewController.
I have following problems:
How do I make it show up in a storyboard? When I run the app it works fine.
How do I make an #IBAction from that button to my viewController?
class CustomCellView: UIView{
//MARK: Initializer
override func awakeFromNib() {
super.awakeFromNib()
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
commonInit()
}
//MARK: Functions
func commonInit(){
let customView = Bundle.main.loadNibNamed("customCellView", owner: self, options: nil)?.first as? UIView ?? UIView()
customView.frame = self.bounds
self.addSubview(customView)
}
}
Add #objc in your viewController where you added customView.
e.g.
#objc func actionCustom()
{
print("Click Added")
}
Use
func commonInit(){
let customView = Bundle.main.loadNibNamed("customCellView", owner: self, options: nil)?.first as? UIView ?? UIView()
customView.frame = self.bounds
self.addSubview(customView)
customView.button.addTarget(self, action: #selector(actionCustom), for: .touchUpInside) //Add click code here
}
my customView is not showing in storyboard but when I run the app it's ok
This is the expected behaviour with the custom views. You won't get to see how the view looks in the xib that you use the custom view only in the xib that you defined the view.
How make #IBAction from that button to my viewController.
You can't. Custom views don't make public the subviews in interface builder. The best thing you can do is to use the delegate pattern or as Bhavesh Sarsawa pointed out doing it programatically either by adding the vc as a target or by making an IBAction in the ccustom view which calls a closure that is sent by dependency injection.
customButton.setAction { code that gets called when the button is pressed }

Swift scrollview adding from XIB not scrollable at all

I'm trying to import from Xib full screen ScrollView into my ViewController.
Following that guide i've made many working examples of it, but when importing it from Xib, ScrollView not responding on scroll (not even bouncing)
My Xib View class:
class TestScroll: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func awakeFromNib() {
super.awakeFromNib()
self.translatesAutoresizingMaskIntoConstraints = false
}
public static func getViewFromNib() -> TestScroll {
return UINib(nibName: "TestScroll", bundle: .main).instantiate(withOwner: nil, options: nil).first as! TestScroll
}
}
And this is how i adding it in ViewController:
override func viewDidLoad() {
super.viewDidLoad()
let testScroll = TestScroll.getViewFromNib()
self.view.addSubview(testScroll)
}
Please help, i've checked many guides already, but not found working example with Xib.
You need to set a frame / constraints
let testScroll = TestScroll.getViewFromNib()
testScroll.frame = self.view.bounds
self.view.addSubview(testScroll)
leave this
self.translatesAutoresizingMaskIntoConstraints = false
only if you'll set constraints

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.

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