There are some rarely used keywords, but they would be a good thing if you know them sometimes. @encode is one of them, which could get the a character for a given type.

In Objective-C, @encode is not difficult to use. Just pass in a type, and you get expect a C string which represents this type returned:

char *typeChar1 = @encode(int32_t);
char *typeChar2 = @encode(NSArray);
// typeChar1 = "i", typeChar2 = "{NSArray=#}"

We could get this string for any types. This keyword is commonly used in Objective-C runtime, when message delivering. When sending a message, the type information is always opted out. If you have to know the type to keep things well, you may want this string. In daily regular app development, we have some API which should contain this type to work. An example is CIAffineClamp, which needs the valueWithBytes:objCType: of NSValue to get a value. We just have to pass the encode string of that type to objCType. Another use case is finding out the missing type information, we would look at it deeper later.

In Swift, there is metatype for a type, which means the type information is kept even at runtime. So there is no need for Swift types to have this keyword. As a result, @encode is removed in Swift and we now cannot obtain the type encoded string of any types. However, in Cocoa we still have a objcType property in NSValue to get a pointer to the type:

class NSValue : NSObject, NSCopying, NSSecureCoding, NSCoding {
    var objCType: UnsafePointer<Int8> { get }


If we want to get the same result as @encode in Swift, a possible way would be converting them to NSNumber (which is a subclass of NSValue), then get the objCType from it:

let int: Int = 0
let float: Float = 0.0
let double: Double = 0.0

let intNumber: NSNumber = int
let floatNumber: NSNumber = float
let doubleNumber: NSNumber = double


// Result is:
// {Some "q"}
// {Some "f"}
// {Some "d"}
// Be notice that fromCString will return a `String?` instead of `String`

For other types which could be converted to NSValue, it is similar to getting its encoded string. Generally speaking, a lot of struct could be converted to NSValue (That is because the purpose of NSValue is making value types could be put into containers like NSArray):

let p = NSValue(CGPoint: CGPointMake(3, 3))
// {Some "{CGPoint=dd}"}

let t = NSValue(CGAffineTransform: CGAffineTransformIdentity)
// {Some "{CGAffineTransform=dddddd}"}

Now, we can use these information to prevent type information missing by storing and restoring them at the proper time.

Take an example, now we need to save some numbers of different types in NSUserDefaults, and then read them back to the same types. We could use class cluster to convert these values to NSNumber and save it in the user default. But the subclass of NSNumber is private, once we convert the number to NSNumber and save it, it would be no way to know the original type unless we use some private APIs. Now, objCType comes to rescue. You can just store both the NSNumber object and its type string, you can get back these type information when you read them back from the disk later.