I am using the public method as below to convert the API data type into Int.
public func convertToInt( value : Any) -> Int{
if let v = value as? String {
if let myNumber = NSNumberFormatter().numberFromString(v) {
return myNumber.integerValue
} else {
print ("Cannot convert to Int...")
}
} else if let v = value as? Int {
return v
} else if let v = value as? NSNumber {
return v.integerValue
}
return 0
}
I am using both swift and objective c files in my project. I Want to access this function into objective c file also. If anyone know the solution please help me.
The problem is both that global Swift functions are unavailable to Objective-C, and the protocol Any
cannot be represented in Objective-C.
Therefore, one potential solution is to encapsulate your function in a helper class, and to use AnyObject
for your value
argument – as Int
and String
can be freely bridged to NSNumber
and NSString
respectively, and thus can be treated as objects when Foundation is imported.
@objc final class HelperFunctions : NSObject {
static func convertToInt(value : AnyObject) -> Int {
if let v = value as? String {
if let myNumber = NSNumberFormatter().numberFromString(v) {
return myNumber.integerValue
} else {
print ("Cannot convert to Int...")
}
} else if let v = value as? Int {
print("int")
return v
}
// note that this check is completely redundant as NSNumber is freely bridgable
// to Int – therefore the 'as? Int' check will always get triggered instead
else if let v = value as? NSNumber {
print("nsnum")
return v.integerValue
}
return 0
}
}
Although that being said, this really isn't very Swifty code. NSNumber
is bridgeable to Int
, so you can already convert it directly:
let n = NSNumber(integer: 5)
let i = n as Int // 5
And Int
already has an initialiser that can take a string:
let i = Int("55") // Optional(55)
So, I don't really see what Swift problem this function is solving. Although I do see the Objective-C problem that it's solving, and for that reason I would simply implement this function as a C function in an Objective-C file.
extern NSInteger convertToInt(id _Nonnull value);
inline NSInteger convertToInt(id _Nonnull value) {
if ([value isKindOfClass:[NSString class]]) {
NSNumberFormatter* f = [[NSNumberFormatter alloc] init];
return [f numberFromString:(NSString*)value].integerValue;
} else if ([value isKindOfClass:[NSNumber class]]) {
return ((NSNumber*)value).integerValue;
}
return 0;
}
You can always import this back into Swift if you really want – and then it'll be available as a global function. But I would recommend that you don't import this back to Swift, and instead find a more Swifty solution to your problem.
For example, I would recommend that you implement this in Swift using protocols and extensions. You can define an IntRepresentable
protocol in order to represent types that can be converted to Int
. The advantage of doing this is that you're being explicit about the types that you can convert to Int
, rather than letting it be an implementation detail of your convenience function.
protocol IntRepresentable {
func _asInt() -> Int?
}
Now you can extend the types that your dictionary could contain and make them conform to IntRepresentable
.
extension NSString : IntRepresentable {
func _asInt() -> Int? {return Int(self as String)}
}
extension NSNumber : IntRepresentable {
func _asInt() -> Int? {return self.integerValue}
}
// not really necessary, as your dict will be [Whatever:AnyObject],
// so the NSString extension will be used – here for completeness
extension String : IntRepresentable {
func _asInt() -> Int? {return Int(self)}
}
extension Int : IntRepresentable {
func _asInt() -> Int? {return self}
init?(representable:IntRepresentable) {
guard let i = representable._asInt() else {return nil}
self = i
}
}
Now you can convert your dictionary from [Whatever:AnyObject]
to [Whatever:Int]
by doing the following:
let inputDict = ["foo":"5", "bar":6, "baz":NSNumber(int:5)]
var outputDict = [String:Int]()
for (key, value) in inputDict {
if let value = value as? IntRepresentable {
outputDict[key] = Int(representable: value)
}
}
print(outputDict) // ["baz": 5, "foo": 5, "bar": 6]
You can always stick this in a convenience function if it makes you feel better, although I would still advocate against global functions. You can use a caseless enum in order to avoid polluting the global namespace:
enum DictionaryConversion {
static func toIntValues<Key>(dict:[Key:NSObject]) -> [Key:Int] {
var outputDict = [Key:Int]()
for (key, value) in dict {
if let value = value as? IntRepresentable {
outputDict[key] = Int(representable: value)
}
}
return outputDict
}
}
Or just extend Dictionary
itself:
extension Dictionary {
func convertValuesToInt() -> [Key:Int] {
var outputDict = [Key:Int]()
for (key, value) in self {
if let value = value as? IntRepresentable {
outputDict[key] = Int(representable: value)
}
}
return outputDict
}
}
let outputDict = DictionaryConversion.toIntValues(inputDict)
let outputDict = inputDict.convertValuesToInt()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With