Reputation: 21
I have the following variable:
var npill : String!
It's an Int value, but I can't set it as Int because of:
npillIn: fieldNumeroPillole.text!,
How can I convert this var to a Int var? I have tried the following:
var number1: Int = (npill! as NSString).intValue
By the above code I receive the following error:
cannot use instance member 'npill' within property initializer, property initializers run before "self" is aviable
If I then set:
var number1: Int = (self.npill! as NSString).intValue
The error it outputs is as follows:
Value of type '(NSObject) -> () -> Farmaco' has no member 'npill'
If anyone knows how I should be converting it properly, please let me know.
Upvotes: 1
Views: 9050
Reputation: 73166
(As @Hamish pointed out in a comment below, I misunderstood what the OP was really asking about. I'll leave my answer, however, as some curiosa and insights regarding !
type annotation, which may be relevant for future readers of this question)
For any type of String
optionals, their values needs to be unwrapped prior to using the failable init?(_ text: String)
initializer or Int
.
In your example, the variable npill
is an optional, as you've annotated its type with the !
specifier (which should be used with care). Quoting from the implemented evolution proposal SE-0054 [emphasis mine]
Appending
!
to the type of a Swift declaration will give it optional type and annotate the declaration with an attribute stating that it may be implicitly unwrapped when used.
Hence, it's entirely legal to use npill
directly with the init?(_ text: String)
initializer of Int
, as it will be unwrapped (without any safety check for nil
content!) on-the-fly upon use.
// UNSAFE example!
var npill: String! = "42"
if let npillInt = Int(npill) {
/* ^^^^^^^^ ^^^^^- since 'npill' has a type annotated with
| '!', it will be unsafely unwrapped at
| this point
\
the optional binding here safely unwraps the return from
the failable Int initializer, but has nothing to do with
the unwrapping of 'npill' */
print(npillInt) // 42
}
// why unsafe? consider
npill = nil
if let npillInt = Int(npill) { // runtime exception!
// ...
}
Generally you should avoid using the !
annotation, however, unless you are entirely certain that the content of the resulting optional variable will never ever be nil
.
Leaving aside the cons of even using the !
annotation: you may implement a safe version of the unsafe example above, by overriding the unsafe implicit unwrapping with safe explicit unwrapping techniques. For a given optional variable declared using the !
annotation, we may still apply safe means to unwrap it, e.g. optional binding or using the nil coalescing operator. @appzYourLife has already showed one perfectly valid and safe way to handle the unwrapping and attempted type conversion of npill
using optional binding, so I'll simply include another example using the nil
coalescing operator instead:
// "safe" example (STILL: why use the `!` annotation?)
var npill: String! = "42"
if let npillInt = Int(npill ?? "x") {
/* ^^^^^ if 'npill' is 'nil', the Int initializer will
be given the value "x", which itself will lead
it to fail, which is safe here as we intend to
bind the result of the initialization to 'npillInt' */
print(npillInt) // 42
}
npill = nil
if let npillInt = Int(npill ?? "x") {
// ... doesnt enter
}
The consensus of the examples above is that if we're even slightly uncertain whether npill
can ever be nil
or not, we need to treat it as if it was just an optional not type annotated with !
(i.e. String?
); overriding the default unsafe unwrapping with safe means when working with the variable. In such a case, why would we even want to use the !
typ annotation at all, as it only brings fragility/danger to our application?
Upvotes: 0
Reputation: 59496
Thank you to @Hamish for pointing out what the OP was asking
So the problem seems to be this
import Foundation
class Foo {
var npill : String!
var number1: Int = (npill! as NSString).intValue
}
error: cannot use instance member 'npill' within property initializer; property initializers run before 'self' is available
var number1: Int = (npill! as NSString).intValue
^
You are using a property to populate another property, and this is not allowed.
However you can easily fix the problem postponing the initialisation of number1
. Infact if you make number1 lazy
, it will be populated only when used.
class Foo {
var npill : String!
lazy var number1: Int = { return Int(self.npill!)! }()
}
Warning: Of course this code will crash if
npill
is stillnil
whennumber1
is used.
You can simply write
let npill: String! = "34"
if let npill = npill, let num = Int(npill) {
print(num) // <-- here you have your Int
}
Upvotes: 2