Creating IBOutlet in Swift results in 'class is not constructible with ()' - swift

My code compiled fine before upgrading to beta 4, however I think they changed something with IBOutlets.
The old syntax was:
#IBOutlet var tableView: UITableView
The new syntax is:
#IBOutlet weak var tableView: UITableView!
This is default code generated by Xcode when I ctrl drag from my xib file to the class file.
However, with this new syntax, I'm unable to construct an instance of my class. Take the following example:
class TestViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
}
Then if I try to do either
var controller = TestViewController(nibName: nil, bundle: nil)
or
var controller = TestViewController()
I get an error:
TestViewController is not constructible with ()
What's the right way to create an instance of my controller then? The only way that currently works for me is to make the outlets optional, but I'd rather not do that.

Can you try this.
#IBOutlet var tableView: UITableView?
I know this is not the answer but the error is gone after this.

The solution seems to be to implement the init method in that view controller:
init()
{
super.init(nibName: nil, bundle: nil)
}
I'm not sure why that is.

Related

Pass outlet Data from TableViewCell to ViewController.swift

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.

How to focus on a text field when opening an application?

How to focus on a text field when opening an application?
Swift 4,
Xcode 10,
macOS
ANSWER:
Thanks to the advice by #Willeke in the comments, I did it this way:
import Cocoa
import AppKit
import Foundation
let defaults = UserDefaults.standard
class ViewController: NSViewController{
#IBOutlet weak var addDomain: NSTextField!
#IBOutlet weak var addSiteField: NSTextField!
#IBOutlet weak var tableView: NSTableView!
#IBOutlet weak var removeSite: NSSegmentedControl!
override func viewDidAppear() {
super.viewDidAppear()
addDomain.window?.makeFirstResponder(addDomain)
}
Because:
https://developer.apple.com/documentation/appkit/nsresponder/1526750-becomefirstresponder
Use the NSWindow makeFirstResponder(_:) method, not becomeFirstResponder() method, to make an object the first responder. Never invoke this method directly.
You seem to be not over-riding the viewDidAppear that belongs to your NSViewController, but you are adding a new function on it's own.
Try using:
override func viewDidAppear() {
// Though the default implementation does nothing as of now,
// it is always safe to have the call to the super function in place,
// in case you plan to add sub-classes in between.
super.viewDidAppear()
addDomain.window?.makeFirstResponder(addDomain)
}
In your viewController in viewDidAppear
yourTextField.becomeFirstResponder()
Update:
macOS implementation requires using NSWindow makeFirstResponder!

Swift: Perform Segue is throwing a found nil when unwrapping an Optional

I know there's a couple of other post on a similar errors but looking at those they are happening in the prepare for segue method as the user attempts to pass some data. In my case, I am just trying to segue from one vc to another. The IBOutlet is linked up from Storyboard. I check the destination vc in prepare for segue and it exists. The crash happens after that method is called.
Here is my code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var btnShowAccount: UIButton!
#IBOutlet weak var ivLaunch: UIImageView!
#IBOutlet weak var vButtonWrapper: UIView!
#IBOutlet weak var btnMissionLog: UIButton!
#IBOutlet weak var btnAccount: UIButton!
#IBOutlet weak var btnNotes: UIButton!
#IBOutlet weak var btnInfo: UIButton!
#IBOutlet weak var btnPrivacy: UIButton!
#IBOutlet weak var btnHelp: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
//align button text to left
btnAccount.contentHorizontalAlignment = .left
btnMissionLog.contentHorizontalAlignment = .left
btnNotes.contentHorizontalAlignment = .left
}
override func viewDidAppear(_ animated: Bool) {
self.ivLaunch.fadeOut(0.15)
self.vButtonWrapper.fadeIn()
}
#IBAction func showAccount(_ sender: Any) {
self.performSegue(withIdentifier: "toAccountFromRoot", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print(segue.destination)
}
The error message doesn't point to which object the compiler is trying to unwrap:
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
XCode is less than helpful as it displays the error in viewDidLoad, on first line of code, which obviously has already happened. (And if I comment out all viewDidLoad code it shows the error in viewDidAppear).
I do see this in the debug navigator:
; function signature specialization <preserving fragile attribute, Arg[1] = [Closure Propagated : reabstraction thunk helper from #callee_owned (#unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> () to #callee_owned (#unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (#out ()), Argument Types : [#callee_owned (#unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> ()]> of generic specialization <preserving fragile attribute, ()> of Swift.StaticString.withUTF8Buffer<A>((Swift.UnsafeBufferPointer<Swift.UInt8>) -> A) -> A
Any help would be appreciated, I'm kind of stuck on this one.
Your stack crawl highly suggests that your destinationVC has type ViewController which is the same class that your first VC uses.
You can verify this by adding:
print(type(of: segue.destination))
to your prepare(for:sender:) method. If it prints ViewController, then that is your problem.
In that case, the crash in viewDidLoad is when the destinationVC loads. Because it is set to ViewController instead of UIViewController (which is what you'd expect for a blank VC), the outlets are not connected so you get the unwrapping nil message when trying to access btnAccount. Fix the class for the blank view controller by deleting the Class in the Identity Inspector.
Once you've verified that that works. Create a new class (that is a subclass of UIViewController) for your destinationVC and assign that class in the Identify Inspector.

Setting XIB inside custom cell tableView issue

I have followed this this tutorial
How to visualize reusable xibs in storyboards using IBDesignable
I have added a label inside the view to change the label and I'm calling the xib inside the custom cell for tableView. So I'm facing this issue,
fatal error: unexpectedly found nil while unwrapping an Optional value
While I’ve added this code inside the view and linked it
#IBOutlet weak var priceLabel: UILabel!
This is how I'm calling it inside the custom cell.
TableViewcell code:
class ProductListBigTableViewCell: UITableViewCell {
#IBOutlet weak var productImage: UIImageView!
#IBOutlet weak var productName: UILabel!
#IBOutlet weak var productQuantity: UILabel!
#IBOutlet weak var productAddButton: BaseButton!
#IBOutlet weak var prodcutPriceView: PriceView!
override func awakeFromNib() {
super.awakeFromNib()
productFirstName.text = "first product"
productFirstQuantity.text = "4 p"
prodcutPriceView.priceLabel.text = ""
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
I can figure that the view is not initialised yet so it is nil. I could not find a way or resource how to change a value inside XIB inside the UITableViewCell. So how I can change it and initial the view for the XIB?

Static Table View with dynamic text

I have a static table view, but I want the last cell to say "Logout, (username here)"...can I even do that with a static table view?
The language I am using is Swift.
So far, I've tried to use cellForRowAtIndexPath and only have it return anything when the indexPath.row is the last cell. That doesn't work. Furthermore, it changes all of the other cells and, on top of that, they lose their segues to the other views...
Yes, you can update controls in static cells in UITableViewController's UITableView. When you have a static table, you can just create IBOutlet references to the controls in the cells and update those outlets directly without use of any UITableViewDataSource methods. You can effectively just ignore the fact that it is a UITableView and treat these labels as if they were placed directly on the view in question. Just hook up the controls in the static cells to IBOutlet references in the view controller.
For example:
class ViewController: UITableViewController {
#IBOutlet weak var label1: UILabel! // in first cell
#IBOutlet weak var label2: UILabel! // in second cell
#IBOutlet weak var label3: UILabel! // in third cell
override func viewDidLoad() {
super.viewDidLoad()
label1.text = "foo"
label2.text = "bar"
label3.text = "baz"
}
}