I have just finished converting my game using the Entity and Component base architecture (GameplayKit) that apple introduced in iOS9.
I cannot figure out how to check that a current state (GKStateMachine) does not equal a state.
Say I want to check that the currentState is equal to my GameOverState, I would say this
if self.stateMachine.currentState is GameOverState {...
How would I check if the current state does not equal GameOverState, the "... is ..." sytanx is new to me so I am not sure how to call it.
I ran into this issue myself. It doesn't seem like ther is an inverse to is, so the only option I could see was to wrap the conditional statement to invert the boolean. So you would do like the following...
if !(self.stateMachine.currentState is GameOverState) {...
I found it hard to find documentation... so for yours, and others reference:
Documentation on the is operator (section titled "Type-Casting Operators")
Related
I'm learning Swift, using this guide from the official website, in the form of PlayGround.
And I had this error:
I'm so confused... for one thing, this is an introduction guide, for another, I tried all of these and none of them work:
Luckily I finally got this one to work, but I don't know why...
So, I think my question is:
Why there's an error?
What's the original thought behind this part of guide design? I mean, what do they want to show us originally, knowing it's incorrect...
In my working code case, I don't see I can change my code to what's showing in the original guide example of if condition using optional variable. There's no way for this code:
if let nickname {
print("Hey, \(nickname)")
}
to work, right?
Answering your questions:
There's an error because the Xcode version that you are working with has a Swift version <5.7 (Xcode <14) which does not yet support if let shorthand syntax for optional binding when shadowing an existing optional variable (proposed in SE-0345).
For your second image, you are attempting to use optional binding with an non-optional string literal "something", which is, in semantics, pointless, not to mention being syntactically invalid.
The original idea behind this part of the guide is to familiarize you with the idea of dealing with optionals, specifically "optional binding", which is a technique used to work with optional values. You might wanna look into that via the official Swift language guide.
Short story: Think of variables as boxes. In Swift, these boxes can contain a certain type of data (e.g. String, Int, Bool, etc.). All these types that you might be already familiar with are solid data types that guarantee something of that type will be present in the box. But in some cases, you will be exposed to (or need) uncertainties in which you have no idea whether or not a solid piece of data is present within the box. This is when optional values come in--boxes that do not guarantee the presence of values (this box can either have something solid inside or nothing at all, nil).
Usually, we can force unwrap the optional values, but that can cause an error in your program when the box has nothing inside (Swift be like: hey! you promised me that there's gonna be a value inside the box but there's nothing inside, you untruthful creature! what do I do now? *rage halt*). That's why you need an optional binding: you tell Swift to carefully unwrap it and do something with the potential value inside (if it can be safely unwrapped) and do something else when there's nothing inside. The conventional syntax is:
if let aValue = anOptionalValue {
// if there's something inside the box, do something with it
print("haha found ya", aValue)
} else {
// otherwise do something else
print("oh no! empty box...")
}
Swift will now be happy: "at least you warned me that it might be empty inside and told me exactly how to handle it."
You are trying to use the shorthand syntax for optional binding which is only available after Swift 5.7 + Xcode 14. You'll need to get a Xcode 14 beta to use it.
I'm making a game, where i need to define the object in the radius of the explosion in certain radius. Firstly, i was making it through distance between all objects, but i saw that there is GKRTree class in GameplayKit. But after many tries, it doesn't want to work at all. It just returns empty array in any case. I want to know, are GKRTree class broken or what. If yes, are there any other method to do the same stuff as GKRTree in swift or github. Because i dont want to calculate distance, since it can be use a lot of cpu.
Thanks
Edit: I tried what is described in this answer https://stackoverflow.com/a/38655862/11687591, but it dont work. And there are no another solution about this problem. There is some links, where somebody is talking about broken gkrtree and there is no answer. https://www.reddit.com/r/swift/comments/63frk6/does_anyone_have_a_working_example_of_gkrtree/
https://twitter.com/StayOnTheMove/status/1067067053419520000?s=20
And that's all. One things that i've tried that i created 2 circles. One of them is not moving and in one position all the time. Another is moving to my touch position. Second is smaller than the other one. Larger is a little bit transparent so i can see other circle. I also use print() to see all things that happening in the code. And after all of that, even if there is clearly situation where one circle is inside other one, gkrtree.entities method don't work and it returns empty array.
For what it's worth, GamePlayKit.GKRTree is recently failing for me as of Xcode 11.5+. The following line,
import GameKit
class blah {
private var searchTree: GKRTree<RouteSegment>?
public init() {
searchTree = GKRTree.init(maxNumberOfChildren: 3)
}
}
Using a let expression also gets a nil value.
Edit:
The reason it was returning nil is because I didn't have GameplayKit in the linking phase of the project. Duh. By default, all the iOS frameworks are on the search path, which doesn't mean they will be available at runtime. I'm not sure why Apple chose this mechanism. When I traced the assembly code step into the init() function, I found it just returned nil; there must be some stubs in the API.
Solution for me: make sure that GameplayKit is in the linked binaries phase in the project settings.
What's the difference between the following 2 subscripts?
subscript(position: Int) {
get { ... }
}
subscript(position: Int) {
_read { ... }
}
_read is part of the Swift Ownership story that has been in development for a while now. Since read (the likely name once it goes through Swift Evolution) is fairly advanced concept of the language you will probably want to read at least where it is described in the Ownership Manifesto here to get a more full answer than I'll provide here.
It is an alternative to get on subscripts that allows you to yield a value instead of return a value. This is essential for move only types because they cannot be copied (that is their entire purpose) which is what happens when you return a value. By using read it makes it so you could have for example have an Array of move only types and still use the values in it without taking the ownership of them by moving them. The easiest (and not technically correct since it is a coroutine) way to conceptually think about it is that you get a pointer to the object that read yields.
The sibling of read is modify which is currently in the pitch phase of Swift Evolution here so that can also give you some helpful insight into what read is since it is a coroutine as well.
So for now if Xcode gives you a _read to implement simply change it to get since it is a bug since it isn't an official part of the language yet.
What does = do here?
List<Segment> totalSegments = flight.departureFlight.segments;
Do both, totalSegments and flight.departureFlight.segments point to the same memory reference or totalSegments has the same data as flight.departureFlight.segments but points to a different memory location?
My understanding was that the latter should happen since dart is pass by value and not reference. However, a very annoying bug occurred when I added this line below that one:
totalSegments.addAll(flight.returnFlight.segments);
This above line actually modified the flight variable which in turn somehow modified the AsyncSnapshot from the StreamBuilder. Although, I wasn't using the variable anywhere else and not modifying other variables mentioned.
This all happened inside build function of a Stateless Widget. Maybe that has to do something with it.
I tried reading dart documentation for it, but either I couldn't find what I am looking for or the information is simply missing there. Read this too, but according to this, my use case shouldn't happen.
When it comes to objects as in your case, you are assigning a reference to an existing object (memory location) to a new variable. While acting upon that reference, you change the same object.
If this is not what you intend, check out answers related to (deep) copying of the objects
You were mistaken by the fact that Dart passes by value, and not by reference. Actually, it is exactly the opposite: (Almost) everything is always passed by reference (Which is usually a good thing!) Therefore, it is quite logical that because you edited totalSegments your departureflight.segments got edited too. It is a synonym. One of the ways to solve your problem would be:
List<Segment> totalSegments = List();
totalSegments.addAll(flight.departureFlight.segments.toList());
List<Segment> totalSegments = flight.departureFlight.segments;
This expression does the following.
Assigns the value of the expression flight.departureFlight.segments to variable totalSegments.
This and only this and nothing more.
There is no need to know what is really happening, because this is what happens.
P.S.
What value will be obtained as a result of executing the expression flight.departureFlight.segments is another question, because it depends on the implementation of the members of the operands of the expression flight.departureFlight.segments.
When moving some Cocoa code to Cocoa Touch I was disappointed to find that UIBezierPath is missing the "Accessing Elements of a Path" methods:
– elementCount
– elementAtIndex:
– elementAtIndex:associatedPoints:
– removeAllPoints
– setAssociatedPoints:atIndex:
The only way to get at these elements in Cocoa Touch seems to be through CGPathApply. Before I try to recreate this as a subclass or category of UIBezierPath, I was wondering if this had already been done. Does anyone have an idea if something like this is already available?
I made a port on https://github.com/seivan/UIBezierPathPort but it's with Swift.
Has a test suite and documentation.
Works as of Beta 5.
Technically you should be able to use Swift on a Obj-C project.
Let me know how you like it.
I've bumped into the same problem a couple of months ago and couldn't find anything readily available back then. (Truth be told, since going the CGPathApply route wasn't that bad for my needs, I didn't look very hard to be honest).
The applier function is called for every CGPathElement in the CGPath, such an element consists of a CGPathElementType and a C-array of CGPoints.
Since a CGPathElementType is an enum with only five different values
enum CGPathElementType {
kCGPathElementMoveToPoint,
kCGPathElementAddLineToPoint,
kCGPathElementAddQuadCurveToPoint,
kCGPathElementAddCurveToPoint,
kCGPathElementCloseSubpath
};
You don't need to write that much code to do (control)point manipulation / inspection of a path. Having the same interface available would've been nice though.