Failing a Swift initializer without setting stored property - swift

I'm writing an application Bluetooth-controlled keynote remote. This will be using AppleScript to control Keynote based on interactions with the CoreBluetooth framework.
Consider this class, which requires the use of an optional OSALanguage initializer.
class KeynoteController {
let applescriptLanguage: OSALanguage
init?() {
if let applescriptLanguage = OSALanguage(forName: "AppleScript") {
self.applescriptLanguage = applescriptLanguage
} else {
return nil // Compile error on this line
}
}
}
In this example, I want to fail initializing my KeynoteController if there's no OSALanguage named "AppleScript" (admittedly unlikely, but good design). However, I can't return from my initializer until all stored properties are populated.
I could make applescriptLanguage an optional, but since it's non optional and constant if initialization succeeds, this seems like a hack.
What's the correct way to design this?

The problem seems to come from trying to make applescriptLanguage a non-optional. The compiler wants it to be assigned a value, even if the object is failing initialization.
Fix it by making it optional property (implicitly unwrapped because it should never actually be nil after initialization).
let applescriptLanguage: OSALanguage!
This seems like a compiler error to me, but I have no idea what's going on under the hood.
Alternatively, you could temporarily assign it to a dummy value in the else block. This adds extra initialization time and memory allocation, so probably not the best idea, but it'll work if you really want to have the property be non-optional.
} else {
self.applescriptLanguage = OSALanguage()
return nil
}

Related

Can I make self.entity a non optional for certian functions in a GKComponent using swift?

I'm using the GameplayKit entity component system to develop a game.
I have a number of GKComponent. Most of the instance functions require that self.entity is not nil, but it is an optional, as a component may be initialised before being attached to an entity.
If I "do things properly", I understand I should use guard (or if) to check that self.entity is not nil, for each function where I require it. This adds a chunk of extra code for each function, and in addition a function may require the entity has specific components to function.
Problem statement:
For some functions in a GKComponent, I want to specify that the function requires self.entity is not nil, and has some specific components, without needing a number of guard or if statements which bulks up my code.
Things I've tried:
I tried creating an extension to GKComponent.
The extension contains a function which throws an error if the entity is nil, returns true if it is not nil.
import Foundation
import GameplayKit
extension GKComponent {
enum ComponentExtensionError: Error {
case hasNoEntity
}
func requiresEntity() throws -> Bool {
if (self.entity != nil) {
return true
} else {
throw ComponentExtensionError.hasNoEntity
}
}
}
GKComponent function:
func setTileWalls () {
try? self.requiresEntity()
# Some stuff
}
This compiles, but doesn't solve my problem, as I still have to access the entity as self.entity?.somefunc().
I figured now I know that self.entity is not nil, I could proceed to set it as unwrapped...
func setTileWalls () {
try? self.requiresEntity()
self.entity = self.entity!
# Some stuff
}
But alas, you cannot SET self.entity.
I considered I could in stead modify the extension to return the entity, and then do something like...
func stTileWalls () {
guard let entity = self.requiresEntity() else { throw }
}
but then I'd need to modify each functions code to use entity rather than self.entity. I don't feel like this is optimal solution, but maybe an acceptable one.
My ideal solution would be to be able to call a function which checks that self has an entity, and some components, making them non optional for the scope, and throwing an error if any are nil.
Why? I'm frustrated by entity and any component always being optional (when I know it shouldn't be). If I understand correctly, "doing things properly" requires that I guard and throw (or return maybe?). Syntactically I feel it looks ugly and I feel like I'm missing something in terms of fixing this in an elegent way with Swift.
There is no easy solution to solve this issue if you want a safe solution that requires less boilerplate code than unwrapping an optional.
Throwing an error instead of returning nil is definitely a bad idea, since handling an error requires even more boilerplate code than safely unwrapping an optional.
You cannot override existing variables types, so you cannot make GKComponent.entity non-optional either.
Use guard statements for optional binding, that way you can minimise the boilerplate code for unwrapping the value.

Why doesn't Swift allow setting value of an optional constant after object initialization?

The code below creates a compile error saying "error: return from initializer without initializing all stored properties ('self.response' not initialized)"
class Question {
let text: String
let response: String?
init(text: String) {
self.text = text
}
func ask() {
print(text)
}
}
I want to make "response" constant and by the time I initialize, response will be unknown. Besides "return from initializer without initializing all stored properties", why do I have to make it "var"?
Because Swift tries to make you implement safe code, and having uninitialized stored properties is really not safe, because you or a client of your class may use that constant before it is properly set and the result will be undefined. This is a cause of a lot of bugs that may not be immediately caught.
Moreover, because an optional constant stored property is initialized as having a nil value, if you were able to change its value after initialization you would violate the "constantness" of your constant. That is why you need to declare it as a var.
Optional variables / properties are automatically set to nil by definition if no initial value is provided in the declaration line.
An optional constant is stuck to nil which makes no sense...
Therefore the compiler doesn't let you declare an optional constant this way.

Can't set nil to an optional property with custom setter in Swift

I have swift class with various properties, some of which have optional types.
class UserObject: PFUser{
//optional property
var optionalPhotoURL:String? {
get {
if let optionalPhotoURL:String = objectForKey("optionalPhotoURL"){
return optionalPhotoURL
}
//not needed but just for emphasis
return nil
}
//I am unable to set UserObject.optionalPhotoURL = nil with this setters
set {
if let newPhotoURL:String = newValue! {
setObject(newPhotoURL, forKey: "optionalPhotoURL")
}else{
self.optionalPhotoURL = nil
}
}
}
}
I am unable to set optionalPhotoURL as nil, if it already had a previous value assigned to it.
I guess my question is, how do i "unset" an optional property with custom setter?
Update
These setters all crash
set {
if let newPhotoURL:String = newValue {
setObject(newPhotoURL, forKey: "optionalPhotoURL")
}else{
self.optionalPhotoURL = nil
}
}
and this
set {
if (newValue != nil) {
setObject(newValue!, forKey: "optionalPhotoURL")
}else{
self.optionalPhotoURL = nil
}
}
What you have here is a computed property.
Swift properties can either be computed or stored. We can observe value changes in our stored properties by using didSet and willSet but here we still have a stored property.
In your case, since you have overridden set and get*, you don't have a stored property, you have a computed property. If you want a computed property to have a backing storage, you must create that independently.
So you may want something like this:
class FooClass {
private var storageProperty: String?
var accessProperty: String? {
get {
return self.storageProperty
}
set {
self.storageProperty = newValue
// or whatever logic you may like here
}
}
}
*: You can't override set without also overriding get. You can however override get without overriding set--this makes a readonly computed value.
Moreover, it's important that we implement our storage properties in this way over relying on key-value coding.
For starters, setObject(forKey:) approach doesn't even work on pure Swift types. This will only work on objects which inherit from Objective-C types. It's an inherited method from NSObject's compliance to NSKeyValueCoding protocol. Why the base object of Objective-C conforms to so many protocols is beyond me... but it does and there's nothing we can do about it.
If we have a code base in which some of our objects are inheriting from Objective-C objects (which basically any project will have, UIViewController, etc), and some of our objects are pure Swift objects (which you will tend to have when you're creating your own Swift classes from scratch), then our Swift objects will not be able to implement this same pattern. If we have some objects of both types, we'll either have to implement the pattern I show above for all of them (and then we have consistency) or we'll have to implement one pattern for some types and another for other types (Swift structs would definitely have to implement the above pattern, you can't just make them inherit from NSObject) (and then we have inconsistency, which we don't like).
But what's far worse about setObject(forKey:) is that the first argument of this method always will be of type AnyObject. There is no type safety to the method at all. Where things are stored via setObject(forKey:) is based purely on the key which we use. When we use setObject(forKey:), we take a pile of type-safety advantages that Swift gives us and we throw them out the window. If we don't care to leverage the advantages Swift gives us over Objective-C, why are we writing it in Swift at all?
We can't even make the stored property private when we use setObject(forKey:). Anyone who knows the key can call setObject(forKey:) and set that object to whatever they want. And that includes objects which are not strings. All we have to do to introduce a crash to this codebase is write a class extension or subclass which has a key collision on a different type other than what you've used (so maybe an NSData value for the same key). And even if it doesn't happen to be a different type, simply duplicating the same key for multiple properties is going to introduce bugs... and bugs that are hard to debug.
Never set a value of a computed property in its set scope by calling itself !
This causes an infinite loop and the app will crash.
I don't know which API setObject:forKey belongs to, but in the case of nil you are supposed to remove the object
set {
if let newPhotoURL = newValue {
setObject(newPhotoURL, forKey: "optionalPhotoURL")
} else {
removeObjectForKey("optionalPhotoURL")
}
}
Your property optionalPhotoURL is a computed property, it does not store any values:
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html
You might want to create an additional property which actually stores the value. However, why do you want to set it to nil, since you are not deleting they object in case of nil.

Swift basic expression

I'm very new to swift, but proficient in other languages like Java, JavaScript, C, ... I'm lost with Swift syntax when it comes to create expressions. Look at this basic example where I just try to find out if one string is contained into another by calling String.rangeOfString that returns an Optional Range (Range?)
This works as expected:
let LEXEMA:String="http://"
let longUrl:String="http://badgirls.many/picture.png"
let range=longUrl.rangeOfString(LEXEMA);
if (range? != nil) {
// blah
}
Now I'm trying to combine the expression inside the if, something like:
if (longUrl.rangeOfString(LEXEMA)? !=nil) {
// blah
}
But I always get syntax errors, the above yields a "Expected Separator" and can't understand why. Done some more tests:
if (absolutePath.rangeOfString(URL_LEXEMA) !=nil) { }
Expected Separator before "!"
if absolutePath.rangeOfString(URL_LEXEMA) !=nil { }
Braced block of statements is an unused closure
What am I doing wrong?
If you’re coming from other like Java, you might be thinking of optionals like pointers/references, and so used to equating them to nil and if non-nil, using them. But this is probably going to lead to more confusion. Instead, think of them like a container for a possible result, that you need to unwrap to use. if let combines the test and unwrapping operation.
With this in mind, here’s how you could adapt your code:
let LEXEMA: String="http://"
let longUrl: String="http://badgirls.many/picture.png"
if let range = longUrl.rangeOfString(LEXEMA) {
// use range, which will be the unwrapped non-optional range
}
else {
// no such range, perhaps log an error if this shouldn’t happen
}
Note, that ? suffixing behaviour you were using changes in Swift 1.2 so even the code in your question that compiles in 1.1 won’t in 1.2.
It’s possible that sometimes you are whether there was a value returned, but you don’t actually need that value, just to know it wasn’t nil. In that case, you can compare the value to nil without the let:
if longUrl.rangeOfString(LEXEMA) != nil {
// there was a value, but you don't care what that value was
}
That said, the above is probably better expressed as:
if longUrl.hasPrefix(LEXEMA) { }
For starters:
You don't need parenthesis with if statements unless you have nested parenthetical subexpressions that require it.
You don't need to specify the type on the left side of the = of a let or var declaration if Swift can figure it out from the right side of the =. Very often Swift can figure it out, and you can tell that Swift can figure it out, so you can avoid that redundant clutter.
You do need to specify the type if Swift cannot figure out the type from
the right side. Example:
For example, consider the following lines:
let LEXEMA = "http://"
let longUrl = "http://badgirls.many/picture.png"
Swift can figure out that they're strings.
Similarly for this function or class that returns a UIView:
var myView = ViewReturningClassOrFunc()
Consider this:
#IBOutlet var myView : UIView!
In the above line, Swift cannot figure out ahead of time it will be assigned a UIView, so you have to provide the type. By providing a ! at the end you've made it an implicitly unwrapped optional. That means, like ?, you're indicating that it can be nil, but that you are confident it will never be nil at the time you access it, so Swift won't require you to put a ! after it when you reference it. That trick is a time saver and big convenience.
You should NOT add the ? to the line:
if (longUrl.rangeOfString(URL_LEXEMA) !=nil) {
As another answer pointed out, you're missing the let.
if let longUrl.rangeOfString(URL_LEXEMA) {
println("What do I win? :-)")
}
swift is case sensitive language. you need to check about whitespaces as well
if longUrl.rangeOfString(LEXEMA) != nil {
//your condition
}
there should be space between statement != nil
Just add a space between != and nil like:
if longUrl.rangeOfString(LEXEMA) != nil {
// blah
}
I tested your code in playground, an error of Expected ',' separator reported.
And do not forget the rules that 1s and 0s and Airspeed Velocity said.

Returning an implicitly unwrapped optional

I'm writing a program in Swift which has various functions which should always return values, but in some cases cannot, and so the program crashes and alerts the user of the error. To accomplish this, I am using implicitly unwrapped Optionals as return values for my functions, so that error cases can just return nil (even though that code will never be reached). It looks something like this:
func giveMeAThing() -> Thing! {
if !possibleErrorCase() {
var thing = createAThingForSure()
return thing
}
else {
crashAndBurn()
return nil
}
}
Writing this, it feels a bit hacky, so my question is whether or not this is a good use of implicitly unwrapped Optionals in Swift. Is there a better way to structure my code that will avoid this?
It may be that the piece of the puzzle you are missing is #noreturn. If you declare a function as #noreturn, the compiler abandons any complaints if you don't fulfill the surrounding contract. Thus you can call such a method and not return any value, and the compiler will not complain because it knows we are going to die anyway. For example, fatalError and abort are declared this way.
Thus, the following is legal:
func f() -> String {
fatalError("oooooops")
}
That compiles even though we fail to fulfill the contract of returning a value, because #noreturn (in the declaration of fatalError) tears up the contract and flushes the pieces down the toilet.
Another possible way of approaching the same issue is to use assert. This crashes and burns for you if a condition is not met. So, in your example:
func giveMeAThing() -> Thing {
assert(!possibleErrorCase(), "gaaaaah!") // crash and burn if error case
return createAThingForSure()
}
The downside is that by default all asserts succeed in a shipping app. But it's great during development, and after all your shipping app should not be crashing and burning anyway.
I'd rather write this as
func giveMeAThing() -> Thing! {
if possibleErrorCase() {
crashAndBurn() // I assume this will not return anyhow
}
return createAThingForSure()
}
but that's likely just a question of taste.
You don't need an implicitly unwrapped optional since you don't expect the second case to return any value.
As commenters noted, use fatalError in the fail case.