How to cast [Int8] to [UInt8] in Swift
I broadly agree with the other answers that you should just stick with map
, however, if your array were truly huge, and it really was painful to create a whole second buffer just for converting to the same bit pattern, you could do it like this:
// first, change your process logic to be generic on any kind of container
func process<C: CollectionType where C.Generator.Element == UInt8>(chars: C) {
// just to prove it's working...
print(String(chars.map { UnicodeScalar($0) }))
}
// sample input
let a: [Int8] = [104, 101, 108, 108, 111] // ascii "Hello"
// access the underlying raw buffer as a pointer
a.withUnsafeBufferPointer { buf -> Void in
process(
UnsafeBufferPointer(
// cast the underlying pointer to the type you want
start: UnsafePointer(buf.baseAddress),
count: buf.count))
}
// this prints [h, e, l, l, o]
Note withUnsafeBufferPointer
means what it says. It’s unsafe and you can corrupt memory if you get this wrong (be especially careful with the count). It works based on your external knowledge that, for example, if any of the integers are negative then your code doesn't mind them becoming corrupt unsigned integers. You might know that, but the Swift type system can't, so it won't allow it without resort to the unsafe types.
That said, the above code is correct and within the rules and these techniques are justifiable if you need the performance edge. You almost certainly won’t unless you’re dealing with gigantic amounts of data or writing a library that you will call a gazillion times.
It’s also worth noting that there are circumstances where an array is not actually backed by a contiguous buffer (for example if it were cast from an NSArray
) in which case calling .withUnsafeBufferPointer
will first copy all the elements into a contiguous array. Also, Swift arrays are growable so this copy of underlying elements happens often as the array grows. If performance is absolutely critical, you could consider allocating your own memory using UnsafeMutablePointer
and using it fixed-size style using UnsafeBufferPointer
.
For a humorous but definitely not within the rules example that you shouldn’t actually use, this will also work:
process(unsafeBitCast(a, [UInt8].self))
It's also worth noting that these solutions are not the same as a.map { UInt8($0) }
since the latter will trap at runtime if you pass it a negative integer. If this is a possibility you may need to filter them first.
Swift converting signed array of Int [int8] to unsigned array of Int [UInt8]
If your intention is to convert signed 8-bit integers to
unsigned ones with the same bit representation (e.g. -1 -> 255
):
let intArray: [Int8] = [0, 1, 2, 127, -1, -2, -128]
let uintArray = intArray.map { UInt8(bitPattern: $0) }
print(uintArray)
// [0, 1, 2, 127, 255, 254, 128]
How to cast `Int8?` to `Int?`?
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.
Int to UInt (and vice versa) bit casting in Swift
You can do:
let unsigned = UInt8(bitPattern: Int8(-1)) // -> 255
let signed = Int8(bitPattern: UInt8(0xff)) // -> -1
Many similar initializers exist:
extension Int8 {
init(_ v: UInt8)
init(_ v: UInt16)
init(truncatingBitPattern: UInt16)
init(_ v: Int16)
init(truncatingBitPattern: Int16)
init(_ v: UInt32)
init(truncatingBitPattern: UInt32)
init(_ v: Int32)
init(truncatingBitPattern: Int32)
init(_ v: UInt64)
init(truncatingBitPattern: UInt64)
init(_ v: Int64)
init(truncatingBitPattern: Int64)
init(_ v: UInt)
init(truncatingBitPattern: UInt)
init(_ v: Int)
init(truncatingBitPattern: Int)
init(bitPattern: UInt8)
}
swift 3 ios : convert UInt8 Array to int8
You can convert a [UInt8] to a [Int8] by using this:
for el in uint8Array {
uint8Array.append(UInt8(bitPattern: el))
}
Convert Int to Array of UInt8 in swift
You could do it this way:
let x: Int = 2019
let length: Int = 2 * MemoryLayout<UInt8>.size //You could specify the desired length
let a = withUnsafeBytes(of: x) { bytes in
Array(bytes.prefix(length))
}
let result = Array(a.reversed()) //[7, 227]
Or more generally, we could use a modified version of this snippet:
func bytes<U: FixedWidthInteger,V: FixedWidthInteger>(
of value : U,
to type : V.Type,
droppingZeros: Bool
) -> [V]{
let sizeInput = MemoryLayout<U>.size
let sizeOutput = MemoryLayout<V>.size
precondition(sizeInput >= sizeOutput, "The input memory size should be greater than the output memory size")
var value = value
let a = withUnsafePointer(to: &value, {
$0.withMemoryRebound(
to: V.self,
capacity: sizeInput,
{
Array(UnsafeBufferPointer(start: $0, count: sizeInput/sizeOutput))
})
})
let lastNonZeroIndex =
(droppingZeros ? a.lastIndex { $0 != 0 } : a.indices.last) ?? a.startIndex
return Array(a[...lastNonZeroIndex].reversed())
}
let x: Int = 2019
bytes(of: x, to: UInt8.self, droppingZeros: true) // [7, 227]
bytes(of: x, to: UInt8.self, droppingZeros: false) // [0, 0, 0, 0, 0, 0, 7, 227]
Related Topics
How to Move Application's Window Between Virtual Desktops in Os X
Hmac Sha512 Using Commoncrypto in Swift 3.1
Get the Type of Anyobject Dynamically in Swift
How to Set Priority on Constraints in Swift
Sf Symbols Hierarchical, Palette, and Multicolor Rendering Mode Colors
Xcode Build Perfect Failure -- Copenssl Not Found
Differences Between Filtering Realm with Nspredicate and Block
Swiftui Onmovecommand Actions Aren't Executed
Is It Safe to Force Unwrap an Optional After Checking It Is Not Nil
Swiftui Button Interact with Map
Solving System of Equations in Swift
How to Perform Face Detection in Swift
Changing Tab Bar Color (Swift)
Troubles Using Cgpathcontainspoint Swift
How to Get Part of a String in Swift