I've just updated my code from Swift 1.2 to Swift 2.1. The project was fully-functioning with previous version of Swift, but now I'm seeing "Ambiguous use of 'init'" errors. Each occurrence of this error seems to be caused by the use of optional arguments in the constructor. I've even managed to reproduce this issue in Xcode Playground with the following simplified code using the same pattern:
class Item : UIView {
override init(frame: CGRect = CGRectZero) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
let i = Item() # Ambiguous use of 'init(frame:)'
However, I still don't understand why Swift 2.1 now has a problem with this pattern, or what the alternative should be. I've tried searching for this, but all I've stumbled upon was "ambiguous use" errors for other (non-constructor) methods due to method renaming or signature changing, neither of which is the case here.
It's ambiguous use because when u call let i = Item(), there are 2 options -
the init(frame: CGRect = CGRectZero) and the init()
it's better to do something like this:
override init(frame: CGRect) {
super.init(frame: frame)
}
convenience init() {
self.init(frame: CGRectZero)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
Related
I have a macOS storyboard app in which I am having a SwiftUI view which hosted using an NSHostingController. I need to pass an EnvironmentObject to this SwiftUI view from my NSHostingController. I am unable to achieve this. I have currently written this code but it does not work. What could be the issue here?
import Cocoa
import SwiftUI
class SearchText: ObservableObject {
#Published var text = ""
}
class HostingController: NSHostingController<SwiftUIView> {
#objc required dynamic init?(coder: NSCoder) {
super.init(coder: coder, rootView: SwiftUIView().environmentObject(SearchText()))
}
}
The issue is that modifier .environmentObject returns different type than you specify in generics, ie SwiftUIView.
Here is possible approach
class HostingController: NSHostingController<AnyView> {
#objc required dynamic init?(coder: NSCoder) {
super.init(coder: coder, rootView:
AnyView(SwiftUIView().environmentObject(SearchText())))
}
}
Alternate: (Xcode 13.4)
class HostingController: NSHostingController<HostingController.HelperView> {
struct HelperView: View {
var body: some View {
SwiftUIView().environmentObject(SearchText())
}
}
#objc required dynamic init?(coder: NSCoder) {
super.init(coder: coder, rootView: HelperView())
}
}
I am learning Swift and I have a compile error:
class ListScansVC: UIViewController {
#IBOutlet weak var tableView: UITableView!
internal var scans: [Scan]
internal var dataSource: ListScanDataSource
init(scans: [Scan]){
self.scans = scans
dataSource = ListScanDataSource.init(scans: scans)
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
dataSource.registerReusableViewsForTableView(tableView)
}
}
In another ViewController i am doing:
override func viewDidLoad() {
super.viewDidLoad()
let scan = Scan(title : "Ticket", scanDate: NSDate())
let listScanVC = ListScansVC.init(scans: [scan])
self.displayChildContent(ListScansVC)
}
func displayChildContent(content : UIViewController){
self.addChildViewController(content)
self.view.addSubview(content.view)
content.didMoveToParentViewController(self)
}
The error is:
"Cannot convert value of Type 'ListScansVC.Type' to expected argument type 'UIViewController'"
An init method in Swift like
init(scans :[Scan]){)
has be be called with
let listScanVC = ListScansVC(scans: [scan])
in the next line you have to pass the instance (starting with a lowercase letter) rather than the type
self.displayChildContent(listScanVC)
I'd recommended to use more distinctive names to avoid that type/instance confusion.
I'm getting the following error:
Type 'TestClass' does not conform to protocol 'NSCoding'
There's only two methods required for NSCoding and both are there. What am I missing?
class TestClass: NSObject, NSCoding {
var Property1:Double? = 0.00
required init(code aDecoder: NSCoder) {
if let priceCoded = aDecoder.decodeObjectForKey("Property1") as? Double {
self.Property1 = priceCoded
}
}
func encodeWithCoder(aCoder: NSCoder){
if let priceEncoded = self.Property1 {
aCoder.encodeObject(priceEncoded, forKey: "Property1")
}
}
}
You missed 'r' symbol in an argument name. Update your initializer name to:
required init(coder aDecoder: NSCoder)
And it will work
I am solving this by using this :-
required init?(coder aDecoder: NSCoder) {
}
func encodeWithCoder(aCoder: NSCoder) {
}
XCode 8.0 (8A218a) , swift 3
Say I have a class like this one:
class UniverseViewController: UITableViewController {
var model = createModel()
// blah, blah...
}
When exactly will the createModel function be called? Before the init? After it?
It is called before init and viewDidLoad etc.
The following code:
struct testStruct {
init() {
println("testStruct")
}
}
let tempValue = testStruct()
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
println("Coder")
}
override func viewDidLoad() {
super.viewDidLoad()
println("viewDidLoad")
}
will give us the following output:
testStruct
Coder
viewDidLoad
I have classes with inheritance like:
UIView -> TestSubclass -> Test
class Test has some properties and methods. It works until I add some initializers into class TestSubclass:
class TestSubclass : UIView {
override init(frame: CGRect) {
super.init(frame: frame)
print("CustomActivityInit")
}
required init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
print("CustomActivityInitCoder")
}
}
After this I can't access properties of my Test class
override func viewDidLoad() {
super.viewDidLoad()
var test = Test(frame: CGRect.nullRect)
test.test = "zzz"
}
and get EXC_BAD_ACCESS error on line test.test = "zzz"
Could you help me understand the reason, please?
This is the test project to see the issue https://www.dropbox.com/s/1d8fvxm0es9b5n4/TestInit.zip
I use XCode 6 beta 5, deployment target iOS7+, iOS8 SDK
You must override init() because of inheritance from UIView.
class TestSubclass : UIView {
override init() {
super.init()
}
}
The reference from Apple:
Default Initializers
Swift provides a default initializer for any structure or base class that provides default values for all of its properties and does not provide at least one initializer itself. The default initializer simply creates a new instance with all of its properties set to their default values.
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html