CMutablePointer<NSRange> dead end - cocoa-touch

I'm trying to call lineFragmentRectForGlyphAtIndex method of NSLayoutManager object in Swift. Its description is that:
func lineFragmentRectForGlyphAtIndex(glyphIndex: Int, effectiveRange: CMutablePointer<NSRange>)
But I can't figure it out how am I suppose to call it. According to Apple docs I have to call it like this:
let someRange : NSRange = ...
layoutManager.lineFragmentRectForGlyphAtIndex(0, effectiveRange: &someRange)
That's what documentation says. But I get an error: 'NSRange' is not a subtype of '#lvalue $T5'
What should I do?

Try making it a var instead of a let:
var someRange: NSRange = ...
layoutManager.lineFragmentRectForGlyphAtIndex(0, effectiveRange: &someRange)
Basically: using the & on a var gives you something compatible with a CMutablePointer, but a let is not supposed to be mutable. Hence the type error.
If you want to pass a null pointer, just write nil instead of &someRange (and then of course you don't need to declare the extra var).

Related

Why does indexing need to be referenced? [duplicate]

This question already has answers here:
What is the return type of the indexing operation?
(2 answers)
Closed 2 years ago.
I'm currently learning Rust coming from JavaScript.
My problem is the following:
fn main() {
let name = String::from("Tom");
let sliced = name[..2];
println!("{}, {}", name, sliced);
}
This doesn't work. Saying "doesn't have a size known at compile-time".
To fix this I need to add & the referencing operator.
fn main() {
let name = String::from("Tom");
let sliced = &name[..2];
println!("{}, {}", name, sliced);
}
I know I need to add & before name and & is the referencing operator. But I just don't know why I actually need to do that?
By referencing a variable the reference refers to variable name but does not own it. The original value will not get dropped if my reference gets out of scope. Does that mean that the variable gets out of scope if i do name[...] and the variable gets dropped and because of that i need to create a reference to it to prevent that?
Could somebody explain me that?
I know I need to add & before name and & is the referencing operator. But I just don't know why I actually need to do that.
I understand where the confusion come from, because when you look at index() it returns &Self::Output. So it already returns a reference, what's going on?
It's because the indexing operator is syntactic sugar and uses the Index trait. However, while it uses index() which does return a reference, that is not how it is desugared.
In short x[i] is not translated into x.index(i), but actually to *x.index(i), so the reference is immediately dereferenced. That's how you end up with a str instead of a &str.
let foo = "foo bar"[..3]; // str
// same as
let foo = *"foo bar".index(..3); // str
That's why you need to add the & to get it "back" to a reference.
let foo = &"foo bar"[..3]; // &str
// same as
let foo = &*"foo bar".index(..3); // &str
Alternatively, if you call index() directly, then it isn't implicitly dereferenced of course.
use std::ops::Index;
let foo = "foo bar".index(..3); // &str
Trait std::ops::Index - Rust Documentation:
container[index] is actually syntactic sugar for *container.index(index)
The same applies to IndexMut.

Modifying self in `iter_mut().map(..)`, aka mutable functional collection operations

How do I convert something like this:
let mut a = vec![1, 2, 3, 4i32];
for i in a.iter_mut() {
*i += 1;
}
to a one line operation using map and a closure?
I tried:
a.iter_mut().map(|i| *i + 1).collect::<Vec<i32>>();
The above only works if I reassign it to a. Why is this? Is map getting a copy of a instead of a mutable reference? If so, how can I get a mutable reference?
Your code dereferences the variable (*i) then adds one to it. Nowhere in there does the original value get changed.
The best way to do what you asked is to use Iterator::for_each:
a.iter_mut().for_each(|i| *i += 1);
This gets an iterator of mutable references to the numbers in your vector. For each item, it dereferences the reference and then increments it.
You could use map and collect, but doing so is non-idiomatic and potentially wasteful. This uses map for the side-effect of mutating the original value. The "return value" of assignment is the unit type () - an empty tuple. We use collect::<Vec<()>> to force the Iterator adapter to iterate. This last bit ::<...> is called the turbofish and allows us to provide a type parameter to the collect call, informing it what type to use, as nothing else would constrain the return type.:
let _ = a.iter_mut().map(|i| *i += 1).collect::<Vec<()>>();
You could also use something like Iterator::count, which is lighter than creating a Vec, but still ultimately unneeded:
a.iter_mut().map(|i| *i += 1).count();
As Ry- says, using a for loop is more idiomatic:
for i in &mut a {
*i += 1;
}

Trying to switch a direct integer value with a variable in swift

I'm trying to switch out a direct integer with a variable in swift, but for some reason I'm getting this error and I have no idea. The end goal is to get my currentValue (line 76) to replace the 100's on line 41 - could anyone let me know how I could accomplish this without the error? New to swift and having a hard time (background in objective-c, figured something this simple would not stop me in my tracks!)
Full .swift file here: http://pastebin.com/K6UHkNEv
EDIT:
// these values change the number of squares
let _gameView = CGOLView(gridWidth:100, gridHeight:100)
#IBOutlet weak var tileSizeSlider: UISlider!
#IBAction func sliderValueChanged(sender: UISlider) {
var currentValue = Int(sender.value)
print("\(currentValue)")
}
should work as:
// these values change the number of squares
let _gameView = CGOLView(gridWidth:currentValue, gridHeight:currentValue)
#IBOutlet weak var tileSizeSlider: UISlider!
#IBAction func sliderValueChanged(sender: UISlider) {
var currentValue = Int(sender.value)
print("\(currentValue)")
}
instead I get this error:
Use of unresolved identifier 'currentValue'
and if I try to create custom int's and input them:
var gridWidthValue = 50
var gridHeightValue = 50
like this:
let _gameView = CGOLView(gridWidth:gridWidthValue, gridHeight:gridHeightValue)
I get:
'ViewController.Type' does not have a member named 'gridHeightValue'
Any help would be appreciated - thanks stackoverflow community!
David.
currentValue is a local variable to sliderValueChanged.
Instead you should instantiate _gameView in init. Note however, you still won't be able to use currentValue.
If this is a one off sort of thing, you can always make _gameView an optional and then create it when you have adjusted the slider. This is admittedly a little clumsy.
I am not familiar with Conway's Game of Life, but looking at the code, it seems CGOLView's init does some adjustment based on the grid width and height. The reason I am mentioning this is that you could always change the view's frame size, however, you'd then also need to make some other mods to the tileViews for it to look proper.
As to why gridWidthValue/gridHeightValue is not working. Those are properties defined in an instance. Hence you would need to do somethign like self.gridWithValue to reference it. However, you cannot do that when defining the property such as
let _gameView = CGOLView(gridWidth:gridWidthValue, gridHeight:gridHeightValue)
This is also why instantiating _gameView in init is the way to go.
Your problem is that you cannot access the variable currentValue because it is inside of a function. You have to declare that value outside of the function to be able to use it outside of the function.

MKPolygon using Swift (Missing argument for parameter 'interiorPolygons' in call)

Fellow Devs,
I'm trying to implement a polygon overlay on a mapview as follows:
private func drawOverlayForObject(object: MyStruct) {
if let coordinates: [CLLocationCoordinate2D] = object.geometry?.coordinates {
let polygon = MKPolygon(coordinates: coordinates, count: coordinates.count)
self.mapView.addOverlay(polygon)
}
}
The following error is presented:
Missing argument for parameter 'interiorPolygons' in call
According to the documentation:
Apple Docu:
Mutable Pointers
When a function is declared as taking an UnsafeMutablePointer
argument, it can accept any of the following:
nil, which is passed as a null pointer
An UnsafeMutablePointer value
An in-out expression whose operand is a stored lvalue of type Type, which is passed as the address of the lvalue
An in-out [Type] value, which is passed as a pointer to the start of the array, and lifetime-extended for the duration of the call
Now I think that my approach then would be correct, providing a [CLLocationCoordinate2D] array. Did anyone experience the same problem and found a workaround?
thanks
Ronny
The error you're getting is Swift's cryptic way of saying that it can't find a method which matches your parameters. If you did try passing the interiorPolygons parameter, you'd get an equally confusing:
Extra argument 'interiorPolygons' in call
Your code is pretty close though; you just need a couple of minor changes. In the doc you reference, it says one of the things you can pass is:
An in-out [Type] value, which is passed as a pointer to the start of
the array, and lifetime-extended for the duration of the call
So, it's looking for an in-out parameter. Which is done by passing coordinates prefixed with an &, like so:
MKPolygon(coordinates: &coordinates, count: coordinates.count)
But, in-out parameters can't be constants. From the docs:
You can only pass a variable as the argument for an in-out parameter.
You cannot pass a constant or a literal value as the argument, because
constants and literals cannot be modified.
So, you need to define coordinates with a var first:
if var coordinates: [CLLocationCoordinate2D] = object.geometry?.coordinates
Which makes the entire function look like this:
private func drawOverlayForObject(object: MyStruct) {
if var coordinates: [CLLocationCoordinate2D] = object.geometry?.coordinates {
let polygon = MKPolygon(coordinates: &coordinates, count: coordinates.count)
self.mapView.addOverlay(polygon)
}
}
My final solution by cherry-picking from several tutorials and integrating:
func setPolylineFromPoints(locations:[CLLocation]){
if locations.count == 0 {
return;
}
// while we create the route points, we will also be calculating the bounding box of our route
// so we can easily zoom in on it.
var pt : UnsafeMutablePointer<MKMapPoint>? // Optional
pt = UnsafeMutablePointer.alloc(locations.count)
for idx in 0..<locations.count-1 {
let location = locations[idx]
let point = MKMapPointForCoordinate(location.coordinate);
pt![idx] = point;
}
self.polyline = MKPolyline(points:pt!, count:locations.count-1)
// clear the memory allocated earlier for the points
pt?.destroy()
pt?.dealloc(locations.count)
}

How to use "enumerateChildNodesWithName" with Swift in SpriteKit?

I'm using Swift to make a game in SpriteKit.
In Objective-C I could use the following method:
(void)enumerateChildNodesWithName:(NSString *)name usingBlock:(void (^)(SKNode *node, BOOL *stop))block
to perform actions on that *node, but I can't get this function working in Swift. Basically, I don't know how to reference that node in Swift.
This is the code I'm using, but I'm having trouble with the "usingBlock:" part. I've tried many things for many hours, but have not succeeded. Help please!
func spawnEnemy() -> () {
let enemy = SKSpriteNode(imageNamed: "enemy")
enemy.name = "enemy"
enemy.position = CGPointMake(100, 100)
self.addChild(enemy)
}
func checkCollisions() -> () {
self.enumerateChildNodesWithName("enemy", usingBlock: ((SKNode!, CMutablePointer<ObjCBool>) -> Void)?)
}
For now, don't trust autocomplete to insert the code you need — it drops in signatures from the "header", but a block signature is not the same as the declaration you need when inserting your own closure for a block parameter.
The formal way to write a closure would be to replicate the signature inside braces, adding local parameter names and using the in keyword to mark the start of the closure body:
self.enumerateChildNodesWithName("enemy", usingBlock: {
(node: SKNode!, stop: UnsafeMutablePointer <ObjCBool>) -> Void in
// do something with node or stop
})
But Swift's type inference means you don't have to write that much. Instead, you can just name the parameters, because their type (as well as the closure's return type) is known:
self.enumerateChildNodesWithName("enemy", usingBlock: {
node, stop in
// do something with node or stop
})
You can also use trailing closure syntax:
self.enumerateChildNodesWithName("enemy") {
node, stop in
// do something with node or stop
}
(You can even drop the local parameter names and refer to parameters by position — e.g. $0 for node — but here isn't a great place to do that because it makes your code far less readable. It's best to reserve $0 and friends for closures where it's blindingly obvious what the parameters are, like the closures you use with map and sort.)
See Closures in The Swift Programming Language for further explanation.
Also, because stop is an UnsafeMutablePointer, the syntax for using it is a bit different than in ObjC: set stop.memory = true to break out of enumeration.