Ambiguous use of 'init' with CFStringTransform and Swift 3 - ios

When trying to build the sample project of BonMot,
let theCFMutableString = NSMutableString(string: myString) as CFMutableString
CFStringTransform(theCFMutableString, UnsafeMutablePointer<CFRange>(nil), kCFStringTransformToUnicodeName, false)
I get this error on the CFStringTransform line
Ambiguous use of 'init'
The Xcode 8 project uses Swift 3

In Swift 2, pointer types conformed to NilLiteralConvertible, allowing a non-optional pointer type to represent a null pointer. Therefore when you did
UnsafeMutablePointer<CFRange>(nil)
the compiler was actually using the init(_ other: COpaquePointer) initialiser of UnsafeMutablePointer, as COpaquePointer is NilLiteralConvertible and can therefore represent a null pointer.
However in Swift 3 (SE-0055), pointer types no longer conform to ExpressibleByNilLiteral. Rather than allowing a non-optional pointer type to represent a null pointer, this is now simply done with optionals, where nil means a null pointer.
Therefore you can just pass nil directly into the range parameter of CFStringTransform, as it expects a UnsafeMutablePointer<CFRange>!:
CFStringTransform(theCFMutableString, nil, kCFStringTransformToUnicodeName, false)

Related

How to cast `Int8?` to `Int?`?

I have a UInt8? variable named seconds that I need to pass to a function accepting Int?.
This leads to Cannot convert value of type UInt8? to expected argument type Int?.
This means I have to cast, and so I tried the obvious:
Int?(seconds)
But this results in: UInt8? is not convertible to Int.
Of course I could do:
(seconds == nil) ? nil : Int(seconds!)
But WTF, does it really have to be so contrived?
Your type is Optional<UInt8>. A UInt8 can always be converted to an Int with the function Int.init. But since it's wrapped in an Optional, you'll have to map that function over the optional, yielding a new value of type Optional<Int>:
seconds.map(Int.init)
Optional.map(_:) and its companion flatMap often make working with optionals a lot easier.

what is the difference between "variable:Type" and "variable as Type" swift

What is the difference between:
let variable:Double = 23
and "as Type"?
let variable = 23 as Double
let variable:Double = 23
Declaring variable in this way is called Type Annotation in which we are telling complier explicitly that variable is type of Double instead of compiler referring to type of assigned value.
let variable = 23 as Double
This is called type casting .As per definition in Swift,
Type casting in Swift is implemented with the is and as operators.
These two operators provide a simple and expressive way to check the
type of a value or cast a value to a different type.
So these are not different in terms of functionality. Using first way, we are adding redundant token for declaring a constant as type inference would detect type automatically by value.
By Second way, we are forcing a constant to have a kind of value which would be useful in case of superClass/Subclass type casting.

How to match the 2d array datatype between swift and objective-c?

I am calling a .mm (objective-c / c++) class method from my swift viewController via linked headers. They are successfully linked. However, I am struggling to pass correct data types that match as parameters.
Here is where I call the function in swift
OpenCVWrapper.thefunc(array1, otherstuff);
...array1 is of type [[Int]]
and here is the definition in objective-c
+(NSString*) thefunc: (int[][2])array1 otherstuff(int)other{
but i get the error
Cannot convert value of type '[[Int]]' to expected argument type 'UnsafeMutablepointer<(Int32)(Int32)>!'
My question is, how can I match the data types so they both handle a basic 2D array of type Int?
UPDATE:
value / structure issues:
structure passed from swift:
structure received in OC:
First of all, you may need to know that C-array and Swift Array are different things. C-array represents a contiguous region of memory and uses the pointer to the first element when passed.
Second, if you want to use imported Objective-C method from Swift, you'd better check the generated header of the method.
(Press the "four square icon" and choose "Generated Interface" while editor is showing the .h file.)
Tested with a small sample project, your method is imported as:
open class func thefunc(_ array1: UnsafeMutablePointer<(Int32, Int32)>!, otherstuff other: Int32) -> String!
(The corresponding type to int in Swift is Int32, not Int.)
So, you may need to pass a mutable pointer to tuple (Int32, Int32), to do that you need to declare a Swift Array of Element type (Int32, Int32) and pass it as an inout argument (using &).
So, you may need to write something like this:
//Assuming all inner Array of `array1` have two elements.
var convertedArray = array1.map {(Int32($0[0]), Int32($0[1]))}
MyClass.thefunc(&convertedArray, otherstuff: someInt32Value)
But the conversion of huge array may take some amount of time, in some cases, which is critical.
You may declare your Swift side array1 as Array of (Int32, Int32) and modify other parts according to this change, and use it as:
//Somewhere in your code...
var array1: [(Int32, Int32)] = []
//...
//And call `thefunc` as:
MyClass.thefunc(&array1, otherstuff: someInt32Value)

Implicitly unwrapped optional assign in Xcode 8

In Xcode 8 release version, i found a strange scene.
Here is the code,
let implicitlyUnwrappedOptionalString: String! = "implicitlyUnwrappedOptionalString"
let foo = implicitlyUnwrappedOptionalString
print(implicitlyUnwrappedOptionalString)
print(foo)
and here is the result:
implicitlyUnwrappedOptionalString
Optional("implicitlyUnwrappedOptionalString")
These above shows that when i assign a implicitly unwrapped optional to a variable without a explicit type, the type will be inferred to an optional type, not the type which it originally is, aka implicitly unwrapped optional.
My Xcode has been updated to 8. Anyone can verify the behavior in Xcode 7.x?
The change is due to the Swift version changing or the Xcode?
This is a consequence of SE-0054 Abolish ImplicitlyUnwrappedOptional type which has been implemented in Swift 3. Extract from that proposal (emphasis added):
However, the appearance of ! at the end of a property or variable declaration's type no longer indicates that the declaration has IUO type; rather, it indicates that (1) the declaration has optional type, and (2) the declaration has an attribute indicating that its value may be implicitly forced. ...
If the expression can be explicitly type checked with a strong optional type, it will be. However, the type checker will fall back to forcing the optional if necessary. The effect of this behavior is that the result of any expression that refers to a value declared as T! will either have type T or type T?. For example, in the following code:
let x: Int! = 5
let y = x
let z = x + 0
… x is declared as an IUO, but because the initializer for y type checks correctly as an optional, y will be bound as type Int?. However, the initializer for z does not type check with x declared as an optional (there's no overload of + that takes an optional), so the compiler forces the optional and type checks the initializer as Int.
In your case, the assignment
let foo = implicitlyUnwrappedOptionalString
makes foo a strong optional, as in the example let y = x
from the proposal.
You could make foo an IUO by adding an explicit type annotation
let foo: String! = implicitlyUnwrappedOptionalString
but generally you should try to get rid from IUOs in your code,
as stated in the same proposal:
Except for a few specific scenarios, optionals are always the safer bet, and we’d like to encourage people to use them instead of IUOs.

Why NSNumber *a = 0 do not display error

I know the correct way to initial a NSNumber is NSNumber *a = #1;
and when I declare NSNumber *a = 1;, I will got the error
Implicit conversion of int to nsnumber is disallowed with arc
But I don't know why when I declare NSNumber *a = 0; there is no error
In my case, I have write some function in NSNumber category
and then
If the value of NSNumber is #0, I can use the function in category normally
If the value of NSNumber is 0, I can use the function in category, no error happened but when run app, this function will never call
The value 0 is synonymous with nil or NULL, which are valid values for a pointer.
It's a bit of compatibility with C that leads to this inconsistent behavior.
History
In the C language, there is no special symbol to represent an uninitialized pointer. Instead, the value 0 (zero) was chosen to represent such a pointer. To make code more understandable, a preprocessor macro was introduced to represent this value: NULL. Because it is a macro, the C compiler itself never sees the symbol; it only sees a 0 (zero).
This means that 0 (zero) is a special value when assigned to pointers. Even though it is an integer, the compiler accepts the assignment without complaining of a type conversion, implicit or otherwise.
To keep compatibility with C, Objective-C allows assigning a literal 0 to any pointer. It is treated by the compiler as identical to assigning nil.
0 is a null pointer constant. A null pointer constant can be assigned to any pointer variable and sets it to NULL or nil. This was the case in C for the last 45 years at least and is also the case in Objective-C. Same as NSNumber* a = nil.
You can consider 0 as nil or null that can be assign to object but 1 is integer and can't allow to object or non integer.
Objective-C silently ignores method calls on object pointers with value 0 (i.e. nil). That's why nothing happens when you call a method of your NSNumber category pointer which you assigned the value 0.
A nil value is the safest way to initialize an object pointer if you don’t have another value to use, because it’s perfectly acceptable in Objective-C to send a message to nil. If you do send a message to nil, obviously nothing happens.
Note: If you expect a return value from a message sent to nil, the return value will be nil for object return types, 0 for numeric types, and NO for BOOL types. Returned structures have all members initialized to zero.
In the last Apple Doc Working with nil

Resources