Error: 'String' is not convertible to 'String!' - swift

mapView.rac_valuesForKeyPath("userTrackingMode", observer: self).subscribeNextAs {
// block handling
I get an error 'String' is not convertible to 'String!'. Any suggestions what this may mean?
I used to think, that String! is same as String, so it is unwrapped String?...
Xcode 7.3.1
Swift 2.2
ReactiveCocoa 4.1.0

I think the compiler is reporting a wrong error.
You can simplify the expression using
let key: String! = "userTrackingMode"
and then use key instead of the literal.
That will simplify the expression and will help the compiler to print the real error.
Type inferring is complicated and when the compiler doesn't find a valid type combination, it can show you a wrong error.

Related

Difference between wrapping a value and explicitly declaring value as a type in Swift

I came across a heterogeneous dictionary definition like this on a tutorial online:
var mixedMap4 = [AnyHashable(0): "Zero" as Any,
AnyHashable(1): 1.0 as Any,
AnyHashable("pi"): 3.14 as Any]
I was wondering why the author chose to write
AnyHashable(0) instead of 0 as AnyHashable. When I tried this on Swift playground, it also worked. However when I turned "Zero" as Any into Any(0) it gives the following
error: error: The Dictionary.xcplaygroundpage:41:34: error: protocol
type 'Any' cannot be instantiated var mixedMap4 = [AnyHashable(0):
Any("Zero") ,
Thank you for the answer
The clue is in the error message.
AnyHashable is a struct that type-erases the underlying hashable type, and so can be directly instantiated as an object
Any is a protocol and therefore can't be directly instantiated, although all other types can be complied with it, thus a String such as "Zero" can be cast as Any but Any(String) is meaningless.
To me it all just feels like a bucket load of trouble waiting to happen!

'String' is not convertible to 'String?'

Using ReactiveSwift, I've used the following code:
let alertMessageProperty = MutableProperty<String?>(nil)
...
.on(failed: { self.alertMessageProperty.value = $0.localizedDescription })
...
which means:
self.alertMessageProperty.value is of type String?
in .on(failed:), failed is of type ((Error) -> Void)? so $0 is of type Error and $0.localizedDescription is of type String.
in a simple Playground, assigning a String to a String? variable works fine, as expected.
It does not compile and I get this error:
'String' is not convertible to 'String?'
I think String is SO convertible to String?. What's going on here?
Versions: Swift 3.2 - ReactiveSwift 2.0.1
There is a lot missing in your example so I can not reproduce the exact problem.
Your code that you left out in ... is probably a lot more complicated, maybe a chain of multiple reactive operations, and my guess is that the actual error is something completely different somewhere in that code. The error message you're getting is just misleading due to some bug i the Swift compiler.
You can try to break up your code into smaller pieces and see if the compiler now fails at a different place and try to narrow it down that way.

Using 'Any' and 'AnyObject' types in Swift Linux gives errors

I have this line of code:
produceJSONMessage(message: message as AnyObject)
That works ok in XCode (Mac). However building it in linux using swift build produces an error:
/home/ubuntu/x/x/objects.swift:x:x: error: 'Any' is not convertible to 'AnyObject'; did you mean to use 'as!' to force downcast?
produceJSONMessage(message: message as AnyObject)
So I followed its advice by using produceJSONMessage(message: message as! AnyObject). It doesn't throw an error during build, but it crashes during runtime with:
Could not cast value of type 'Any' (0x9aab88) to 'Swift.AnyObject' (0x7f7c84007c88).
Anyway I got it to build and not throw an error with:
produceJSONMessage(message: message as? AnyObject)
The new problem is that when the function receives the object, it is always nil (it is not nil before entering the function). This is the function signature:
func produceJSONMessage(message: AnyObject? = nil)
Where message is usually a of String:Any type or a plain String
Anything that I should take note of here? All combinations of the codes I posted work fine for Mac XCode.
I made it work by removing AnyObject from my code above and replacing them with Any. Maybe I misused the AnyObject type, but it didn't help that it built ok in Mac but not in Linux!

`?` causing segmentation fault in Xcode 8.3.2's Swift compiler

I have this line of Swift which use to compile without issue
let layoutSettings = try LayoutSettings.deserialize(params: layoutSettingsParams as Dictionary<String, AnyObject?>)
As of Xcode 8.3.2 I get the error
Swift Compiler Error
Command failed due to signal:
Segmentation fault: 11
If I remove the ? at the end of the line of code it compiles without issue.
How do I use the nullable type without crashing the compiler?
AnyObject and AnyObject? are not the same thing. AnyObject? is actually syntactic sugar for Optional< AnyObject >. The fact that it compiles with Dictionary< String, AnyObject > but not Dictionary< String, AnyObject? > means that Dictionary< String, AnyObject > or [String: AnyObject] is the correct type, or convertible to the correct type. In general the swift compiler occasionally has problems with type inference which either causes it to crash or to compile very slowly. I notice this most frequently with dictionaries and with returns from .map(). In both cases if you explicitly state the type (even if according to the rules of the language it should be inferred) it usually helps the compiler go faster and/or not crash. In these instances I think it also helps the reader, because if the compiler can't infer the type easily its often the case that a human can't do it without some thinking as well.

Cast to a Metatype Type in Swift?

Can you cast to a Metatype Type in Swift? It really seems like you should be able to (after all you can instantiate objects from Metatypes).
The following doesn't work:
class Super {}
class A : Super {}
let superA:Super = A()
let subType = superA.dynamicType
let afterCast = superA as subType
//Compiler error: "use of undeclared type 'subType'"
Does anyone know the right way to do this?
Edit:
As newacct pointed out, the result of .dynamicType is obviously not known until runtime, so a compile-time cast to the result of .dynamicType would not make sense.
So the answer is: "You can't" (and there is no good reason to try).
First of all, as takes a type, not an expression, on the right-hand side. So what you have is a syntax error.
What you seem to be trying to do is "cast" to a type that is computed at runtime. What would that even mean? Let's first consider what is a "cast".
Usually, when we have a cast expression x as T, it has two components:
At compile-time: The entire cast expression x as T has compile-time type T?, which allows you to do stuff with the resulting expression that you maybe cannot do on x directly. In other words, it allows you to change the compile-time type.
At runtime: It checks whether the runtime type of x is a subtype of T, and if it is, it evaluates to the optional containing that value, otherwise, it evaluates to nil.
If the type T is not known at compile-time, then obviously you cannot do the compile-time part of it. (The compile-time type of the resulting expression cannot, obviously, depend on something which is not known at compile-time.)
The other part, the runtime component, could that be done with a type computed at runtime? Sure. For example,
import Foundation
let afterCast : Super? =
(superA as AnyObject).isKindOfClass(subType) ? superA : nil
It's not clear if that is what you want.