Swift UnsafeMutablePointer & UnsafeMutablePointerUnsafePointerSomeType
I've managed to suss this out... I wasn't allocating the memory properly for rects
and count
What I had was:
var rects: UnsafeMutablePointer<UnsafePointer<NSRect>> = nil
var count: UnsafeMutablePointer<Int> = nil
What ultimately fixed the issue was:
var rects: UnsafeMutablePointer<UnsafePointer<NSRect>> = UnsafeMutablePointer<UnsafePointer<NSRect>>.alloc(1)
var count: UnsafeMutablePointer<Int> = UnsafeMutablePointer<Int>.alloc(1)
Hope this helps someone else :)
edit If anyone is interested, here's what the swift code for the above turned out to be:
override func drawSelectionInRect(dirtyRect: NSRect) {
var primaryColor = NSColor.alternateSelectedControlColor().colorWithAlphaComponent(0.5)
var secondarySelectedControlColor = NSColor.secondarySelectedControlColor().colorWithAlphaComponent(0.5)
switch (self.selectionHighlightStyle){
case .Regular:
if (self.selected){
if self.emphasized{
primaryColor.set()
}else{
secondarySelectedControlColor.set()
}
let bounds = self.bounds
var rects: UnsafeMutablePointer<UnsafePointer<NSRect>> = UnsafeMutablePointer<UnsafePointer<NSRect>>.alloc(1)
var count: UnsafeMutablePointer<Int> = UnsafeMutablePointer<Int>.alloc(1)
self.getRectsBeingDrawn(rects, count: count)
let rectArrayPtr = UnsafeMutableBufferPointer(start: rects, count: count.memory)
var base = rectArrayPtr.baseAddress
for var i = 0; i < count.memory; i++ {
var currentRect = base.memory
let rect = NSIntersectionRect(bounds, currentRect.memory)
NSRectFillUsingOperation(rect, .CompositeSourceOver)
base.successor()
}
}
default:
super.drawSelectionInRect(dirtyRect)
}
}
edit
As per a further comment, the same has been achieved here with a less verbose approach (thanks to Paul Patterson below):
http://stackoverflow.com/questions/32536855/using-getrectsbeingdrawn-with-swift
Assigning UnsafeMutablePointer value to UnsafePointer without unsafeBitCast
You can create an UnsafePointer<T>
from an UnsafeMutablePtr<T>
simply with
let ptr = UnsafePointer(mptr)
using the
/// Creates an immutable typed pointer referencing the same memory as the
/// given mutable pointer.
///
/// - Parameter other: The pointer to convert.
public init(_ other: UnsafeMutablePointer<Pointee>)
initializer of UnsafePointer
. In your case that would for example be
p.left = UnsafePointer(leftVal)
Cast C struct double pointer to a Swift struct unsafe pointer
Let's think about that in terms of what's happening in C. When I do a cast of pointers in C, the data that represents the pointer type will now be treated as a pointer of a different type. The value of the pointer doesn't change, just how you treat it.
Swift doesn't like to do this kind of thing and doesn't encourage you to do it because while cheap, it's a fundamentally unsafe thing to do and can lead to corrupting data, jumping into space, bus errors, etc.
That doesn't mean that swift doesn't have the ability to do this. The link that you point to uses withUnsafePointerTo
which tries to limit the scope of the use of the pointer. In your case, you probably want to look at unsafeBitCast
(documentation here) which mimics the C pointer cast (it's not strictly the same as C casting in general, but for pointers it is).
let a:UnsafeMutablePointer<SomeType> = fetchASomeTypePointer()
let b = unsafeBitCast(a, to: UnsafeMutablePointer<SomeOtherType>.self)
This makes the data representing the pointer to SomeType
now become a pointer to SomeOtherType
.
Like I said before, this is a dangerous thing to do especially if you don't fully understand what you're doing.
Extension for Generic Type `UnsafeMutablePointerUInt8`
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.
Using getRectsBeingDrawn: with Swift
This is what you want:
var rects = UnsafePointer<NSRect>()
var count = Int()
getRectsBeingDrawn(&rects, count: &count)
for i in 0 ..< count {
let rect = rects[i]
// do things with 'rect' here
}
You make two variables rects
and count
, and pass references to both of them, so they get filled with information.
After calling getRectsBeingDrawn
, rects
points to count
rectangles, which you can access with a subscript, like an array.
Indirect initialization of memory via UnsafeMutablePointer types
You can achieve what you are looking for via withUnsafeMutablePointer(to:_:) like so:
let foo = Foo()
withUnsafeMutablePointer(to: &foo.person) { (ptr) -> Void in
initializeWithBob(ptr)
}
print(foo.person!.name) // outputs Bob
However, I wouldn't recommend this approach. IMHO it makes more sense to wrap the APIs you are working with in a C function that you can make 'nice' to call from Swift. The problem with your current approach is that this type of Swift is hard to read for Swift developers and also hard to read for Audio Toolbox developers.
How to represent Objc-C NSUInteger[] = {0,1,2} in Swift as UnsafeMutablePointerUInt?
You can simply pass a Swift [UInt]
array as in-out argument with &
, this passes the address of the array element storage to the (Objective-)C function:
var pageIndexes: [UInt] = [1, 2, 3]
ptp.printPDF(atPath: "path", pages: &pageIndexes, length: UInt(pageIndexes.count), copy: 1)
For more information, see
- Using Imported C Functions in Swift,
- Interacting with C Pointers.
Related Topics
Why Does a Function Have Long-Term Write Access to All of Its In-Out Parameters
Convert Input Data to Integer in Swift
Swift Bug? Calling Super Class Method When Subclass with Generic Type
List Scroll Freeze on Catalyst Navigationview
Swift Auto Completion Not Working in Xcode 6 Beta
Idiomatic Way to Test Swift Optionals
How to Loop Over The Output of a Publisher with Combine
On Demand Resources "0 Asset Packs"
Testing a Class Which Preserves Its State in Private Variables
Access Each Header and Controls in The Tableview in Swift
Swiftui New App Lifecycle How to Connect The Facebook Sdk
Swift Loaditem Closure Not Running
How to Get a Full List of Running Processes
Understanding Optional Global Variables in Swift
Applying Impulses in Spritekit