Extension for Generic Type 'Unsafemutablepointer<Uint8>'

Extension for Generic Type `UnsafeMutablePointer UInt8 `


Swift 3.1 Update

As of Swift 3.1 (available with Xcode 8.3 beta), concrete same-type requirements are now supported. You can now just say:

extension UnsafeMutablePointer where Pointee == UInt8 {
func asArray(withLength length: Int) -> [Int] {
return UnsafeBufferPointer(start: self, count: length).map(Int.init)
}
}

Pre Swift 3.1

You can do this – although it's not particularly nice. You'll have to create a new protocol in order to 'tag' the UInt8 type, and then constrain your extension to that protocol. It also doesn't allow you to easily specify that the Int(...) initialiser can take a _UInt8Type input – you have to implement a hacky 'shadow' method to do that.

protocol _UInt8Type {
func _asInt() -> Int
}
extension UInt8 : _UInt8Type {
func _asInt() -> Int {
return Int(self)
}
}

// Change 'Pointee' to 'Memory' for Swift 2
extension UnsafeMutablePointer where Pointee : _UInt8Type {
func asArray(withLength length:Int) -> [Int] {
return UnsafeBufferPointer(start: self, count: length).map{$0._asInt()}
}
}

All in all I'd prefer to keep this fully generic and go with @AMomchilov's solution. I'm only really adding this for the sake of completion.

Although it's worth noting that having concrete same-type requirements for extensions (extension Type where Generic == SomeType) has been proposed as a part of the Swift Generics Manifesto – so hopefully this will be possible in a future version of Swift.

Why can’t I initialize a Swift UnsafeMutablePointer UInt32 with (&myUInt32) or (&[myUInt32])

I am a little bit speculating here, but the reason seems to be that
UnsafeMutablePointer<T> has generic initializer

init<U>(_ from: UnsafeMutablePointer<U>)

where <U> is unrelated to <T>. It seems that the compiler cannot
infer the type <U> in

legIntPtr = UnsafeMutablePointer(&legInt) //Compile error!

Just to confirm this conjecture, we can define a custom extension

extension UnsafeMutablePointer {
init(_ from : UnsafeMutablePointer<T>) {
// Swift 2: init(_ from : UnsafeMutablePointer<Memory>) {
self = from
}
}

which initializes the pointer from another pointer of the same type.
Now all your code compiles and works as expected.

What you can do is use withUnsafeMutablePointer():

legIntPtr = withUnsafeMutablePointer(&legInt, { $0 })

But keep in mind that the compiler does not track this pointer to
the object as a reference and might destroy the object. That's why
these pointers are "unsafe". You should normally use the pointer
only inside the withUnsafeMutablePointer() closure.

Cannot assign value of type 'UnsafeMutableRawPointer!' to type 'UIView'

Bridging between raw pointers and managed object pointers is done
in Swift using the Unmanaged type. In your case the equivalent
code would be

let rawPointer = SmartPlayerSDK.smartPlayerCreatePlayView(0, y: 0, width: 10, height: 10)
let view = Unmanaged<UIView>.fromOpaque(rawPointer).takeUnretainedValue()

If smartPlayerCreatePlayView() returns a (+1) retained object
reference (as the "Create" in the method name indicates) then it
should be

let view = Unmanaged<UIView>.fromOpaque(rawPointer).takeRetainedValue()

to balance that, otherwise you have a memory leak.

For more bridging conversions, helper functions, and links
to the documentation, see How to cast self to UnsafeMutablePointer<Void> type in swift.

Swift3: type inference inside generic extension

If you take a look at the flatMap(_:) signature,

extension Sequence {
// ...
public func flatMap<SegmentOfResult : Sequence>(_ transform: (Self.Iterator.Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Iterator.Element]
// ...
}

you'll see that it returns a [SegmentOfResult.Iterator.Element], where SegmentOfResult is the type that is returned from the function you pass it. This isn't necessarily the same type as Element (as your extension is for all arrays), which is why your code fails to compile.

In order to be working with arrays where the elements are sequences, you'll want to constrain your extension so that Element : Sequence.

Also, as the function you're passing to flatMap(_:) is an identity transform (it just returns the element it receives as input), you'll want to change the return type to [Element.Iterator.Element] (an array of the inner element).

extension Array where Element : Sequence {
func flat() -> [Element.Iterator.Element] {
return self.flatMap { $0 }
}
}

Although that being said, I see no reason why this shouldn't be an extension of Sequence:

// An extension for a sequence of sequences
extension Sequence where Iterator.Element : Sequence {

// returns an array of the inner element type (an array of the element of the element)
func flat() -> [Iterator.Element.Iterator.Element] {
return self.flatMap { $0 }
}
}

(However, I don't really see the need to create an extension for this in the first place – array.flatMap{$0} isn't exactly lengthy!)

Can one extend a Swift Dictionary by a struct?

Try my version

1. Code (with struct)

import Foundation

struct Foo: Hashable {
let bar: String

static let predefinedFoo = Foo(bar: "something")

var hashValue: Int { return bar.hashValue }

static func ==(lhs: Foo, rhs: Foo) -> Bool {
return lhs.hashValue == rhs.hashValue
}
}

struct Baz {
let isSpecial: Bool
init(isSpecial: Bool) {
self.isSpecial = isSpecial
}
}

extension Dictionary where Key: Any, Value: Any {
var hasSpecialPredefined: Bool {
for key in keys {
if let _key = key as? Foo, _key == .predefinedFoo, let value = self[key] as? Baz {
return value.isSpecial
}
}
return false
}
}

let foo1 = Foo(bar: "ddddd")
var test: [Foo: Baz] = [foo1: Baz(isSpecial: true)]
print("\(test), hasSpecialPredefined: \(test.hasSpecialPredefined)")
test[.predefinedFoo] = Baz(isSpecial: true)
print("\(test), hasSpecialPredefined: \(test.hasSpecialPredefined)")

Result

Sample Image

2. Code (with classes)

import Foundation

class Foo: Hashable {
let bar: String

init(bar:String) {
self.bar = bar
}

static let predefinedFoo = Foo(bar: "something")

var hashValue: Int { return bar.hashValue }

public static func ==(lhs: Foo, rhs: Foo) -> Bool {
return lhs.hashValue == rhs.hashValue
}
}

class Baz: AnyObject {
let isSpecial: Bool
init(isSpecial: Bool) {
self.isSpecial = isSpecial
}
}

extension Dictionary where Key: Foo, Value: Baz {
var hasSpecialPredefined: Bool {
for key in keys {
if key == .predefinedFoo {
return self[key]?.isSpecial ?? false
}
}
return false
}
}

let foo1 = Foo(bar: "ddddd")
var test: [Foo: Baz] = [foo1: Baz(isSpecial: true)]
print ("hasSpecialPredefined: \(test.hasSpecialPredefined)")
test[.predefinedFoo] = Baz(isSpecial: true)
print ("hasSpecialPredefined: \(test.hasSpecialPredefined)")

Incrementing a variable of type UInt8 inside of a for loop

The problem there it is in the last loop when you try to increment it overflows your UInt8.max 255.

You have many different options to accomplish what you want:

To keep the loop you will need start your iteration from the second element in your array and increment your var at the same time you assign it to your buff to prevent overflow:

for var i = 1; i < 256; ++i {
buff[i] = ++index
}

or use for in loop to iterate your array indices:

for i in buff.indices {
buff[i] = UInt8(i)
}

Or you can simply initialize your array with a range:

let buff = [UInt8](0...255)


Related Topics



Leave a reply



Submit