I've tried dozens of things to get this right and just can't come up with anything that works. Can anyone tell me what's wrong with the following Swift code:
let incomingRequest: CFHTTPMessageRef? = CFDictionaryGetValue(self.incomingRequests as CFMutableDictionaryRef, unsafeAddressOf(incomingFileHandle!)) as CFHTTPMessageRef
The code above gives the error message: 'UnsafePointer<Void>' is not convertible to 'CFHTTPMessageRef'
I guess what I don't understand is how do I convert an 'UnsafePointer' returned by a Core Foundation function to the pointer type it should be (i.e. CFHTTPMessageRef in this case). How do I find documentation on how to do this. I've read everything I can find, but nothing so far explains how to recast return values to what they should have been in the first place. This has to be documented somewhere, doesn't it?
EDIT
Here's the code I'm having trouble with:
let incomingRequest = CFDictionaryGetValue(self.incomingRequests as CFMutableDictionaryRef, unsafeAddressOf(incomingFileHandle!))
unsafeBitCast(incomingRequest, CFHTTPMessageRef.self)
if (incomingRequest != nil) {
let success: Boolean = CFHTTPMessageAppendBytes(incomingRequest as CFHTTPMessageRef, unsafeAddressOf(data!.bytes) as UnsafePointer<UInt8>, data!.length)
if success { // Do something... }
The CFHTTPMessageAppendBytes call still gives a "Type 'UnsafePointer' does not conform to protocol 'AnyObject'". And the following 'if' check for 'success' complains that "Type 'Boolean' doesn not conform to protocol 'BooleanType'". What the heck is that about? Boolean isn't a Boolean type?
I find the strict type checking of Swift extremely frustrating. So far it is far more difficult to code in than Obj-C, C, or any of the other languages I've used. I'm sure it's because I just don't get it, or haven't found the right documentation, but this is really driving me crazy.
Use unsafeBitCast. As following example:
import Foundation
var x = "1"
var dict : NSMutableDictionary = [x: "2"]
var y = CFDictionaryGetValue(dict as CFMutableDictionaryRef, unsafeAddressOf(x))
let str: NSString = unsafeBitCast(y, NSString.self)
str == "2"
FYI: There is one quora related with unsafeBitCast. http://www.quora.com/Why-does-Swift-not-allow-implicit-type-conversion
Related
I am trying to find a count of entities which satisfy predicate. According to documentation and "header" files, this should work:
let fetch = NSFetchRequest<NSFetchRequestResult>(entityName: "FileRecord")
let ctx: NSManagedObjectContext = GetCtx()
let res = try ctx.count(for: fetch)
however I get compile error:
Cannot invoke 'count' with an argument list of type '(for: NSFetchRequest<NSFetchRequestResult>)'
however when I create the fetch request from FileRecord like this instead:
let fetch: NSFetchRequest<FileRecord> = FileRecord.fetchRequest()
I get the following error:
Cannot convert value of type 'NSFetchRequest<FileRecord>' to expected argument type 'NSFetchRequest<NSFetchRequestResult>'
Please anyone got an idea what can be wrong? I am a decent C++ language lawyer but I am just a novice with Swift...
EDIT: SOLVED
My example above was wrong. In reality I had code functionally identical to:
let res: UInt64 = try ctx.count(for: fetch)
since count returns Int, the function did not match. The error message was not specific enough for me to see it immediately. Thanks to all who have tried to help :)
I'm trying to write a general argmin function in Swift. Here is my code:
func argmin<X, Y:Comparable, R:SequenceType, where X== R.Generator.Element>
(f:(X)->Y, domain:R)->X{
var gen = domain.generate()
var best = gen.next()!
var minval = f(best)
while let this = gen.next() {
let value = f(this)
if value < minval {
best = this
minval = value
}
}
return best
}
I get the error message "Expected identifier to name generic parameter" when I try to compile this definition. I have no idea what this means. It sounds like an error one would get on calling the function, not defining it, but even then, I wouldn't understand it.
I'm just starting to learn Swift. Can you explain this message? (BTW, I know this function will blow up if called with an empty sequence. I'm not worrying about that yet.)
You have to remove this comma:
func argmin<X, Y:Comparable, R:SequenceType, where X== R.Generator.Element>
^
Placed that, it tells the compiler there's another generic parameter. The error message just says that - maybe in a cryptic way, but once you know, it's clearer what it means
I'm working with a third party c API I'm trying to call one of the functions with a simple string. Something like this:
some_c_func("aString");
I get a build error:
Type 'UnsafeMutablePointer<char_t>' does not conform to protocol 'StringLiteralConvertible'
I've seen some suggestions to use utf8 on String or similar conversions, which gets nearly there, but with the following error:
some_c_func("aString".cStringUsingEncoding(NSUTF8StringEncoding));
'UnsafePointer<Int8>' is not convertible to 'UnsafeMutablePointer<char_t>'
How can I create an UnsafeMutablePointer?
It all depends on what char_t is.
If char_t converts to Int8 then the following will work.
if let cString = str.cStringUsingEncoding(NSUTF8StringEncoding) {
some_c_func(strdup(cString))
}
This can be collapsed to
some_c_func(strdup(str.cStringUsingEncoding(NSUTF8StringEncoding)!))
WARNING! This second method will cause a crash if func cStringUsingEncoding(_:) returns nil.
Updating for Swift 3, and to fix memory leak
If the C string is only needed in a local scope, then no strdup() is needed.
guard let cString = str.cString(using: .utf8) else {
return
}
some_c_func(cString)
cString will have the same memory lifecycle as str (well similar at least).
If the C string needs to live outside the local scope, then you will need a copy. That copy will need to be freed.
guard let interimString = str.cString(using: .utf8), let cString = strdup(interimString) else {
return
}
some_c_func(cString)
//…
free(cString)
it may be simpler than that - many C APIs pass strings around as char * types, and swift treats these as unsafe.
try updating the C API (good) or hack it's header files (bad) to declare these as const char * instead.
in my experience this allows you to pass standard swift String types directly to the C API.
apparently a constant is required, in order to conform to the protocol.
I haven't tried passing strings like that, but I have a C function that I call from Swift, that takes a lot more parameters than shown here, among which is a reference to a Swift C typecast buffer to hold an error string. The compiler doesn't complain and the function call works. Hopefully this will steer you closer to the answer and you can provide an update with the final answer or someone else can.
var err = [CChar](count: 256, repeatedValue: 0)
var rv = somefunc((UnsafeMutablePointer<Int8>)(err))
if (rv < 0) {
println("Error \(err)")
return
}
I'm sure this is something stupid I'm doing wrong but why is the swift parser telling me I can't convert the expression's type () when clearly the definition of AudioQueueDispose returns an OSStatus type? I've put off asking this question for a while cos I know it's going to be something dumb I'm just overlooked.
I put this in to Xcode playground for simplicity...
import UIKit
import AudioToolbox
import AVFoundation
var audioQueue:AudioQueue
var status : OSStatus = OSStatus(noErr)
status = AudioQueueDispose(audioQueue, inImmediate: false)
I think the error message was very misleading especially with the little arrow pointing to the '=' sign implying it was an issue with the return type. Anyway, the actual problem is to do with using 'false', which is a swift type 'Bool', whereas the function expects at type 'Boolean' which is in fact a UInt8. So the above can be fixed by writing...
status = AudioQueueDispose(audioQueue, 0)
Perhaps someone can offer a better solution which does not involve using integers?
For now I'm just defining a couple of constants..
let FALSE:Boolean = 0
let TRUE:Boolean = 1
I am quite new to swift and got a pretty weird compiler error:
Command
/Applications/Xcode6-Beta5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc
failed with exit code 254
The Error occours when I ad the following lines to my code:
var response = HoopsClient.instance().collections["posts"]
response = response["_id"]
when I remove the second line everything compiles fine. I don't get it ^^
edit: The reason is probably that "response" is of type "AnyObject" according to the compiler... but shouldn't that be detected by xcode or give me a runtime error instead of this compiler error?
Try casting response as the type you're expecting. From what you're trying to do, instance().collections I would assume that it should return some type of dictionary.
var response = HoopsClient.instance().collections["posts"] as NSDictionary
That way, response now can handle subscripts so you could now (in theory) do:
response = response["_id"]
However
The error you get is regarding bad access to an array. This makes me think that instance().collections actually returns an array of some sort, containing Post objects.
Arrays in Swift can only handle Integer subscripts. If you want to access the information of a Post in the array, you can do something like this:
for post: Post in response {
println(post._id)
}
I know this is a long shot, but hope it helps.
Swift tends to throw error when it cant infer the type of an object, what you could probably do is add a conditional cast as follows
Im assuming that HoopsClient.instance().collections["posts"] is either a Dictionary or an Array
var response = HoopsClient.instance().collections["posts"]
if response is NSArray {
let item = response.objectAtIndex(0)
let reponseId: Post = item
}
if response is NSDictionary {
let item = response.objectForKet("_id")
let reponseId: Post = item
}
Any way, in my experience you should try to cast your variables when assigning from types that return AnyObject, xcode doesn't handle very well type inferring and when it's unable to infer the type the interface starts to throw error, like text editor uncoloring the code.