Can't call a function inside the class instance - swift

I have a class DiscoverUserInfo, which has a function compoundKeyValue. I need to call this function in line 23 (see pic below). But I am getting the following error:
Value of type '(NSObject) -> () -> DiscoverUserInfo' has no member
'compoundKeyValue'

You cannot call a method on self during initialization of self. Maybe you want to create a computed property instead?
public var compoundKey: String {
return self.compoundKeyValue
}
That will also allow you to remove the didSet handler from UserObject.

You may make the method compoundKeyValue static, as
static func compoundKeyValue() -> String {
return UserObject.UserId
}
and create compoundKey as
public var compoundKey: String = DiscoverUserInfo.compoundKeyValue()

Related

How to initialize and use function pointer in Swift

Let's say I have this code snipped in the playground
import UIKit
internal final class TestClass {
internal final var funcPointer: () -> Void
init() {
self.funcPointer = self.func1() //Cannot assign value of type '()' to type '() -> Void'
}
internal final func func1() {
print("func1 is called!")
}
}
var testClass: TestClass = TestClass()
testClass.funcPointer()
Why do I get the shown error message within the init() method and how to initialize a function pointer correctly?
I have already seen this SO post and this tutorial but anyway I don't get it to work for a (Void) -> Void function...
To assign the closure to the property you have to remove the parentheses
self.funcPointer = self.func1
The subsequent error
self' used in method call 'func1' before all stored properties are initialized
can be fixed by declaring funcPointer implicit unwrapped optional
internal final var funcPointer: (() -> Void)!

What is the difference between a Computed Property and a Stored Value Property in Swift?

Question:
What is the difference between the two lines in Row.swift?
Context:
Row.swift
open class Row {
// Existing code (Good):
public var cellIdentifier: String { return String(describing self) }
// The change (Bad):
public var cellIdentifier: String = String(describing: self)
DifferentRow.swift
public class DifferentRow: Row {
public override var cellIdentifier: String { return "\(super.cellIdentifier)" }
// returns the error below
Error:
Cannot override mutable property with read-only property 'cellIdentifier'
This:
public var cellIdentifier: String { return String(describing self) }
is defining a computed property. No value is stored. Every time you access cellIdentifier the closure runs and returns the String. It is read-only because only the getter has been provided.
This:
public var cellIdentifier: String = String(describing: self)
is a stored value property and it is read/write.
The error is telling you that you can't replace a property that has read/write capabilities with one that has only read capabilities.
Note: if you are initializing a property with a value, you can't access self because self doesn't represent the class/struct instance until the object is completely initialized. If you made the property a lazy var, you could use self in the initialization, because then the property would be initialized once the first time it is accessed.
You can read more about Swift properties here in the Swift Language Guide
You can’t override a “read from and write to”-property with a property which one can only read from.
You can assign a different value:
public override var cellIdentifier: String = “newValue”
or create both a set and a get implementation:
public override var cellIdentifier: String {
get { return “\(super.cellIdentifier)” }
set { super.cellIdentifier = newValue }
}
Under Computed Properties read more on this syntax.
I think the error message is quite confusing.
The problem with
public var cellIdentifier: String = String(describing: self)
is the reference to self:
When assigning cellIdentifier during definition, self is not guarateed to be fully initialized.
Therefore, it is forbiddin to call a function (like String(describing:)) and hand-in the half-initilized self
One solution could be to make cellIdentifier a lazy property:
public lazy var cellIdentifier: String = String(describing: self)
This will automatically delay the function call to the time after initialization has finished.

Error - Cannot use mutating member on immutable value: function call returns immutable value

So I have this custom struct
public struct Feature {
var featureID: String = ""
var featureName: String = ""
var matchingFieldValue: String = ""
var polygonCollection = [MyPolygon]()
mutating func setFeatureID(featureID: String) {
self.featureID = featureID
}
func getMatchingFieldValue() -> String {
return matchingFieldValue
}
mutating func setMatchingFieldvalue(matchingFieldValue: String) {
self.matchingFieldValue = matchingFieldValue
}
public func getPolygonCollection() -> [MyPolygon] {
return polygonCollection
}
}
and I am trying to append a polygon to my polygonCollection by calling this function
feature.getPolygonCollection().append(polygon)
but I am getting the error
cannot use mutating member on immutable value: function call returns immutable value
by the way, I am defining the polygon in another class, it is a long class so just put the relevant calling code that gives the error.
All the previously asked ques
I appreciate all the help.
Due to value semantics getPolygonCollection() returns an immutable copy of polygonCollection. You cannot change it. That's what the error message says.
Add this function in the struct
mutating func add(polygon: MyPolygon) {
self.polygonCollection.append(polygon)
}
and call it
feature.add(polygon)

Instance member cannot be used on type

I have the following class:
class ReportView: NSView {
var categoriesPerPage = [[Int]]()
var numPages: Int = { return categoriesPerPage.count }
}
Compilation fails with the message:
Instance member 'categoriesPerPage' cannot be used on type
'ReportView'
What does this mean?
Sometimes Xcode when overrides methods adds class func instead of just func. Then in static method you can't see instance properties. It is very easy to overlook it. That was my case.
You just have syntax error when saying = {return self.someValue}. The = isn't needed.
Use :
var numPages: Int {
get{
return categoriesPerPage.count
}
}
if you want get only you can write
var numPages: Int {
return categoriesPerPage.count
}
with the first way you can also add observers as set willSet & didSet
var numPages: Int {
get{
return categoriesPerPage.count
}
set(v){
self.categoriesPerPage = v
}
}
allowing to use = operator as a setter
myObject.numPages = 5
For anyone else who stumbles on this make sure you're not attempting to modify the class rather than the instance! (unless you've declared the variable as static)
eg.
MyClass.variable = 'Foo' // WRONG! - Instance member 'variable' cannot be used on type 'MyClass'
instanceOfMyClass.variable = 'Foo' // Right!
It is saying you have an instance variable (the var is only visible/accessible when you have an instance of that class) and you are trying to use it in the context of a static scope (class method).
You can make your instance variable a class variable by adding static/class attribute.
You instantiate an instance of your class and call the instance method on that variable.
Another example is, you have class like :
#obc class Album: NSObject {
let name:String
let singer:Singer
let artwork:URL
let playingSong:Song
// ...
class func getCurrentlyPlayingSongLyric(duration: Int = 0) -> String {
// ...
return playingSong.lyric
}
}
you will also get the same type of error like :
instance member x cannot be used on type x.
It's because you assign your method with "class" keyword (which makes your method a type method) and using like :
Album.getCurrentlyPlayingSongLyric(duration: 5)
but who set the playingSong variable before? Ok. You shouldn't use class keyword for that case :
// ...
func getCurrentlyPlayingSongLyric(duration: Int = 0) -> String {
// ...
return playingSong.lyric
}
// ...
Now you're free to go.
Your initial problem was:
class ReportView: NSView {
var categoriesPerPage = [[Int]]()
var numPages: Int = { return categoriesPerPage.count }
}
Instance member 'categoriesPerPage' cannot be used on type 'ReportView'
previous posts correctly point out, if you want a computed property, the = sign is errant.
Additional possibility for error:
If your intent was to "Setting a Default Property Value with a Closure or Function", you need only slightly change it as well. (Note: this example was obviously not intended to do that)
class ReportView: NSView {
var categoriesPerPage = [[Int]]()
var numPages: Int = { return categoriesPerPage.count }()
}
Instead of removing the =, we add () to denote a default initialization closure. (This can be useful when initializing UI code, to keep it all in one place.)
However, the exact same error occurs:
Instance member 'categoriesPerPage' cannot be used on type 'ReportView'
The problem is trying to initialize one property with the value of another. One solution is to make the initializer lazy. It will not be executed until the value is accessed.
class ReportView: NSView {
var categoriesPerPage = [[Int]]()
lazy var numPages: Int = { return categoriesPerPage.count }()
}
now the compiler is happy!
I kept getting the same error inspite of making the variable static.
Solution: Clean Build, Clean Derived Data, Restart Xcode. Or shortcut
Cmd + Shift+Alt+K
UserNotificationCenterWrapper.delegate = self
public static var delegate: UNUserNotificationCenterDelegate? {
get {
return UNUserNotificationCenter.current().delegate
}
set {
UNUserNotificationCenter.current().delegate = newValue
}
}
Just in case someone really needs a closure like that, it can be done in the following way:
var categoriesPerPage = [[Int]]()
var numPagesClosure: ()->Int {
return {
return self.categoriesPerPage.count
}
}

Swift println() does not display anything in a let in

Why I can't see the output of println() when it is called inside an in statement? And how I can see this output in Xcode?
I have done this dummy test code:
public class TestClass {
public var testType: String = ""
public func test(test:((TestClass) -> Void)!){
testType = "TEST"
}
}
var request = TestClass()
request.test({(response: TestClass) in
println("Test: \(response.testType)")
})
In your example you are calling method test() takes as parameter function of type TestClass -> Void. However, in implementation of test() method you never call passed function, thus println() is never executed.
You could try
public func test(testFunction:((TestClass) -> Void)!){
testType = "TEST"
testFunction(self)
}
You don't call the closure inside TestClass.test
Change it to
public func test(test:((TestClass) -> Void)!){
testType = "TEST"
test(self)
}