Convert UnsafeMutablePointer<UInt> to UInt in Swift - swift

I got from a function Swift result in type UnsafeMutablePointer<UInt>
Can I cast it to UInt?

Just use the memory property to access the underlying data.
let ptr: UnsafeMutablePointer<UInt> = funcReturningMutablePtr()
let theValue: UInt = ptr.memory
The type annotations are for clarity, but are not necessary.

Related

Convert UnsafeMutableRawPointer to UInt64

I have an instance of UnsafeMutableRawPointer and want to retrieve intenger representation of it. I'm trying to use the following code:
let pointer : UnsafeMutableRawPointer? = address(of: self)
let intRepresentation : UInt64 = UInt64(bitPattern: pointer)
But Swift compiler throws error: "Cannot convert value of type 'UnsafeMutableRawPointer?' to expected argument type 'Int64'"
Constructor declared as public init(bitPattern pointer: UnsafeMutableRawPointer?) is Swift.Math.Integers.UInt
Also it has public init(bitPattern x: Int64) in the same file
How I can make this code work or convert UnsafeMutableRawPointer to integer in any other (but not too ridiculous, like string parsing) way?
(U)Int has the size of a pointer on all platforms (32 bit or 64 bit), so you can always convert between Unsafe(Mutable)(Raw)Pointer and Int or UInt:
let pointer: UnsafeRawPointer? = ...
let intRepresentation = UInt(bitPattern: pointer)
let ptrRepresentation = UnsafeRawPointer(bitPattern: intRepresentation)
assert(ptrRepresentation == pointer)
Your code
let intRepresentation = UInt64(bitPattern: pointer)
does not compile because UInt64 does not have an initializer taking a pointer argument, and that is because pointers can be 32 bit or 64 bit. (And even on a 64-bit platform, UInt and UInt64 are distinct types.)
If you need an UInt64 then
let intRepresentation = UInt64(bitPattern:Int64(Int(bitPattern: pointer)))
does the trick.

How to convert Int8 to Character?

I need to convert Int8 to Character. How can I do it?
I tried use UnicodeScalar
var result += Character(UnicodeScalar(data[i]))
... but got this error:
Cannot invoke initializer for type 'UnicodeScalar' with an argument
list of type (Int8)
Unicode.Scalar can be initalized just with paramaters of certain types which you can find in docs.
I would suggest you using init(_:) which takes UInt8 which tells that given number is positive (this is required for creating UnicodeScalar). So, you can try to cast your Int8 to UInt8 and then your initializer takes parameter of correct type
let int: Int8 = data[i]
if let uint = UInt8(exactly: int) {
let char = Character(UnicodeScalar(uint))
}
Maybe you need just convert whole data to a string:
var result = String(data: data, encoding: .ascii)

"Type of expression is ambiguous without more context" when creating UInt16 array from Bluetooth characteristic

I am using Xcode 9.2 and I don't understand the reason behind the error
Type of expression is ambiguous without more context
I am getting some input when trying to create and wordArray as showed below. If I define it as UInt8 array it does work but not if I do as Uint16 since I get the error.
The original data, Characteristic.value comes from a BLE characteristic
let characteristicData = Characteristic.value
let byteArray = [UInt8](characteristicData!)
print("\(Characteristic.uuid) value as byte is->",byteArray)
let wordArray = [UInt16](characteristicData!)//Type of expression is ambiguous without more context
print("\(Characteristic.uuid) value as word is->",wordArray)
Why does this happen and how I can fix it?
characteristicData has the type Data and that conforms to the
(RandomAccess)Collection protocol with UInt8 as element type, that's why you can
initialize an [UInt8] array from it:
let byteArray = [UInt8](characteristicData)
You could equivalently write
let byteArray = Array(characteristicData)
To interpret the data as an array of a different type, use
the generic
func withUnsafeBytes<ResultType, ContentType>(_ body: (UnsafePointer<ContentType>) throws -> ResultType) rethrows -> ResultType
method:
let wordArray = characteristicData.withUnsafeBytes {
[UInt16](UnsafeBufferPointer(start: $0, count: characteristicData.count/2))
}
Here the ContentType is inferred automatically as UInt16.

Swift Dictionary confusion

Say I have
var dict = parseJSON(getJSON(url)) // This results in an NSDictionary
Why is
let a = dict["list"]![1]! as NSDictionary
let b = a["temp"]!["min"]! as Float
allowed, and this:
let b = dict["list"]![1]!["temp"]!["min"]! as Float
results in an error:
Type 'String' does not conform to protocol 'NSCopying'
Please explain why this happens, note that I'm new to Swift and have no experience.
dict["list"]![1]! returns an object that is not known yet (AnyObject) and without the proper cast the compiler cannot know that the returned object is a dictionary
In your first example you properly cast the returned value to a dictionary and only then you can extract the value you expect.
To amend the answer from #giorashc: use explicit casting like
let b = (dict["list"]![1]! as NSDictionary)["temp"]!["min"]! as Float
But splitting it is better readable in those cases.

Swift: Convert Int16 to Int32 (or NSInteger)

I'm really stuck! I'm not an expert at ObjC, and now I am trying to use Swift. I thought it would be much simpler, but it wasn't. I remember Craig said that they call Swift “Objective-C without C”, but there are too many C types in OS X's foundation. Documents said that many ObjC types will automatically convert, possibly bidirectionally, to Swift types. I'm curious: how about C types?
Here's where I'm stuck:
//array1:[String?], event.KeyCode.value:Int16
let s = array1[event.keyCode.value]; //return Int16 is not convertible to Int
I tried some things in ObjC:
let index = (Int) event.keyCode.value; //Error
or
let index = (Int32) event.keyCode.value; //Error again, Swift seems doesn't support this syntax
What is the proper way to convert Int16 to Int?
To convert a number from one type to another, you have to create a new instance, passing the source value as parameter - for example:
let int16: Int16 = 20
let int: Int = Int(int16)
let int32: Int32 = Int32(int16)
I used explicit types for variable declarations, to make the concept clear - but in all the above cases the type can be inferred:
let int16: Int16 = 20
let int = Int(int16)
let int32 = Int32(int16)
This is not how this type of casting works in Swift. Instead, use:
let a : Int16 = 1
let b : Int = Int(a)
So, you basically instantiate one variable on base of the other.
In my case "I was trying to convert core data Int16 to Int" explicit casting didn't worked. I did this way
let quantity_string:String = String(format:"%d",yourInt16value)
let quantity:Int = Int(quantity_string)