convert String to AnyObject in swift - swift

I have a static string variable
struct numb {
static var selectedNumber: String = String()
}
I am trying to unwrap ( while casting it as AnyObject) the value and assign it to messageComposeViewController
if let textMessageRecipients :AnyObject = numb.selectedNumber
{
messageComposeVC.recipients = textMessageRecipients as? [AnyObject]
messageComposeVC.body = "Testing 123!"
}
the compiler is throwing an error
bound value in a conditional binding must be of Optional type
How do I convert my string to AnyObject and assign it to the message view controller?

From your examples and the error you see, you are attempting to unwrap a value that isn't optional. You don't need to use if let when there is a value. You can force a cast using if let like this:
if let myValue:AnyObject = numb.selectedNumber as? AnyObject
This will produce a warning saying that casting a String to AnyObject will always succeed, again you don't need the if let, your casts will always succeed.
Your final example should look something like:
messageComposeVC.recipients = [numb.selectedNumber] as [AnyObject]
messageComposeVC.body = "Testing 123!"

You need to make your selectedNumber to optional like this:
struct numb {
static var selectedNumber: String?
}

Tested in Swift 2.1, Xcode 7. works !
var myItems : String?
myItems = ItemsTextfield.text
myItems as! AnyObject

Related

Is there a way to compile with a generic type?

This is something that has vexed a number of developers including myself. Let say we have a protocol that defines a subscript which we apply to a simple class.
protocol Cache {
subscript<Value>(_: String) -> Value? { get set }
}
class InMemoryCache: Cache {
private var cache: [String: Any] = [:]
subscript<Value>(key: String) -> Value? {
get {
cache[key] as? Value
}
set {
if let value = newValue {
cache[key] = value
} else {
cache.remove(key)
}
}
}
}
This works fine as long as we know the types:
cache["abc"] = 5
let x: Int? = cache["abc"]
but the developers want to do this:
cache["abc"] = nil
Which won't compile because the compiler cannot determine the Value generic type. This works however
cache["abc"] = nil as String?
I've tried a number of things but they all have drawbacks. Things like adding a second subscript with the Any type. Nothing seems to work well even though it would seem like a simple problem.
Has anyone found a solution that handles cache["abc"] = nil?
You can do this by changing your protocol requirements somewhat.
Have the protocol require a subscript that does not use generics, and returns an Any?.
protocol Cache {
subscript(key: String) -> Any? { get set }
}
This subscript will let you do the following:
cache["abc"] = 5
cache["abc"] = nil
let value = cache["abc"] // value is an `Any?`
but it will not let you do this:
let number: Int? = cache["abc"] // error
So, let's fix that by adding another subscript to Cache. This subscript is equivalent to your original subscript requirement, except it doesn't need a setter and will call the other subscript (the one required by the protocol):
extension Cache {
subscript<Value>(key: String) -> Value? {
self[key] as? Value
}
}
(If you're worried that this subscript calls itself, don't be. self[key] here actually calls the other subscript, not this one. You can confirm this in Xcode by command-clicking on the [ or the ] in self[key] to jump to the definition of the other subscript.)
Then, implement the required subscript in your class:
class InMemoryCache: Cache {
private var cache: [String: Any] = [:]
subscript(key: String) -> Any? {
get { cache[key] }
set { cache[key] = newValue }
}
}
This will allow all of the following to compile:
let cache = InMemoryCache()
cache["abc"] = 5
let x: Int? = cache["abc"]
cache["abc"] = nil
There is a workaround to have your desire output.
Because this is a dictionary so you get assign nil directly in your InMemoryCache
class InMemoryCache: Cache {
private var cache: [String: Any] = [:]
subscript<Value>(key: String) -> Value? {
get {
cache[key] as? Value
}
set {
if let value = newValue {
cache[key] = value
} else {
cache[key] = nil // make nil directly here
}
}
}
}
In here because of Value is a generic type. So you can not assign nil directly. It must have a specific type.
Instead you can do like this
let nilValue : Int? = nil // any type nil you want
cache["abc"] = nilValue
or directly cast it to nil of any tupe before assign to dictionary
cache["abc"] = (nil as String?)
It will refresh anything value is store in the key.
Example
// value
let nilValue : Int? = nil
var number : Int? = nil
var string : String? = nil
cache["abc"] = 5
number = cache["abc"] // Optional.some(5)
cache["abc"] = "abc"
number = cache["abc"] // nil
string = cache["abc"] // Optional.some("abc")
cache["abc"] = nilValue
number = cache["abc"] // nil
string = cache["abc"] // nil
The reason why you are having a hard time with this is because
cache["abc"] = nil
cannot be compiled. There is not enough information to infer the generic type of the subscript - or of the optional value. The compiler sees something like
cache<?>["abc"] = Optional<?>.none
How is it supposed to figure out what to put in place of the question marks?
There's another ambiguity. Your cache can contain any type, even Optional. When you are assigning nil to the subscript, how does anybody know if you want to remove the element or store an instance of Optional<Something>.none at the subscript?
When I find myself fighting the language in this way, I usually try to take a step back and ask if I am perhaps doing something fundamentally bad. I think, in this case, the answer is yes. You are trying to pretend something is more strictly typed than it really is.
I think your getter/setter should explicitly take a value that is of type Any. It works better and it has the advantage that it explicitly documents for the user that a Cache conforming type can store anything in it.
For this reason, I would say TylerP's solution is the best. However, I would not create a subscript in the extension, I would define a function
extension Cache
{
func value<Value>(at key: String) -> Value?
{
self[key] as? Value
}
}
The reason for this is that the compiler can get confused when you have multiple subscripts with similar signatures. With the extension above, I can conform Dictionary<String, Any> to the protocol and not need a new class.
extension Dictionary: Cache where Key == String, Value == Any {}
var dict: [String : Any] = [:]
dict["abc"] = 5
let y: Int? = dict.value(at: "abc")
dict["abc"] = nil
Obviously, the above won't be useful to you if you need reference semantics for your cache.
TylerP's solution was pretty much bang on the money. For completeness though, here's what the code now looks like:
protocol Cache {
/// Handles when we need a value of a specific type.
subscript<Value>(_: String) -> Value? { get }
/// Handles getting and setting any value.
/// The getter is rarely used because the generic getter above
/// is used. Setting a value compiles because we don't care what
/// type is it. Setting a `nil` also compiles for the same reason.
subscript(_: String) -> Any? { get set }
}
class InMemoryCache: Cache {
private var cache: [String: Any] = [:]
subscript(key: String) -> Any? {
get { cache[key] }
set {
if let value = newValue {
cache[key] = value
} else {
remove(key)
}
}
}
subscript<Value>(key: String) -> Value? {
cache[key] as? Value
}
}

Swift Keypath from String

Is there a way to create a Keypath from a String in Swift 4 to access a value in a struct by its path or variable name
Finally I found out that I should use CodingKeys instead of KeyPaths
to access the a value of a variable of a struct by String
Thanks in advance,
Michael
consider you have something like this,
struct foo {
var test: doo
}
struct doo {
var test: Int
}
//How to use it
let doo = Doo(test: 10)
let foo = Foo(test: doo)
let mykeyPath = \Foo.test.test
let result = foo[keyPath: mykeyPath]
print(result)

What is difference between optional and decodeIfPresent when using Decodable for JSON Parsing?

I am using Codable protocol from Swift 4 first time, I am not able to understand use of decodeIfPresent from Decodable.
/// Decodes a value of the given type for the given key, if present.
///
/// This method returns `nil` if the container does not have a value associated with `key`, or if the value is null. The difference between these states can be distinguished with a `contains(_:)` call.
///
/// - parameter type: The type of value to decode.
/// - parameter key: The key that the decoded value is associated with.
/// - returns: A decoded value of the requested type, or `nil` if the `Decoder` does not have an entry associated with the given key, or if the value is a null value.
/// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
public func decodeIfPresent(_ type: String.Type, forKey key: KeyedDecodingContainer.Key) throws -> String?
Here it suggest that it returns nil, if value not present with associated key. If this is the only reason , then how it differ from optional property, as optional variable also set to nil if value is not present in response.
There's a subtle, but important difference between these two lines of code:
// Exhibit 1
foo = try container.decode(Int?.self, forKey: .foo)
// Exhibit 2
foo = try container.decodeIfPresent(Int.self, forKey: .foo)
Exhibit 1 will parse:
{
"foo": null,
"bar": "something"
}
but not:
{
"bar": "something"
}
while exhibit 2 will happily parse both. So in normal use cases for JSON parsers you'll want decodeIfPresent for every optional in your model.
Yes, #Sweeper's comment makes a sense.
I will try to explain it according to my understanding.
public class User : Decodable{
public var firstName:String
public var lastName:String
public var middleName:String?
public var address:String
public var contactNumber:String
public enum UserResponseKeys: String, CodingKey{
case firstName = "first_name"
case lastName = "last_name"
case middleName = "middle_name"
case address = "address"
case contactNumber = "contact_number"
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: UserResponseKeys.self)
self.firstName = try container.decode(String.self, forKey: .firstName)
self.lastName = try container.decode(String.self, forKey: .lastName)
self.middleName = try container.decodeIfPresent(String.self, forKey: .middleName)
self.address = try container.decode(String.self, forKey: .address)
self.contactNumber = try container.decode(String.self, forKey: .contactNumber)
}
}
Above is my User class, in which I marked middleName as optional parameter, because it may possible that JSON response may not provide middleName key-value pair in response, so we can use decodeIfPresent.
self.middleName = try container.decodeIfPresent(String.self, forKey: .middleName)
While for others variables which are mandatory fields so we are sure that no need to use of optional for that. We used only decode for that as that method does not return optional.
public func decode(_ type: String.Type, forKey key: KeyedDecodingContainer.Key) throws -> String
Above decode function returns String while decodeIfPresent returns String?, so we can use optional variable to store that.
So final conclusion is that if you are not sure of service response contract or you may dealing with any third party services where JSON response and parameters may change without your knowledge then you can use decodeIfPresent so it can handle absence of particular parameter in response and set value as nil.
I think it makes sense to use decodeifPresent rather than an optional property if you want to use a default value for a property that could be missing from the JSON.
For example, let's examine 3 situations:
1. All the keys are present in the JSON:
Let's suppose you must decode this JSON:
{
"project_names": ["project1", "project2", "project3"],
"is_pro": true
}
You can use this struct:
struct Program: Codable {
let projectNames: [String]
let isPro: Bool
}
and you will get a Program object with a isPro value equal to true.
(I suppose your decoder keyDecodingStrategy is .convertFromSnakeCase in the rest of this example)
2. Some keys are missing in the JSON and you're ok to have an optional in Swift:
{
"project_names": ["project1", "project2", "project3"]
}
You can now use this struct:
struct Program: Codable {
let projectNames: [String]
var isPro: Bool?
}
and you will get a Program object with a isPro value equal to nil.
If the JSON looked like this:
{
"project_names": ["project1", "project2", "project3"],
"is_pro": true
}
then isPro would be a Bool? with value true.
Maybe that's what you want, but probably you would like to have a Bool with a default value of false. That's where decodeIfPresent could be useful.
3. Some keys are missing in the JSON and you want a non-optional property with a default value in Swift:
If your struct looks like this:
struct Program: Codable {
let projectNames: [String]
var isPro: Bool = false
}
then you will get a parsing error if the "is_pro" attribute is not present in your JSON. Because Codable expects to find a value to parse a Bool property.
In that situation, a good idea would be to have an initializer with decodeIfPresent, like so:
struct Program: Codable {
let projectNames: [String]
let isPro: Bool
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.projectNames = try container.decode([String].self, forKey: .projectNames)
self.isPro = try container.decodeIfPresent(Bool.self, forKey: .isPro) ?? false
}
}
This allows you to have the best of both worlds:
your struct has a Bool, not a Bool? property
you are still able to parse a JSON that does NOT contain the "is_pro" field
you can get a default value of false if the field is not present in the JSON.

Swift Conversion using a variable

Is there anyway to use conversion using a variable? I am using object stacking using type of "AnyObject" and I've been able to take the class type and populate a variable. Now I need to populate an array using conversion.
var myString = "Hello World"
var objectStack = [AnyObject]()
objectStack.append(myString)
let currentObject = String(describing: objectStack.last!)
var objectType = String()
let range: Range<String.Index> = currentObject.range(of: ":")!
objectType = currentObject.substring(to: range.lowerBound)
let range2: Range<String.Index> = objectType.range(of: ".")!
objectType = objectType.substring(from: range2.upperBound)
The code above will evaluate the class and set the value of "objectType" to "String". Now I'm trying to go the other way. Something like this:
for obj in objectStack{
obj = newObject as! objectType //this doesn't work
}
Is something like this possible?
There is a simpler, safer way to get the type:
let type = type(of: objectStack.last!) // String.Type
let typeString = String(describing: type) // "String"
The other way around is not possible because the type of the object is not known at compile time. Do you have a number of known types you want to try to cast to? In that case, use optional binding to check if the cast is successful:
let object = objectStack.last!
if let string = object as? String {
// do String stuff
}
else if let i = object as? Int {
// do Int stuff
}
// and so on
If you have a large number of possible types that share some common functionality: Use Protocols. See Swift Documentation for a nice introduction.
You define a protocol for some common functionality that different types can implement:
protocol Stackable {
func doStuff()
// (more methods or properties if necessary)
}
The protocol provides a contract that all types conforming to this protocol have to fulfill by providing implementations for all declared methods and properties. Let's create a struct that conforms to Stackable:
struct Foo: Stackable {
func doStuff() {
print("Foo is doing stuff.")
}
}
You can also extend existing types to make them conform to a protocol. Let's make String Stackable:
extension String: Stackable {
func doStuff() {
print("'\(self)' is pretending to do stuff.")
}
}
Let's try it out:
let stack: [Stackable] = [Foo(), "Cat"]
for item in stack {
item.doStuff()
}
/*
prints the following:
Foo is doing stuff.
'Cat' is pretending to do stuff.
*/
This worked for me:
var instance: AnyObject! = nil
let classInst = NSClassFromString(objectType) as! NSObject.Type
instance = classInst.init()

Swift dynamictype initialisation with dynamic protocol type

I have a number of structs which implement a Resource protocol. This defines that they must have a variable extendedInfo which conforms to ExtendedInfo protocol to provide a way to initialise them with json via init(json: [String: AnyObject]. I'm trying to provide a way to dynamically instantiate these, with JSON, providing the right type of ExtendedInfo and assign it to the struct's extendedInfo variable. However, I'm getting a Argument labels '(json:)' do not match any available overloads error when trying to instantiate them via their dynamicType
protocol Resource {
associatedtype ExtendedInfoTypeAlias: ExtendedInfo
var extendedInfo: ExtendedInfoTypeAlias? { get set }
}
protocol ExtendedInfo {
init(json: [String: AnyObject])
}
struct User: Resource {
typealias ExtendedInfoTypeAlias = UserExtendedInfo
let name: String = "Name"
var extendedInfo: UserExtendedInfo?
}
struct UserExtendedInfo: ExtendedInfo {
let age: Int?
init(json: [String: AnyObject]) {
age = json["age"] as? Int
}
}
let user = User()
let sampleJSON = ["age": 50]
let userExtendedInfo = user.extendedInfo.dynamicType.init(json: sampleJSON) // Argument labels '(json:)' do not match any available overloads
user.extendedInfo = userExtendedInfo
Any ideas guys? Thanks
First of all, you don't need to explicitly define the type of ExtendedInfoTypeAlias in your struct implementation – you can just let it be inferred by the type you provide for extendedInfo.
struct User: Resource {
let name: String = "Name"
var extendedInfo: UserExtendedInfo?
}
Second of all, you can just use the protocol's associated type of your given struct's dynamicType in order to use your given initialiser. For example:
user.extendedInfo = user.dynamicType.ExtendedInfoTypeAlias.init(json: sampleJSON)
print(user.extendedInfo) // Optional(Dynamic_Protocols.UserExtendedInfo(age: Optional(50)))
As for why your current code doesn't work, I suspect it's due to the fact that you're getting the dynamicType from an optional – which is preventing you from calling your initialiser on it.
I did find that the following works, even when extendedInfo is nil. (This is a bug).
user.extendedInfo = user.extendedInfo!.dynamicType.init(json: sampleJSON)
Change:
let user = User()
To:
var user = User()
and try this:
user.extendedInfo = UserExtendedInfo(json: sampleJSON)