I've created a progressView and linked it like this:
And here is what I do in my view controller:
class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {
#IBOutlet weak var progressView: UIProgressView!
#IBOutlet weak var KronosWebsite: WKWebView!
override func loadView() {
//initialize the webview
progressView = UIProgressView()
progressView.progress = 1.0
KronosWebsite = WKWebView()
self.view = KronosWebsite
self.view.addSubview(progressView)
}
}
And I've got
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional
in this line progressView.progress = 1.0
Add super.loadView() when you use loadView for a vc that originally inside storyboard
override func loadView() {
super.loadView()
or insert all code inside viewDidLoad , also don't re-init
progressView = UIProgressView()
KronosWebsite = WKWebView()
as they already initiated from storyboard
The docs say to never override loadView if your view controller comes from a storyboard or xib:
loadView()
If you use Interface Builder to create your views and initialize the view controller, you must not override this method.
Everything that you're currently doing in loadView can be done in the storyboard anyway, so just remove the loadView method and connect your UIProgressView and WKWebView to your outlets in your storyboard. You can also set the progress view's initial progress to 1.0 inside the storyboard.
Related
I am adding a subview(xib) to the view controller. The subview contains other subview(xib).
When the app loads, both the subviews are loaded but , the last child subview has all it IBOutlets as nil.
Below is the simple code with Viewcontroller and two views.
The loadUI() method is printing nil.
Heres the full code. https://github.com/Laxmanraju/SubnibbedView
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let cnatainer = Bundle.main.loadNibNamed("ContainerView", owner: self, options: nil)?.first as! ContainerView
self.view.addSubview(cnatainer)
cnatainer.loadUI()
}
}
class ContainerView: UIView {
#IBOutlet weak var detail: DetailOptionView!
func loadUI(){
print(detail.imageView). // prints nil
}
}
class DetailOptionView: UIView {
#IBOutlet weak var imageView: UIImageView!
}
Getting error Unexpectedly found nil while unwrapping an Optional value
while trying to pass data from tableviewcell to viewcontroller
DataCell.swift
#IBOutlet weak var containerView: UIView!
viewcontroller.swift
let dataCell = DataCell()
override func viewDidLoad() {
super.viewDidLoad()
dataCell.containerView.layer.cornerRadius = 10.0
}
#IBOutlet weak var containerView: UIView!
You have this IBOulet connection in a xib file or a in a stotryboard. And you are creating the cell programmatically in the view controller. When you create a cell programmatically its IBOutlet connections will be nil. Either created the containerView programmatically without IBOutlet in DataCell class or change the cornerRadius of the containerView in cellForRowAtIndexPath method.
This question deals with the same code with my previous question.
(The previous question is Why is this View nil in awakeFromNib()?)
But totally different approach.
It's not the duplicated question.
So let me restructure my question.
First, let me summarize my project.
Thanks to previous answer, I can reuse xib now.
This is CardContentView.xib
Codes are below
#IBDesignable class CardContentView: UIView {
#IBOutlet weak var backgroundView: UIView!
#IBInspectable var nibName:String?
var contentView: UIView?
override func awakeFromNib() {
super.awakeFromNib()
xibSetup()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
xibSetup()
contentView?.prepareForInterfaceBuilder()
}
func xibSetup(){
guard let view = loadViewFromNib() else { return }
view.frame = self.bounds
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
addSubview(view)
contentView = view
}
func loadViewFromNib() -> UIView? {
guard let nibName = nibName else { return nil }
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: nibName, bundle: bundle)
return nib.instantiate(withOwner: self, options: nil).first as? UIView
}
}
And this is CardView.xib, the property follows 'class CardContentView'
Codes are below
class CardView: UIView {
#IBOutlet weak var cardContentView: CardContentView!
override func awakeFromNib() {
cardContentView.layer.cornerRadius = 16
}
}
This is Main.storyboard. with a single UIView.
Codes are below
class ViewController: UIViewController {
#IBOutlet weak var cardView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
}
}
But, I want to reuse class 'CardView' to 'cardView' property in ViewController.
I want to get 'background' property to 'cardView' property (In simple words, I want to change the yellow box to the blue box in CardContentView!).
And I want to make 'cardView' property with a transition effect.
But, I cannot make extension because it's not in a UIView class, but in a ViewController class.
So I need to make another UIView class.
That's why I made a CardView class separately.
(Of course, I want to organize codes neatly by making another file.)
So, I tried 2 different ways.
Set the property 'cardView' class as CardView, and connect it to ViewController.
class ViewController: UIViewController {
#IBOutlet weak var cardView: CardView!
override func viewDidLoad() {
super.viewDidLoad()
}
}
Cast 'CardView' class to other property in ViewController
override func viewDidLoad() {
super.viewDidLoad()
let tappedView = self.cardView as! CardView
self.view.addSubview(tappedView)
}
But both of them make errors.
1. When I made '#IBOutlet weak var cardView: CardView!', it throws error message, 'Unexpectedly found nil while unwrapping an Optional value, cardContentView = nil'.
2. When I made 'let tappedView = self.cardView as! CardView', it throws error message, 'Could not cast value of type 'UIView' (0x10a229ff8) to 'AwakeFromNibTutorial.CardView' (0x1060aa8d0).'
How can I solve this problem?
Please help me!
In the CardView class's awakeFromNib(), you are not calling super.awakeFromNib().
You would have to use the same logic (xibSetup()) that you used to load the CardContentView from it's corresponding XIB, to load the CardView also from its XIB.
In the ViewController in your storyboard, have you assigned the class of the UIView to CardView?
I'm working on a Swift app and running into a crazy odd problem. I have a simple storyboard view controller setup, it has 3 UIButtons a UIImageView and a UIView (as a subview of the main view).
I want to programmatically add a WKWebView to the UIView.
Easy enough right? All of the above are in the Storyboard View, declared in the custom UIViewController class and connected in IB. However at run time, everything is nil. This is a snippet of my code:
#IBOutlet var button1 : UIButton!;
#IBOutlet var button2 : UIButton!;
#IBOutlet var button3 : UIButton!;
#IBOutlet weak var containerForWebView: UIView!
var webView: WKWebView!
override func loadView()
{
}
override func viewDidLoad()
{
super.viewDidLoad()
displayWebPage()
}
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
}
override func viewDidLayoutSubviews()
{
super.viewDidLayoutSubviews()
}
private func displayWebPage()
{
webView = WKWebView()
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
webView.frame = CGRect(origin: CGPoint.zero, size: containerForWebView.frame.size)
webView.navigationDelegate = self
containerForWebView.addSubview(webView)
let url = URL(string: "https://www.google.com")!
webView.load(URLRequest(url: url))
}
When the code calls the displayWebPage() method I break on the first line. In the debugger you can see all of the UIViewController properties are nil. The IBOutlets are Nil and the _view variable of the UIViewController itself is nil.
I don't understand why this is happening. Everything is pretty simple and easily connected. I never ran into this sort of issue in Objective-C. Any advice is appreciated!
Remove loadView implementation. Do not override that method, always use viewDidLoad instead.
If you override loadView then you are responsible for creating controller's view and assigning it to self.view.
I'm trying to check if a user is scrolling up and down on my app but it's not calling my scrollViewDidScroll method
Any ideas why it's not printing received scroll when I scroll up and down on the app?
import UIKit
class CreateAccount: UIViewController, UITextFieldDelegate, UIScrollViewDelegate {
#IBOutlet weak var scrollViewer: UIScrollView!
#IBOutlet weak var usernameTextField: UITextField!
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var reenterPasswordTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func scrollViewDidScroll(scrollView: UIScrollView) {
print("received scroll")
}
}
Add the scrollview delegate. Whenever you implement a delegate method you need tell it what controller to use, usually it will be self. It's caught me out a few times.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
scrollViewer.delegate = self
}
You need to set delegate of scrollview also don't use tag to differentiate 2 scrollview instead of that create 2 outlets of scrollview and use that in UIScrollViewDelegate methods like this.
func scrollViewDidScroll(scrollView: UIScrollView) {
if scrollView == scrollView1 {
print("received scrollview 1")
}
else if scrollView == scrollView2 {
print("received scrollview 2")
}
}
Delegate are given properly even if your scrollview delegate method not calling then please check you delegate method which you have added for scrollview, this may give warning due to using old swift version scrollview delegate with swift 4.0
Please correct it with below if this is the case:
Old Method:
func scrollViewDidScroll(scrollView: UIScrollView) {
}
New Method:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
}
You can set the .delegate = self as Sarcoma suggests, or:
CTRL drag from scrollView in storyboard onto the File Owner (it is located in the view hierarchy list, actually it is right by the yellow circle icon by the name of your controller: [O] Create Account and choose
delegate