Create a protocol for extending Optional<Any>
type to return it's non-optional-value:
private protocol AnyOptional {
var objectValue: Any? { get }
}
extension Optional: AnyOptional {
var objectValue: Any? {
switch self {
case .None:
return nil
case .Some(_):
return self! as Any
}
}
}
Thereafter you can use AnyOptional
protocol as a type, and cast Any?
objects to AnyOptional
, thereafter allowing us to make use of the .objectValue
property of AnyOptional
class User {
var name: String?
var email: String?
var id: String = "Default ID" // Lets try also with one non-optional
var identification_number: String?
var phone_number: NSMutableArray?
var user_group: String?
var date: NSDate?
}
var myUser = User()
myUser.name = "John"
myUser.phone_number = ["+44", "701 23 45 67"]
func updateProfile(user: User) {
let mirror = Mirror(reflecting: user)
for child in mirror.children {
let value : Any = (child.value as? AnyOptional)?.objectValue ?? child.value
switch(value) {
case let obj as String: print("String item: User.\(child.label!) = " + obj)
case let obj as NSMutableArray: print("NSMutableArray item: User.\(child.label!) = \(obj)")
case let obj as NSDate: print("NSDate item: User.\(child.label!) = \(obj)")
case _ : print("Non-initialized optional item: User.\(child.label!) = \(value)")
}
}
}
Which yields the following output
updateProfile(myUser)
/*
String item: User.name = John
Non-initialized optional item: User.email = nil
String item: User.id = Default ID
Non-initialized optional item: User.identification_number = nil
NSMutableArray item: User.phone_number = (
"+44",
"701 23 45 67"
)
Non-initialized optional item: User.user_group = nil
Non-initialized optional item: User.date = nil */
The benefit of using this solution is that it will "unwrap" optional non-nil values of child.value
(without the "Optional(...)"
padding) as well as values of child.value
that are not optional, without the need of separate "unwrapping" for the two cases. In the switch
case above, you can handle whatever non-nil property of the User
object that you need to work with, not just as String
but any of the types in your User
class. The obj
property in the switch
case will be of the non-optional type of each of the non-nil properties of your class. The default case corresponds to optionals with value nil
(not assigned).