I got this statement in Swift code which produces an error when executing in playground:
let colors: [String: [Float]] = ["skyBlue" : [240.0/255.0, 248.0/255.0, 255.0/255.0,1.0],
"cWhite" : [250.0/255.0, 250.0/255.0, 250.0/255.0, 1.0]]
The error is : expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions
Then I changed the arrays element type to Double which just works fine.
However I am asking myself why this happens ?
As I said using Double it works just fine. So my guess is that Swift tries to guess the type and therefore Double works better in this example than Float.
Similar issues have been reported before, and (as I understand it) the problem is the automatic type inference for "complicated" expressions. You should file a bug report at Apple.
It compiles with a dictionary of one color, but not with two.
In this concrete case, you can work around it by converting each number in the array to a Float explicitly:
let colors = [
"skyBlue" : [Float(240.0/255.0), Float(248.0/255.0), Float(255.0/255.0),Float(1.0)],
"cWhite" : [Float(250.0/255.0), Float(250.0/255.0), Float(250.0/255.0), Float(1.0)]
]
Related
I need your help. I tried a lot to find a solution for the problem but failed so far.
Idea:
Create a vector of "command tuples" like the following:
typedef boost::tuple<std::string, boost::function<void()>> command_tuple;
std::vector<command_tuple> commands {
boost::make_tuple("command1", boost::bind(&myclass::command1, this))
};
If the string "command1" is used the void command1() function is called. The ID index value is based on find_if search for the string ("command1" is ID=0) on the vector.
This is working fine!
boost::get<1>(commands[ID])();
Problem:
I found no way so far to use a vector of boost::function (pointers) defined with any kind type of function parameters:
typedef boost::tuple<std::string, boost::function<void(const char *)>> command_tuple;
std::vector<command_tuple> commands {
boost::make_tuple("command1", boost::bind(&myclass::command1, this, std::placeholders::_1))
};
This will fail with a cannot convert std::_Placeholder<1> to type const char * compilation error.
This is therefore not possible:
boost::get<1>(commands[ID])("dynamic string argument");
Pinning down of the problem:
hmmm ... so I found out so far that even a simple vector of boost::function does not seem to work (in the way I am trying to use it):
std::vector<boost::function<void(const char *)>> commands {
boost::bind(&myclass:command1, this, std::placeholders::_1)
};
Fails with the same compilation error.
It is possible to replace the std::placeholders::_1 with "static string constants" to avoid any compilation errors. But my idea was to use a "dynamic string argument".
Can someone please give me a quick hint of what I am doing wrong or maybe show some simple alternatives. I want to have quite a big list of function pointers that I can call based on their "string name".
I simply want to avoid a big "switch select case" style code block to
select the function to be executed based on a dynamic "input string".
Thanks for your time!
like T.C. replied in the comments. You should never mix std::bind, std::placeholders and boost::bind.
Now that we've reached Swift 2.0, I've decided to convert my, as yet unfinished, OS X app to Swift. Making progress but I've run into some issues with using termios and could use some clarification and advice.
The termios struct is treated as a struct in Swift, no surprise there, but what is surprising is that the array of control characters in the struct is now a tuple. I was expecting it to just be an array. As you might imagine it took me a while to figure this out. Working in a Playground if I do:
var settings:termios = termios()
print(settings)
then I get the correct details printed for the struct.
In Obj-C to set the control characters you would use, say,
cfmakeraw(&settings);
settings.c_cc[VMIN] = 1;
where VMIN is a #define equal to 16 in termios.h. In Swift I have to do
cfmakeraw(&settings)
settings.c_cc.16 = 1
which works, but is a bit more opaque. I would prefer to use something along the lines of
settings.c_cc.vim = 1
instead, but can't seem to find any documentation describing the Swift "version" of termios. Does anyone know if the tuple has pre-assigned names for it's elements, or if not, is there a way to assign names after the fact? Should I just create my own tuple with named elements and then assign it to settings.c_cc?
Interestingly, despite the fact that pre-processor directives are not supposed to work in Swift, if I do
print(VMIN)
print(VTIME)
then the correct values are printed and no compiler errors are produced. I'd be interested in any clarification or comments on that. Is it a bug?
The remaining issues have to do with further configuration of the termios.
The definition of cfsetspeed is given as
func cfsetspeed(_: UnsafeMutablePointer<termios>, _: speed_t) -> Int32
and speed_t is typedef'ed as an unsigned long. In Obj-C we'd do
cfsetspeed(&settings, B38400);
but since B38400 is a #define in termios.h we can no longer do that. Has Apple set up replacement global constants for things like this in Swift, and if so, can anyone tell me where they are documented. The alternative seems to be to just plug in the raw values and lose readability, or to create my own versions of the constants previously defined in termios.h. I'm happy to go that route if there isn't a better choice.
Let's start with your second problem, which is easier to solve.
B38400 is available in Swift, it just has the wrong type.
So you have to convert it explicitly:
var settings = termios()
cfsetspeed(&settings, speed_t(B38400))
Your first problem has no "nice" solution that I know of.
Fixed sized arrays are imported to Swift as tuples, and – as far as I know – you cannot address a tuple element with a variable.
However,Swift preserves the memory layout of structures imported from C, as
confirmed by Apple engineer Joe Groff:. Therefore you can take the address of the tuple and “rebind” it to a pointer to the element type:
var settings = termios()
withUnsafeMutablePointer(to: &settings.c_cc) { (tuplePtr) -> Void in
tuplePtr.withMemoryRebound(to: cc_t.self, capacity: MemoryLayout.size(ofValue: settings.c_cc)) {
$0[Int(VMIN)] = 1
}
}
(Code updated for Swift 4+.)
I've been writing an app that involves using NSUserDefaults to store a few Int variables and it's been working fine. I thought I was finished and was doing some final testing and one of the first lines of code that I wrote, and that has been working consistently before, has failed me.
Apparently the green line error is supposed to occur if I try to unwrap an optional that has a value of nil, but this variable is still very much an optional
var savedTotalSeconds: Int? = userDefaults.objectForKey("totalSecondsKey") as Int?
Why would this possibly return an error? It was working fine before and I only changed things I thought were unrelated to it. In the app I have a button to remove this stored value via:
userDefaults.removeObjectForKey("totalSecondsKey")
What could possibly have gone wrong?
Try using 'as? Int' instead of 'as Int?'
The difference is that the first one tries, and might fail, at casting to Int. That failure will be captured in the optionality of the resulting variable.
The second one tries to coerce the object to 'Int?'.
I've encountered a coding error for my flappy bird project, in Xcode 6.1.
The code is to allow rotation of the bird, and it reads:
bird.zRotation = self.acotarMinMax(-1, max: 0.3, valor: bird.physicsBody?.velocity.dy * (bird.physicsBody?.velocity.dy < 0 ? 0.003 : 0.001))
the error occurs under dy, it reads:
value of optional type 'CGFloat?' not unwrapped; did you mean to use '!' or '?'?
How can I correct the error, or is there another way to generate rotation?
I am a total beginner of Swift, so I'm having a hard time figuring out if this is a syntax problem or something to do with the updated version.
I obtained the code from a online tutorial, and it worked in the video.
Read up on the Swift Optional class: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html
So it seems that dy is an Optional value, which means that it either has a value or it does not, but you don't know until you look into it (like Schroedinger's Cat). So if you need this value and you know it will not be nil, you unwrap it by writing bird.physicsBody?.velocity.dy! which will look into the "box" and take the value out but crash if there is nothing inside. If you write dy? it will look into the box but ignore it if the box is empty.
More on Optional Chaining (which is what you do) here: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html
So I just figured out my error.
As Sebastian correctly pointed out, it is to do with optional chaining.
The code that worked is:
bird.zRotation = self.acotarMinMax(-1, max: 1, valor: bird.physicsBody!.velocity.dy * (bird.physicsBody!.velocity.dy < 0 ? 0.002 : 0.002))
I used '!' to force a value on physicsBody. The precise mechanism of why this works is still a blur to me. But my guess is to do with the new version's correction method.
According to my understanding of the documentation, this should be correct:
var cookies: [NSHTTPCookie] = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies as [NSHTTPCookie]
where I'm creating an array of NSHTTPCookie objects. The interpreter does not like this syntax, however, giving me "Expected type after 'as'" and putting a little pointer at the opening bracket of the [NSHTTPCookie] at the end.
However, this works:
var cookies:NSHTTPCookie[] = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies as NSHTTPCookie[]
From the documentation, it seems like the first version is more correct, however.
Here's another example, this time with someone else's code. No one else using this code has reported the same behavior I get. (This is just a snippet; if the context is relevant let me know and I'll post more)
func asDict(x: AnyObject) -> [String:AnyObject]? {
return x as? [String:AnyObject]
}
In this case the playground interpreter objects in both places [String:AnyObject] is used. It just doesn't seem to be recognizing it as a type.
I double-checked to make sure I have the most recent beta of Xcode 6, but it seems much more likely to me that the problem is in my understanding rather than in the tool, since this would be a mighty big bug for only me to experience.
You must be using an old beta, this works in Beta 5 playground:
import Foundation
println("hello")
var cookies:[NSHTTPCookie] = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies as [NSHTTPCookie]
println("goodbye")