I'm trying to convert this objc code to swift:
CGContextRef contextRef = CGBitmapContextCreate(NULL,
proposedRect.size.width,
proposedRect.size.height,
CGImageGetBitsPerComponent(imageRef),
0,
colorSpaceRef,
(CGBitmapInfo)kCGImageAlphaPremultipliedFirst);
NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithGraphicsPort:contextRef flipped:NO];
So far I ended up with this:
var bitmapContext: CGContext = CGBitmapContextCreate(data, UInt(proposedRect.width), UInt(proposedRect.height), CGImageGetBitsPerComponent(image), 0, colorSpace, CGBitmapInfo(CGImageAlphaInfo.PremultipliedFirst.toRaw()))
let context = NSGraphicsContext(graphicsPort: bitmapContext, flipped: false)
The problem is that CGBitmapContextCreate returns CGContext type and NSGraphicsContext initializer accepts graphicsPort as CMutableVoidPointer type. So how can I convert CGContext to CMutableVoidPointer?
related reverse type casting found here, but it didn't provide much help to me
How to convert COpaquePointer in swift to some type (CGContext? in particular)
I ended up with the reinterpretCast function returning intermediate Int variable for the bitmapContext address.
var bitmapContext: CGContext = CGBitmapContextCreate(...)
let bitmapContextAddress: Int = reinterpretCast(bitmapContext)
let bitmapContextPointer: CMutableVoidPointer = COpaquePointer(UnsafePointer<CGContext>(bitmapContextAddress))
let context = NSGraphicsContext(graphicsPort: bitmapContextPointer, flipped: false)
The documentation here:https://developer.apple.com/library/prerelease/ios/documentation/swift/conceptual/buildingcocoaapps/InteractingWithCAPIs.html
states the following:
When a function is declared as taking a CMutableVoidPointer argument,
it can accept the same operands as CMutablePointer for any type
Type.
From that, it should work like this:
var p: CMutablePointer<CGContext> = &bitmapContext
NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithGraphicsPort:p flipped:NO];
Extended practically, you should be able to pass in &bitmapContext directly to a CMutableVoidPointer argument.
Swift doesn't have "pointers" in the C sense.
Related
Bellow is a minimal example when wrapping the OpenAL32.dll. The foreign function alcCreateContext has the argument attrlist which takes a ptr to an array of type ALCint or nil. The issue is the array can be of different lengths depending on the amount of different flags passed in. The array should be organized as [flag, int, flag, int, ...]. How can this be accomplished in a more dynamic way allowing the inclusion of ALC_FREQUENCY for example? The array size is currently hard coded into the procedure and its nasty.
when defined(windows):
{.push cdecl, dynlib: "OpenAL32.dll", importc.}
else:
{.push importc.}
type
ALCint = cint
ALCdevice* = pointer
ALCcontext* = pointer
const
ALC_MONO_SOURCES* = 0x00001010
ALC_STEREO_SOURCES* = 0x00001011
ALC_FREQUENCY* = 0x00001007
proc alcCreateContext*(device: ALCdevice; attrlist: ptr array[0..3, ALCint]): ALCcontext
proc alcOpenDevice*(devicename: cstring): ALCdevice
const attributes = [ALC_MONO_SOURCES.ALCint, 65536.ALCint, ALC_STEREO_SOURCES.ALCint, 65536.ALCint]
discard alcOpenDevice(nil).alcCreateContext(attributes.unsafeAddr)
I experimented with openArray and other containers. Is the solution some sort of cast? This is also the workaround for getting more then 256 sounds out of OpenAL.
Answer from PMunch. Thank You.
The foreign function now wants ptr UncheckedArray[ALCint] and when passing the argument use cast[ptr UncheckedArray[ALCint]](attributes.unsafeAddr)
when defined(windows):
{.push cdecl, dynlib: "OpenAL32.dll", importc.}
else:
{.push importc.}
type
ALCint = cint
ALCdevice* = pointer
ALCcontext* = pointer
const
ALC_MONO_SOURCES* = 0x00001010
ALC_STEREO_SOURCES* = 0x00001011
ALC_FREQUENCY* = 0x00001007
proc alcCreateContext*(device: ALCdevice; attrlist: ptr UncheckedArray[ALCint]): ALCcontext
proc alcOpenDevice*(devicename: cstring): ALCdevice
const attributes = [ALC_MONO_SOURCES.ALCint, 65536.ALCint, ALC_STEREO_SOURCES.ALCint, 65536.ALCint]
discard alcOpenDevice(nil).alcCreateContext(cast[ptr UncheckedArray[ALCint]](attributes.unsafeAddr))
An array in C is simply a pointer to anywhere with one or more contiguous elements of the same type. So to pass a C array to a function you simply need to get such a pointer. Say for example you have a seq of integers then the address of the first element is a C array. Simply do mySeq[0].addr and you're good. Keep the lifecycle of the data in mind though. If Nim doesn't find any more references to the sequence then the memory will get freed. You can also manually get a pointer with create (https://nim-lang.org/docs/system.html#create%2Ctypedesc) and you can cast such pointers to ptr UncheckedArray[T] to be able to use [] on the data in Nim.
I am working with the Map module in OCaml. Consider the following code to create a map with ints as keys:
module Int = struct
type t = int
let compare a b = a - b
end
module IntMap = Map.Make(Int)
let m = IntMap.(empty |> add 3 "hello")
This all works fine. It compiles and behaves as I would expect.
However, if I add a type annotation for the Int module so the top line becomes:
module Int : Map.OrderedType = struct
The final line causes an error in compilation:
let m = IntMap.(empty |> add 3 "hello")
^
Error: This expression has type int but an expression was expected of type
IntMap.key = Int.t
However IntMap.key and Int.t are both just an alias for int. Furthermore the Int module is of type Map.OrderedType. I know this because that's the required type for Map.Make.
So what an earth is going on here? Why would providing a type annotation that isn't necessary cause an error like this. Do type annotations cause stricter accessibility and not behave the same as inferred types?
This kind of annotation strictly limits the interface of a module. So it seems to me that with the added annotation the only things known about the key type of the map are as given by Map.OrderedType:
module type OrderedType =
sig type t val compare : t -> t -> int end
This says nothing about the type t except that it exists and that it appears in the parameters of compare. In other words, you have hidden the fact that the type t (also known as IntMap.key) is the same type as int.
You can re-introduce this fact using with:
module Int : Map.OrderedType with type t = int = struct
type t = int
let compare a b = a - b
end
It seems like you can't use named tuples in the shorthand notation of Dictionary. Is that so?
E.g.:
var dt = Dictionary<Int, (x:Double, y:Double)>()
var dtShort = [Int: (Double, Double)]()
var dtShortNamed = [Int: (x:Double, y:Double)]()
The first two lines work, the third triggers an error "Expected member name or constructor call after type name"
Is this correct, or am I missing something?
You are correct that it doesn't seem to work that way in Xcode 6 GM or Xcode 6.1 Beta 2.
It does work if you use a typealias though:
typealias NamedTuple = (x:Double, y:Double)
var dtShortNamed = [Int: NamedTuple]()
But, in that case, you might as well just use your first example:
var dt = Dictionary<Int, (x:Double, y:Double)>()
I am trying to do this:
var dictArray = [String:[String]]()
dictArray["test"] = [String]()
dictArray["test"]! += "hello"
But I am getting the weird error NSString is not a subtype of 'DictionaryIndex<String, [(String)]>'.
I just want to be able to add objects to an array inside a dictionary.
Update: Looks like Apple considers this a "known issue" in Swift, implying it will work as expected eventually. From the Xcode 6 Beta 4 release notes:
...Similarly, you cannot modify the underlying value of a mutable
optional value, either conditionally or within a force-unwrap:
tableView.sortDescriptors! += NSSortDescriptor(key: "creditName", ascending: true)
Workaround: Test the optional value explicitly and then assign the
result back:
if let window = NSApplication.sharedApplication.mainWindow {
window.title = "Currently experiencing problems"
}
tableView.sortDescriptors = tableView.sortDescriptors!
You can only do this
var dictArray = [String:[String]]()
dictArray["test"] = [String]()
var arr = dictArray["test"]!;
arr += "hello"
dictArray["test"] = arr
because dictArray["test"] give you Optional<[String]> which is immutable
6> var test : [String]? = [String]()
test: [String]? = 0 values
7> test += "hello"
<REPL>:7:1: error: '[String]?' is not identical to 'UInt8'
append also won't work due to the same reason, Optional is immutable
3> dictArray["test"]!.append("hello")
<REPL>:3:18: error: '(String, [(String)])' does not have a member named 'append'
dictArray["test"]!.append("hello")
^ ~~~~~~
BTW the error message is horrible...
You may use NSMutableArray instead of [String] as a value type for your dictionary:
var dictArray: [String: NSMutableArray] = [:]
dictArray["test"] = NSMutableArray()
dictArray["test"]!.addObject("hello")
This is still an issue in Swift 3. At least I was able to create method that can handle it for you.
func appendOrCreate(newValue: Any, toArrayAt key: String, in existingDictionary: inout [AnyHashable:Any]) {
var mutableArray = [Any]()
if let array = existingDictionary[key] as? [Any]{
//include existing values in mutableArray before adding new value
for existingValue in array {
mutableArray.append(existingValue)
}
}
//append new value
mutableArray.append(newValue)
//save updated array in original dictionary
existingDictionary[key] = mutableArray
}
The problem is that we want class semantics here but have to use structs. If you put class objects into the dictionary, you get what you want!
So, if you haveĀ¹ to have mutable values, you can wrap them in a class and perform updates with a closure:
class MutableWrapper<T> {
var rawValue: T
init(_ val: T) {
self.rawValue = val
}
func update(_ with: (inout T) -> Void) {
with(&self.rawValue)
}
}
Example:
func foo() {
var dict = [String: MutableWrapper<[String]>]()
dict["bar"] = MutableWrapper(["rum"])
dict["bar"]?.update({$0.append("gin")})
print(dict["bar"]!.rawValue)
// > ["rum", "gin"]
}
For what it's worth, I do not see a way to keep caller and wrapper in sync. Even if we declare init(_ val: inout T) we will end up with a copy in rawValue.
Performance is not necessarily an issue since the compiler optimizes structs heavily. I'd benchmark any mutable solution against what looks like lots of copy-updates in the code.
Since Swift 4.1 you can provide a default value to the subscript which allows you to solve this quite naturally now:
dictArray["test", default: []].append("hello")
So I started a project in Swift, and I've come to this problem:
this code works:
var dictionary = ["a":"valueOfA","b":"valueOfB","c":"valueOfC"]
println(dictionary)
dictionary["c"] = "newValOfC"
println(dictionary)
and this doesn't:
var dictionary = [:]
dictionary = ["a":"valueOfA","b":"valueOfB","c":"valueOfC"]
println(dictionary)
dictionary["c"] = "newValOfC"
println(dictionary)
Gives an error:
Playground execution failed: error: <REPL>:35:17: error: cannot assign to the result of this expression
dictionary["c"] = "newValC"
~~~~~~~~~~~~~~~ ^
Notice that this is not a constant value
So why doesn't the line
dictionary = ["a":"valueOfA","b":"valueOfB","c":"valueOfC"]
give an error?
Since the context does not provide enough information to infer the type, you'll need to explicitly name it as a dictionary, otherwise swift assumes it is an NSDictionary (I'm not clear on why though. I assume for better obj-c compatibility):
The following code all works:
// Playground
import UIKit
var str:NSString = "Hello, playground"
var d0 = [:]
var d1: Dictionary = [:]
d0.setValue(UIWebView(), forKey: "asdf")
d1["asdf"] = 1
d1["qwer"] = "qwer"
Okay, I found it, the problem is that by initializing an empty dictionary, the type inference gets a little crazy.
You'll need this code:
var dictionary = Dictionary<String, String>()
instead of
var dictionary = [:]
but that still does not explain why the line
dictionary = ["a":"valueOfA","b":"valueOfB","c":"valueOfC"]
does not give an error
And referring to Swift Language Guide, the
dictionary = [:]
syntax is correct "if the context already provides type information".
The big difference is that
var dictionary = [:]
doesn't give any chance the compiler to infer the right type, whereas
var dictionary = ["a":"valueOfA","b":"valueOfB","c":"valueOfC"]
does.
Actually it looks like the first line produces a __NSDictionaryI instance, whereas the second one produces a Dictionary<String,String as expected.
From The Swift Programming Language book
If the context already provides type information, create an empty dictionary with an empty dictionary literal, which is written as [:] (a colon inside a pair of square brackets):
which means the first line is ambiguous.
The [:] syntax only works if the current context has enough information to be able to infer what the types are. Here are a few ways where the context is known...
As has been mentioned already, the code below works because it can be inferred that the keys and values are strings:
var dictionary = [ "a" : "valueOfA" , "b" : "valueOfB" , "c" : "valueOfC" ]
A dictionary passed into a function has a known context:
func dictionaryFunc(var dictionary : Dictionary<String, String>) {
// Do stuff with the dictionary
}
In both cases, the key/value types for the dictionary are now known, so you could do this to create a new dictionary with the same variable name...
dictionary = [:]
In the first case, if you used the [:] syntax after the declaration you would be erasing the contents of the original dictionary. In the second case, dictionaries get copied when they get passed into functions, so using [:] would only be erasing the copy.
In Swift 2.0 I'm using this:
var dictionary = [String:String]()
dictionary["key1"] = "value1"