How to box int (enum) to object in swift? - ios

I need to cast an int to an object, in Objective-C I could do the following
[row.cellConfig setObject:#(UITextFieldViewModeAlways) forKey:#"textField.rightViewMode"];
What would be the Swift equivalent?

The Swift equivalent of UITextFieldViewModeAlways is
UITextFieldViewMode.Always, which is an enumeration value:
enum UITextFieldViewMode : Int {
case Never
case WhileEditing
case UnlessEditing
case Always
}
You get its underlying integer value with .rawValue.
Integers are automatically "bridged" to NSNumber when passed
to functions taking Objective-C parameters (and Swift strings
bridged to NSString).
So this should work:
row.cellConfig.setObject(UITextFieldViewMode.Always.rawValue,
forKey: "textField.rightViewMode")
For more information, see Using Swift with Cocoa and Objective-C.

Use
row.cellConfig.setObject(NSNumber(UITextFieldViewModeAlways), forKey:"textField.rightViewMode")

You need to create a NSNumber object for that int.
NSNumber *intObj = [NSNumber numberWithInt:num];

Related

Not able to find equivalent of respondsToSelector:#selector(charValue) in Swift 3

I have done lot of google to find the equivalent of respondsToSelector, still i could find any best solution. kindly suggest me for Any object in Swift3 or 4.
Objetive-C
[(id)object respondsToSelector:#selector(charValue)]
In Swift we have .method for AnyObject data type but for Any data type
you should first type cast then use
(object as? Type)?.charValue()
if your object is not of a type then it nil and never call the charValue()
Reason: You can not write respondsToSelector for the swift-based function. There are 2 reasons.
1) In Objective-c, we do have charValue property in NSNumber class along with initWithChar. Whereas in swift we do not have any such properties in NSNumber class.
#property (readonly) char charValue;
- (NSNumber *)initWithChar:(char)value NS_DESIGNATED_INITIALIZER;
2) respondsToSelector only accepts Objective-C functions in argument.
Try with writing responds(to: #selector on NSNumber and you will found that it only accepts objective-c function and we don't have any such method in Swift NSNumber class.
let numb: NSNumber?
numb?.responds(to: #selector(#objc method))
Rather, You can use the swift string conversion of NSNumber, as:
let number: NSNumber?
let numberString = number?.stringValue ?? ""
// Added default variable "" in case of string conversion becomes nil

How to convert RealmOptional to Int or Float in Swift?

I want to convert a type defined as RealmOptional to either Int or Float, depending on the type assigned to the generic. However, when I tried distributing them using switch statement, it turned out that not RealmOptional<Int>() but RealmOptional<Float>() were classified to Int cases. For example,
switch value { // value is of type AnyObject?
case is String:
cell.valueLabel.text = value as? String
case is Int:
// RealmOptional<Float> are executed here
let v = value as! Int
cell.valueLabel.text = String(v) // Float is now treated as Int
case is Double:
print("double") // not printed at all
cell.valueLabel.text = String(value!)
default:
break
}
Why does RealmOptional<Float>() behave as Int here? And how can I set the text to the value correctly?
Lets assume your RealmOptional<Float>() variable is named myFloat. Then, use the getter for the RealmOptional:s (see this git entry for Realm) underlying value, .value, rather then checking the RealmOptional itself:
var value = myFloat.value // value variable now of type Float
Below follows and explanation of why the AnyObject? switches doesn't behave as you expect:
From Apples Language Guide - Type Casting:
Type Casting for Any and AnyObject
Swift provides two special type aliases for working with non-specific
types:
AnyObject can represent an instance of any class type.
Any can represent an instance of any type at all, including function types.
Hence, the AnyObject type can can hold instances of any class type, but the fundamental numeric types (Int, Double etc) in Swift are not of class type, but of structure type.
In the switch in your example, the AnyObject instance is not inferred but cast to the first possible successful downcast, which will be whatever case you put top-most that is of a numeric type. Hence, if you change the ordering of your case:s in the switch, the casting will change.
let value: AnyObject? = 30.0
// try change the order
switch value {
case is String: print("string");
case is Float: print("float"); // hits `Float` downcast first -> prints float
case is Int: print("int");
default: print("other")
}
Now, you could, however, cast your AnyObject to an NSNumber (class instance), and continue from there. From Working with Cocoa Data Types documentation:
Instances of the Swift numeric structure types, such as Int, UInt,
Float, Double, and Bool, cannot be represented by the AnyObject type,
because AnyObject only represents instances of a class type. However,
when bridging to Foundation is enabled, Swift numeric values can be
assigned to constants and variables of AnyObject type as bridged
instances of the NSNumber class.
Note however that NSNumber is fundamentally different from the Swift numeric types (Int, Double etc) in that the former hold any kind of number, and allows us to cast this number to different type of numeric types. However, we cannot easily infer which type a specific NSNumber instance should be cast to, but we could implement our own (not so pretty) specification as how to infer different NSNumber to different swift fundamental numeric types.
However, before proceeding with NSNumber hacking:
From above, the core problem is that your value property is of type AnyObject?. Could you please post the code that lead to value being of type AnyObject?. Possibly the casting to Int, Float and so on if not necessary if using the getter of the RealmOptional (hence no need to casting RealmOptional<T>() to AnyObject??).
I found that this is not related to Realm; it is related to Swift. In Swift when you pass a floating object in switch, it is not only caught up in is Float but also in is Int, because the floating number can be convertible to Int as well.
For example, the code below does not go through is Float condition, because it is caught up in is Int:
let value: AnyObject? = 30.0
switch value {
case is String: print("string");
case is Int: print("int");
case is Float: print("float");
default: print("other")
}
That is why RealmOptional<Float>() is caught up in is Int.
I still don't know how I can cope with the issue here, because an object of type Int is caught up in is Float and an object of type Float is caught up in is Int. Maybe someone can chime in...

In Swift 2, what changed in NSDictionary?

In Swift 2, what exactly changed in the NSDictionary(objects, forKeys) (Objective-C: dictionaryWithObjects:forKeys:) creation?
Apple's prerelease documentation was particularly useless, given that there only is Obj-C code. Even though there's a slight but obvious change in the provided snippet, I don't speak obj-c and haven't made sense out of the change so far.
Here's some code for you guys:
videoDataOutput.videoSettings = NSDictionary(objects: NSNumber(kCVPixelFormatType_32BGRA), forKeys: (kCVPixelBufferPixelFormatTypeKey))
//Working old Swift code; missing argument for parameter 'count' in call on Swift 2
+ (instancetype)dictionaryWithObjects:(NSArray *)objects
forKeys:(NSArray *)keys
//Old Obj-C code
+ (instancetype nonnull)dictionaryWithObjects:(NSArray<ObjectType> * nonnull)objects
forKeys:(NSArray<id<NSCopying>> * nonnull)keys
//New Obj-C code
I've read elsewhere that nonnull is supposed to facilitate compatibility with Swift, but what about <ObjectType>? And what's id?
#Update
Fixed swift code from NSDictionary(objectsAndKeys: ) to NSDictionary(objects: , forKeys:)
You are not using +dictionaryWithObjects:forKeys:, you are using +dictionaryWithObjectsAndKeys:. These are two different methods. +dictionaryWithObjectsAndKeys: is not supported by swift.
Using +dictionaryWithObjects:forKeys: would look like this.
videoDataOutput.videoSettings = NSDictionary(objects: [NSNumber(integer: kCVPixelFormatType_32BGRA)], forKeys: [kCVPixelBufferPixelFormatTypeKey])
NOTE: I also needed to change NSNumber(kCVPixelFormatType_32BGRA) to NSNumber(integer: kCVPixelFormatType_32BGRA)
Because you only have one entry in the dictionary, you can use +dictionaryWithObject:forKey:.
videoDataOutput.videoSettings = NSDictionary(object: kCVPixelFormatType_32BGRA as NSNumber, forKey: kCVPixelBufferPixelFormatTypeKey as NSString)
NOTE 1: I used kCVPixelFormatType_32BGRA as NSNumber instead of NSNumber(integer: kCVPixelFormatType_32BGRA)
NOTE 2: I had to use kCVPixelBufferPixelFormatTypeKey as NSString instead of just kCVPixelBufferPixelFormatTypeKey.
I think the simplest way to do this is to use swift's Dictionary literal.
videoDataOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as NSString: kCVPixelFormatType_32BGRA]
I got this to work in XCode 7 Swift 2 using simply
output.videoSettings = [ kCVPixelBufferPixelFormatTypeKey: Int(kCVPixelFormatType_32BGRA) ]
Check out this project for some current code https://github.com/gibachan/OpenCVSample/
There is no real change for the obj-c programmer. It is mostly for the compiler and as you said for cross-compatibility to swift:
Instead of (NSArray *) you now have (NSArray<ObjectType> * nonnull) which means a) the array may not nonnull (not nil) and b) its contents / values must be of type ObjectType.
Instead of (NSArray *) you have (NSArray<id<NSCopying>> * nonnull) which means a) as above and b) its contents must adapt the NSCopying protocol.
Regarding the expected count: the objectsAndKeys is no longer present (docs), you have to use some other function. or just a literal...
Final note regarding id and ObjectType: id refers to any object, you can sage every view or arra or anything as id - it has itself no type information. ObjectType I think refers to generics, it means that you write ObjectType everywhere you want to use a specific type, you dont know the type yet, but it will be the same at every place where ObjectType is written.

Objective-C - Using Enum identifiers as string [duplicate]

This question already has answers here:
Convert Objective-C enum constants to string names
(2 answers)
Closed 8 years ago.
The enumeration below is used in several places in a BMI tool :
typedef NS_ENUM (NSInteger, BMIStatus) {
Malnutrition = 1,
Anorexia = 2,
Thinness = 3,
Normal = 4,
Overweight = 5,
Obesity = 6,
Morbid = 7
};
Is there a trick to use "Malnutrition" as a string ? Considering I have an image named "Malnutrition.png" that I want to load with a classical ImageNamed, and without using an intermediary array storing [1] => #"Malnutrition" for example.
My idea would be to use a kind of [UIImage imageNamed:[NSString stringWithFormat:#"%e", Malnutrition]] where %e leads to the enum identifier instead of the associated value.
Thanks.
Unfortunately this is just not possible using Objective-C. However, it is in Swift if you can use Swift instead.
This is historically handled in Apple's code with NSString constants. For example:
UIKIT_EXTERN NSString *const NSFontAttributeName NS_AVAILABLE_IOS(6_0);
If you need to map between the int value and the NSString value, you will need to write a mapping function.
Also, do make sure to prefix your enums and string constants!
If you want a string for debugging purposes, add a method - (NSString*) stringFromBMIStatus, with a switch statement returning various strings, and a default printing the numeric value for unexpected input.
If you want a string that gives you the name of an NSImage for each enum value, add a method - (NSString*) imageNameFromBMIStatus, probably returning nil for unexpected input.

ios convert int to NSObject

in my function I have a parameter of NSObject* type, to allow to pass NSString, NSDate, etc.. and intenally do something...
I need to pass also a value of type int..
how can I do this?
thanks
You can use the NSNumber class (http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/Reference/Reference.html), and initialize it with the numberWithInt method.
#Itamar's answer is sufficient, but I'm just simplifying it.
Try this,
NSNumber *your_object = [NSNumber numberWithInt:int_value];
So now int_value is converted into object.

Resources