I have a ClosedRange passed in as a parameter, and now I need to convert it to a ClosedRange:
let range: ClosedRange<Int>
init(range: ClosedRange<Int>) {
self.range = range
}
var body: some View {
Slider(value: doubleBinding, in: range.startIndex...range.endIndex, step: 1)
}
The Slider init function takes a ClosedRange argument. So I got this error:
Cannot convert value of type 'ClosedRange<Int>.Index' to expected argument type 'Double'
So I tried this:
let min = Double(Int(range.startIndex))
let max = Double(Int(range.endIndex))
Slider(value: doubleBinding, in: min...max, step: 1)
But got this error:
Initializer 'init(_:)' requires that 'ClosedRange<Int>.Index' conform to 'BinaryInteger'
You've used the wrong property. It's not startIndex and endIndex. It's lowerBound and upperBound:
Slider(value: doubleBinding,
in: Double(range.lowerBound)...Double(range.upperBound),
step: 1)
You can write a ClosedRange initialiser that conveniently does this:
extension ClosedRange {
init<Other: Comparable>(_ other: ClosedRange<Other>, _ transform: (Other) -> Bound) {
self = transform(other.lowerBound)...transform(other.upperBound)
}
}
Usage:
Slider(value: doubleBinding,
in: ClosedRange(range, Double.init),
step: 1)
I have a flutter code and I compile it swift and every thing is working except one error
(Argument labels '(rawValue:)' do not match any available overloads
(xcode error))
Code:
func close() {
dismiss(animated: true)
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(400), execute: {() -> Void in
self.tmpWindow?.windowLevel = UIWindow.Level(rawValue: 0.0)
UIApplication.shared.delegate?.window??.makeKeyAndVisible()
if (self.statusDelegate != nil) {
self.statusDelegate?.safariExit(uuid: self.uuid)
}
})
}
please help
You are initialising the UIWindow.Level with the wrong type. You are using a a literal value of 0.0 which will be inferred to be a Double when the method signature is: init(rawValue: CGFloat). You need to either use a CGFloat variable or cast the literal to a CGFloat
self.tmpWindow?.windowLevel = UIWindow.Level(rawValue: CGFloat(0.0))
I have a problem in Swift whit optional function param. I want to set an value for an SKSpriteNote within a function, but this value dos not exist before the function is called, so i obviously get an error ;/
Can anyone please tell me what to do, to solve this?
THIS IS THE ERROR I GET:
Variable 'bought_ingredient_market_graphic' used before being initialized
THIS IS MY FUNCTION (see
func show_market_graphic(x: CGFloat, y: CGFloat, level: String, ingredient: String?){
var market_graphic: SKSpriteNode
var bought_ingredient_market_graphic: SKSpriteNode
if(level == "locked"){
market_graphic = SKSpriteNode(imageNamed: "locked_ingredient")
} else {
market_graphic = SKSpriteNode(imageNamed: "bought_ingredient")
bought_ingredient_market_graphic = SKSpriteNode(imageNamed: ingredient!)
}
market_graphic.zPosition = 10
market_graphic.position = CGPoint(x: x, y: y)
addChild(market_graphic)
if(level != "locked"){
// * ERROR ON LINE BELOW
bought_ingredient_market_graphic.zPosition = 20
// * ERROR ON LINE BELOW
bought_ingredient_market_graphic.position = market_graphic.position
// * ERROR ON LINE BELOW
addChild(bought_ingredient_market_graphic)
}
}
First off, I would consider using an enum when passing in the parameter "level" into the function. This will help fix possible logic issues within your function.
Where your problem probably lies: If you do not pass in a non-nil ingredient String, you will encounter an error when accessing or using bought_ingredient_market_graphic. You could have a typo in your string that you use to initialize your image. Make sure your string matches your image name. This is likely what is happening.
Also why not try initializing your sprite in the else logic?
func show_market_graphic(x: CGFloat, y: CGFloat, level: String, ingredient: String?) {
var market_graphic: SKSpriteNode
var bought_ingredient_market_graphic: SKSpriteNode
if level == "locked" {
market_graphic = SKSpriteNode(imageNamed: "locked_ingredient")
} else {
market_graphic = SKSpriteNode(imageNamed: "bought_ingredient")
bought_ingredient_market_graphic = SKSpriteNode(imageNamed: ingredient!)
bought_ingredient_market_graphic.zPosition = 20
bought_ingredient_market_graphic.position = market_graphic.position
addChild(bought_ingredient_market_graphic)
}
market_graphic.zPosition = 10
market_graphic.position = CGPoint(x: x, y: y)
addChild(market_graphic)
}
Your code should work in principle, the compiler fails to detect the corelation between level == "locked" and level != "locked".
I assume that the compiler sees a risk that the value of level could change betwwen the statelents. So the best way would be to initialize bought_ingredient_market_graphic in the first if-clause.
I am currently learning Rust and looking to use it for developing a GUI
based application with GTK+. My problem relates to registering callbacks to
respond to GTK events/signals and mutating state within those callbacks.
I have a working but inelegant solution, so I would like to ask if there
is a cleaner, more idiomatic solution.
I have implemented my code as a struct with method implementations, where
the struct maintains references to the GTK widgets along with other state
that it needs. It constructs a closure that is passed to the
GtkWidget::connect* functions in order to receive events, draw to a
canvas, etc. This can cause problems with the borrow checker, as I will now
explain. I have some working but (IMHO) non-ideal code that I will
show.
Initial, non-working solution:
#![cfg_attr(not(feature = "gtk_3_10"), allow(unused_variables, unused_mut))]
extern crate gtk;
extern crate cairo;
use gtk::traits::*;
use gtk::signal::Inhibit;
use cairo::{Context, RectangleInt};
struct RenderingAPITestWindow {
window: gtk::Window,
drawing_area: gtk::DrawingArea,
width: i32,
height: i32
}
impl RenderingAPITestWindow {
fn new(width: i32, height: i32) -> RenderingAPITestWindow {
let window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
let drawing_area = gtk::DrawingArea::new().unwrap();
drawing_area.set_size_request(width, height);
window.set_title("Cairo API test");
window.add(&drawing_area);
let instance = RenderingAPITestWindow{window: window,
drawing_area: drawing_area,
width: width,
height: height,
};
instance.drawing_area.connect_draw(|widget, cairo_context| {
instance.on_draw(cairo_context);
instance.drawing_area.queue_draw();
Inhibit(true)
});
instance.drawing_area.connect_size_allocate(|widget, rect| {
instance.on_size_allocate(rect);
});
instance.window.show_all();
return instance;
}
fn exit_on_close(&self) {
self.window.connect_delete_event(|_, _| {
gtk::main_quit();
Inhibit(true)
});
}
fn on_draw(&mut self, cairo_ctx: Context) {
cairo_ctx.save();
cairo_ctx.move_to(50.0, (self.height as f64) * 0.5);
cairo_ctx.set_font_size(18.0);
cairo_ctx.show_text("The only curse they could afford to put on a tomb these days was 'Bugger Off'. --PTerry");
cairo_ctx.restore();
}
fn on_size_allocate(&mut self, rect: &RectangleInt) {
self.width = rect.width as i32;
self.height = rect.height as i32;
}
}
fn main() {
gtk::init().unwrap_or_else(|_| panic!("Failed to initialize GTK."));
println!("Major: {}, Minor: {}", gtk::get_major_version(), gtk::get_minor_version());
let window = RenderingAPITestWindow::new(800, 500);
window.exit_on_close();
gtk::main();
}
The above fails to compile as the closures with
RenderingAPITestWindow::new that are created and passed to calls to
GtkWidget::connect* methods attempt to borrow instance. The
compiler states that the closures may outlive the function in which
they are declared and that instance is owned by the outer function,
hence the problem. Given that GTK may keep a reference to these closures
around for an unspecified amount of time, we need an approach in which the
lifetime can be determined at runtime, hence my next stab at the problem
in which the RenderingAPITestWindow instance is wrapped in
Rc<RefCell<...>>.
Wrapping the RenderingAPITestWindow instance compiles but dies at runtime:
#![cfg_attr(not(feature = "gtk_3_10"), allow(unused_variables, unused_mut))]
extern crate gtk;
extern crate cairo;
use std::rc::Rc;
use std::cell::RefCell;
use gtk::traits::*;
use gtk::signal::Inhibit;
use cairo::{Context, RectangleInt};
struct RenderingAPITestWindow {
window: gtk::Window,
drawing_area: gtk::DrawingArea,
width: i32,
height: i32
}
impl RenderingAPITestWindow {
fn new(width: i32, height: i32) -> Rc<RefCell<RenderingAPITestWindow>> {
let window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
let drawing_area = gtk::DrawingArea::new().unwrap();
drawing_area.set_size_request(width, height);
window.set_title("Cairo API test");
window.add(&drawing_area);
let instance = RenderingAPITestWindow{window: window,
drawing_area: drawing_area,
width: width,
height: height,
};
let wrapped_instance = Rc::new(RefCell::new(instance));
let wrapped_instance_for_draw = wrapped_instance.clone();
wrapped_instance.borrow().drawing_area.connect_draw(move |widget, cairo_context| {
wrapped_instance_for_draw.borrow_mut().on_draw(cairo_context);
wrapped_instance_for_draw.borrow().drawing_area.queue_draw();
Inhibit(true)
});
let wrapped_instance_for_sizealloc = wrapped_instance.clone();
wrapped_instance.borrow().drawing_area.connect_size_allocate(move |widget, rect| {
wrapped_instance_for_sizealloc.borrow_mut().on_size_allocate(rect);
});
wrapped_instance.borrow().window.show_all();
return wrapped_instance;
}
fn exit_on_close(&self) {
self.window.connect_delete_event(|_, _| {
gtk::main_quit();
Inhibit(true)
});
}
fn on_draw(&mut self, cairo_ctx: Context) {
cairo_ctx.save();
cairo_ctx.move_to(50.0, (self.height as f64) * 0.5);
cairo_ctx.set_font_size(18.0);
cairo_ctx.show_text("The only curse they could afford to put on a tomb these days was 'Bugger Off'. --PTerry");
cairo_ctx.restore();
}
fn on_size_allocate(&mut self, rect: &RectangleInt) {
self.width = rect.width as i32;
self.height = rect.height as i32;
}
}
fn main() {
gtk::init().unwrap_or_else(|_| panic!("Failed to initialize GTK."));
println!("Major: {}, Minor: {}", gtk::get_major_version(), gtk::get_minor_version());
let wrapped_window = RenderingAPITestWindow::new(800, 500);
wrapped_window.borrow().exit_on_close();
gtk::main();
}
The above solution compiles but its not particularly pretty:
RenderingAPITestWindow::new returns an
Rc<RefCell<RenderingAPITestWindow>> rather than a
RenderingAPITestWindow
Accessing fields and methods of RenderingAPITestWindow is complicated
by the fact that the Rc<RefCell<...>> must be opened up; it now requires
wrapped_instance.borrow().some_method(...) rather than just
instance.some_method(...)
Each closure requires it's own clone of wrapped_instance; attempting
to use wrapped_instance would attempt to borrow an object -- the
wrapper rather than the RenderingAPITestWindow this time -- that is
owned by RenderingAPITestWindow::new as before
While the above compiles, it dies at runtime with:
thread '<main>' panicked at 'RefCell<T> already borrowed', ../src/libcore/cell.rs:442
An unknown error occurred
This is due to the fact that the call to window.show_all() causes GTK to
initialise the widget hierarchy, resulting in the drawing area widget
receiving a size-allocate event. Accessing the window to call
show_all() required that the Rc<RefCell<...>> is opened (hence
wrapped_instance.borrow().window.show_all();) and the instance
borrowed. Before the borrow ends when show_all() returns, GTK invokes the
drawing area's size-allocate event handler, which causes the closure
connected to it (4 lines above) to be invoked. The closure attempts to
borrow a mutable reference to the RenderingAPITestWindow instance
(wrapped_instance_for_sizealloc.borrow_mut().on_size_allocate(rect);)
in order to invoke the on_size_allocate method. This attempts to borrow a
mutable reference, while the first immutable reference is still in scope.
This second borrow causes the run-time panic.
The working but - IMHO - inelegant solution that I have managed to get
working so far is to split RenderingAPITestWindow into two structs, with
the mutable state that is to modified by the callbacks moved into a
separate struct.
Working but inelegant solution that splits the RenderingAPITestWindow struct:
#![cfg_attr(not(feature = "gtk_3_10"), allow(unused_variables, unused_mut))]
extern crate gtk;
extern crate cairo;
use std::rc::Rc;
use std::cell::RefCell;
use gtk::traits::*;
use gtk::signal::Inhibit;
use cairo::{Context, RectangleInt};
struct RenderingAPITestWindowState {
width: i32,
height: i32
}
impl RenderingAPITestWindowState {
fn new(width: i32, height: i32) -> RenderingAPITestWindowState {
return RenderingAPITestWindowState{width: width, height: height};
}
fn on_draw(&mut self, cairo_ctx: Context) {
cairo_ctx.save();
cairo_ctx.move_to(50.0, (self.height as f64) * 0.5);
cairo_ctx.set_font_size(18.0);
cairo_ctx.show_text("The only curse they could afford to put on a tomb these days was 'Bugger Off'. --PTerry");
cairo_ctx.restore();
}
fn on_size_allocate(&mut self, rect: &RectangleInt) {
self.width = rect.width as i32;
self.height = rect.height as i32;
}
}
struct RenderingAPITestWindow {
window: gtk::Window,
drawing_area: gtk::DrawingArea,
state: Rc<RefCell<RenderingAPITestWindowState>>
}
impl RenderingAPITestWindow {
fn new(width: i32, height: i32) -> Rc<RefCell<RenderingAPITestWindow>> {
let window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
let drawing_area = gtk::DrawingArea::new().unwrap();
drawing_area.set_size_request(width, height);
window.set_title("Cairo API test");
window.add(&drawing_area);
let wrapped_state = Rc::new(RefCell::new(RenderingAPITestWindowState::new(width, height)))
;
let instance = RenderingAPITestWindow{window: window,
drawing_area: drawing_area,
state: wrapped_state.clone()
};
let wrapped_instance = Rc::new(RefCell::new(instance));
let wrapped_state_for_draw = wrapped_state.clone();
let wrapped_instance_for_draw = wrapped_instance.clone();
wrapped_instance.borrow().drawing_area.connect_draw(move |widget, cairo_context| {
wrapped_state_for_draw.borrow_mut().on_draw(cairo_context);
wrapped_instance_for_draw.borrow().drawing_area.queue_draw();
Inhibit(true)
});
let wrapped_state_for_sizealloc = wrapped_state.clone();
wrapped_instance.borrow().drawing_area.connect_size_allocate(move |widget, rect| {
wrapped_state_for_sizealloc.borrow_mut().on_size_allocate(rect);
});
wrapped_instance.borrow().window.show_all();
return wrapped_instance;
}
fn exit_on_close(&self) {
self.window.connect_delete_event(|_, _| {
gtk::main_quit();
Inhibit(true)
});
}
}
fn main() {
gtk::init().unwrap_or_else(|_| panic!("Failed to initialize GTK."));
println!("Major: {}, Minor: {}", gtk::get_major_version(), gtk::get_minor_version());
let wrapped_window = RenderingAPITestWindow::new(800, 500);
wrapped_window.borrow().exit_on_close();
gtk::main();
}
While the above code works as required, I would like to find a better way
for going forward; I would like to ask if anyone knows a better approach as
the above complicates the programming process a fair bit, with the need to
use Rc<RefCell<...>> and split structs to satisfy Rust's borrowing rules.
Here's a working version that I came up with:
#![cfg_attr(not(feature = "gtk_3_10"), allow(unused_variables, unused_mut))]
extern crate gtk;
extern crate cairo;
use std::rc::Rc;
use std::cell::RefCell;
use gtk::traits::*;
use gtk::signal::Inhibit;
use cairo::{Context, RectangleInt};
struct RenderingAPITestWindow {
window: gtk::Window,
drawing_area: gtk::DrawingArea,
state: RefCell<RenderingState>,
}
struct RenderingState {
width: i32,
height: i32,
}
impl RenderingAPITestWindow {
fn new(width: i32, height: i32) -> Rc<RenderingAPITestWindow> {
let window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
let drawing_area = gtk::DrawingArea::new().unwrap();
drawing_area.set_size_request(width, height);
window.set_title("Cairo API test");
window.add(&drawing_area);
let instance = Rc::new(RenderingAPITestWindow {
window: window,
drawing_area: drawing_area,
state: RefCell::new(RenderingState {
width: width,
height: height,
}),
});
{
let instance2 = instance.clone();
instance.drawing_area.connect_draw(move |widget, cairo_context| {
instance2.state.borrow().on_draw(cairo_context);
instance2.drawing_area.queue_draw();
Inhibit(true)
});
}
{
let instance2 = instance.clone();
instance.drawing_area.connect_size_allocate(move |widget, rect| {
instance2.state.borrow_mut().on_size_allocate(rect);
});
}
instance.window.show_all();
instance
}
fn exit_on_close(&self) {
self.window.connect_delete_event(|_, _| {
gtk::main_quit();
Inhibit(true)
});
}
}
impl RenderingState {
fn on_draw(&self, cairo_ctx: Context) {
cairo_ctx.save();
cairo_ctx.move_to(50.0, (self.height as f64) * 0.5);
cairo_ctx.set_font_size(18.0);
cairo_ctx.show_text("The only curse they could afford to put on a tomb these days was 'Bugger Off'. --PTerry");
cairo_ctx.restore();
}
fn on_size_allocate(&mut self, rect: &RectangleInt) {
self.width = rect.width as i32;
self.height = rect.height as i32;
}
}
fn main() {
gtk::init().unwrap_or_else(|_| panic!("Failed to initialize GTK."));
println!("Major: {}, Minor: {}", gtk::get_major_version(), gtk::get_minor_version());
let window = RenderingAPITestWindow::new(800, 500);
window.exit_on_close();
gtk::main();
}
I arrived at this through a few observations:
The instance is being shared across multiple closures for an undetermined amount of time. Rc is the right answer to that scenario because it provides shared ownership. Rc is very ergonomic to use; it works like any other pointer type.
The only part of instance that is actually mutated is your state. Since your instance is being shared, it cannot be borrowed mutably using the standard &mut pointer. Therefore, you must use interior mutability. This is what RefCell provides. Note though, that you only need to use RefCell on the state you're mutating. So this still separates out the state into a separate struct, but it works nicely IMO.
A possible modification to this code is to add #[derive(Clone, Copy)] to the definition of the RenderingState struct. Since it can be Copy (because all of its component types are Copy), you can use Cell instead of RefCell.
I'm running Yosemite public beta & Xcode6 Beta 4
Based on the OSX SceneKit template, I'm trying to determine what node was clicked on. Here is the mouseDown function, mostly from the template code.
The comment labeled #1 works, which if great, but I'm trying to understand why the code comments #2, #3, and #4 don't compile, or what the errors are really telling me.
Searching the errors I'm not finding results that appear to apply to my case.
the error for #2 seems to usually apply to type casting, and I wouldn't think there is any type casting going on here.
the error for #3 has me totally lost.
and the error for #4 seems like SCNNode doesn't have a name property, but it certainly does.
override func mouseDown(theEvent: NSEvent) {
/* Called when a mouse click occurs */
// check what nodes are clicked
let p = gameView.convertPoint(theEvent.locationInWindow, fromView: nil)
let hitResults = gameView.hitTest(p, options: nil)
// check that we clicked on at least one object
if (hitResults.count > 0){
// retrieved the first clicked object
let result: AnyObject = hitResults[0]
// #1 This works
if let myNode: SCNNode = result.node? {
if myNode.name? == "Die" {
println("Node is named Die")
}
}
// #2 This does not work
// error: Could not find an overload for the 'node' that accepts the supplied arguments
if let myNode = result.node? {
if myNode.name? == "Die" {
println("Node is named Die")
}
}
// #3 This does not work either
// error: Type 'String?' does not confrom to protocol '_RawOptionSet'
if result.node?.name? == "Die" {
println("Node is named Die")
}
// #4 This does not work either
// error: 'SCNNode!' does not have a member named 'name'
if let myName = result.node?.name? {
if myName == "Die" {
println("Node is named Die")
}
}
// get its material
let material = result.node!.geometry.firstMaterial;
// highlight it
SCNTransaction.begin()
SCNTransaction.setAnimationDuration(0.5)
// on completion - unhighlight
SCNTransaction.setCompletionBlock() {
SCNTransaction.begin()
SCNTransaction.setAnimationDuration(0.5)
material.emission.contents = NSColor.blackColor()
SCNTransaction.commit()
}
material.emission.contents = NSColor.redColor()
SCNTransaction.commit()
}
super.mouseDown(theEvent)
}
The failures of #2, #3, and #4 are all because of the lack of type. You say:
the error for #2 seems to usually apply to type casting, and I wouldn't think there is any type casting going on here.
However, you declared result to be AnyObject while you're attempting to access it as an SCNNode, so there's certainly some type cast that needs to happen.
I've seen this before as well working with dictionaries. Not only did I get explicit about the type, I also tested the type beforehand:
var item: AnyObject? = nil
item = map["SWLFlexFormat"]
if let value: AnyObject = item {
configuration.formatter = getConfiguredFlexFormatter(configuration, item: value);
}
func getConfiguredFlexFormatter(configuration: LoggerConfiguration, item: AnyObject) -> LogFormatter? {
if let formatString: String = item as? String {
var formatter = FlexFormatter.logFormatterForString(formatString);
return formatter
}
return nil
}