How to delete object after it gone outside the scene? - ios

I am trying to delete the objects after it go outside the scene so so i can extenuate ram consumption
I should put the code i have tried but i dont know how to begin so i have nothing to put here sorry
EDIT
Or maybe i should detect if the object inside the view and delete it if not how i can know if the object is inside the view ?

There is a convenient method which checks whether two CGRects intersect each other or not
You can do something like this
if( CGRectIntersectsRect(object.frame, view.frame) ) {
// Don't delete your object
} else {
// Delete your object as it is not in your view
}
I hope this helps :)

You can check in different ways if node is off-screen, and that depends on how you move nodes.
First method :
if (!intersectsNode(yourNode)) {
// node is off-screen
}
To enumerate nodes you can use :
- enumerateChildNodesWithName:usingBlock: To access all nodes in a node tree read this.
Another way is to use actions:
let move = SKAction.moveTo(location: offScreenLocation, duration: 5)
let remove = SKAction.runBlock({yourNode.removeFromParent()})
let sequence = SKAction.sequence([move,remove])
yourNode.runAction(sequence, withKey:"moving") //Use action with key, to cancel the action if needed
Third method would be to use contact detection.

Related

How to pass data between views. When should I use what?

I have a View-Hierarchy like this:
UIViewController (SingleEventViewController)
UIScrollView (EventScrollView)
UIView (contentView)
3xUITableView (SurePeopleTV, MaybePeopleTV, NopePeopleTV (all inherited from the same UITableView)), & all other UI-Elements
The SingleEventViewController stores one Event (passed within the initializer). (All Events are stored in Core-Data).
The three UITableViews are there for displaying the users which are participating (or not or maybe) at the Event. My question is, what are the possibilities to fill the tableViews with the data and what would you recommend in which situation.
Currently I have a property parentVC: SingleEventViewController in all Subviews and get the data like this:
override func loadUsers() {
//class SurePeopleTV
guard let parentController = parentVC else { return }
users = (parentController.thisEvent.eventSureParticipants?.allObjects as! [User])
finishedLoading = true
super.loadUsers()
}
.
func applyDefaultValues() {
//class EventScrollView
guard let parent = parentVC else { return }
titleLabel.text = parent.eventName
}
I'm new to programming but I got a feeling that I should not create a parentVC reference in all of my classes.
An object should not (ideally) know about its parent - if it does they are "tightly coupled". If you change the object's parent, your code may break. In your case, your parent object must have a thisEvent property.
You want your objects to be "loosely coupled", so the object doesn't know about a specific parent object.
In Swift, the usual ways to pass information "back up the chain" is to use the delegate design pattern… https://developer.apple.com/documentation/swift/cocoa_design_patterns or to use closures.
See also https://www.andrewcbancroft.com/2015/04/08/how-delegation-works-a-swift-developer-guide/ for info on delegation
First of all, if you create a reference to the parent ViewController make sure it is weak, otherwise you can run into memory management issues.
Edit: As Ashley Mills said, delegates the way to handle this
The recommended way to pass data between ViewControllers is using something like this
Every time a segue is performed from the view controller this function is in this function is called. This code first checks what identifier the segue has, and if it is the one that you want, you can access a reference to the next view controller and pass data to it.

How to see if two UIImageView's have touched

How can I determine if two UIImageViews's have touched each other? I'm trying to make it realize they've touched each other and then add some code inside if they did.
Hope someone can help, thanks!
I have already tried
if (newArea.frame.intersects(yolo.frame)) {
print("ok")
}
You can check if UIImageViews are overlapping like that:
if img1.bounds.contains(img2.bounds)
{
print("overlapped")
}
A proper way to do this, without depending on the view hierarchy is to use convertRect.
let r1 = newArea.superview.convert(newArea.frame, to: nil)
let r2 = yolo.superview.convert(yolo.frame, to: nil)
if r1.intersects(r2) { stuff() }
This converts both frames to screen coordinates and then checks the intersection, before they were local coordinates of superviews.

How should a UIView access the data model to display the data (using Swift)?

This seems like it should have a simple answer, and probably does, but it's proving harder to find than I expected. As a specific example, let's say that I'm programming a chess game.
It seems like this is something I should be able to do just using CoreGraphics. It seems like using OpenGL or SpriteKit shouldn't be necessary.
I want to have a Board class that models the state of the board. Where should I declare my Board object? My impression is that it should be in the ViewController.
I want to have a view (actually a subview) that displays the current state of the board (by overloading drawRect). It should do this at the beginning, and should be updated when players make moves. How does the view access the data model to display the board state? Does giving the view a reference to the data violate MVC? If not, how would the reference be passed to the view? (I seem to just find lots of links about passing data between two ViewControllers.)
Should it instead be the ViewController "pushing" the data to the view whenever it needs to be drawn? My understanding, though, is that drawRect should not be called directly, and that instead setNeedsDisplay should be called, which will indirectly result in drawRect being called. This being the case, it's hard to see how the data would be passed.
Your code; your design decision. Nothing to comment on here.
You should have your model declaration in ViewController. True. That is how MVC works.
Having a reference of the data in a UIView DOES break MVC. Your view instance will not be independent anymore. Decoupling view and model is one of the main points of MVC and you are probably breaking it with this design.
What can you do about it?
Extending #Paulw11's comment, in your view controller you can declare a method that looks something like this :
func movePiece(somePiece : Piece, toSquare : Square) {
let pieceID = somePiece.id //I am just assuming the models structures
let pieceImageView = self.pieceImageViewFromID(id) //Assume that this method returns the reference of the image view. Assume that I am just working UIKit here.
let fromPoint : CGPoint = somePiece.origin
let toPoint : CGPoint = toSquare.coordinates
self.animateView(pieceImageView, fromPoint:fromPoint, toPoint:toPoint)
}
Note that in this design, the view is not holding any model references; the view controller will take care of setting its state and bring upon relevant animations.
If you are overriding drawRect:, then yes, for it be called, you should call setNeedsDisplay to update the changes. The view controller might call or you can add property observers to redraw itself based on a property change. One example for this could be:
class SillyView : UIView {
var drawPonies : Bool = false {
didSet {
if oldValue != drawPonies {
self.setNeedsDisplay()
}
}
}
override func drawRect(rect: CGRect) {
if drawPonies {
self.drawGoodLookingPony()
} else {
self.drawSomeOtherAnimal()
}
}
func drawGoodLookingPony() {
//Draw a good looking pony here
}
func drawSomeOtherAnimal() {
//Draw Something else
}
}
If your view controller decides to draw ponies all you have to do is, get the reference of the SillyView and set drawPonies to true.
self.sillyView.drawPonies = true
You are not passing your data model here, but important pieces of configuration information that will help the view redraw itself.

Won't update UILabel from Parse data in swift

I am trying to update my UILabel to a String from my Parse database.
My problem is the label will not update my firstnameLabel when I first sign in. But it WILL update, when i sign in (nothing happens), push the stop button in Xcode and then launch it again (still logged in) and then it updates the label.
How can I do this faster??
Here is my code:
var currentUser = PFUser.currentUser()
if currentUser != nil {
var query = PFQuery(className:"_User")
query.getObjectInBackgroundWithId(currentUser.objectId) {
(bruger: PFObject!, error: NSError!) -> Void in
if error == nil && bruger != nil {
var firstName: String = bruger["firstname"] as String
self.usernameLabel.text = firstName
} else {
println("Error")
}
}
} else {
self.performSegueWithIdentifier("goto_login", sender: self)
}
Hope you can help me!
Rather than trying to load the user object again by the id, try just doing a fetch instead.
[currentUser fetchIfNeededInBackgroundWithBlock: ... ];
By trying to load the object, you might be getting a cached version.
I read somewhere that it could be because of the fact that the could was put inside the ViewDidLoad. I tried to put it outside of that and it worked!
It sounds like you put it in the ViewDidLoad method. You should put it in the ViewWillAppear method instead. Here's an example.
1) ViewDidLoad - Whenever I'm adding controls to a view that should appear together with the view, right away, I put it in the ViewDidLoad method. Basically this method is called whenever the view was loaded into memory. So for example, if my view is a form with 3 labels, I would add the labels here; the view will never exist without those forms.
2) ViewWillAppear: I use ViewWillAppear usually just to update the data on the form. So, for the example above, I would use this to actually load the data from my domain into the form. Creation of UIViews is fairly expensive, and you should avoid as much as possible doing that on the ViewWillAppear method, becuase when this gets called, it means that the iPhone is already ready to show the UIView to the user, and anything heavy you do here will impact performance in a very visible manner (like animations being delayed, etc).
3) ViewDidAppear: Finally, I use the ViewDidAppear to start off new threads to things that would take a long time to execute, like for example doing a webservice call to get extra data for the form above.The good thing is that because the view already exists and is being displayed to the user, you can show a nice "Waiting" message to the user while you get the data.

MKMapView with annotations issue

I have MKMapView with many annotations in proper order. And I have button to change map mode:
- (IBAction)userDidPressTrackButton:(id)sender {
if (self.mapView.userTrackingMode == MKUserTrackingModeFollow) {
self.mapView.userTrackingMode = MKUserTrackingModeFollowWithHeading;
return;
}
if (self.mapView.userTrackingMode == MKUserTrackingModeFollowWithHeading) {
self.mapView.userTrackingMode = MKUserTrackingModeNone;
return;
}
if (self.mapView.userTrackingMode == MKUserTrackingModeNone) {
self.mapView.userTrackingMode = MKUserTrackingModeFollow;
}
}
when mode = MKUserTrackingModeFollowWithHeading annotations begin to put themselves in random order. It seems that in this mode mapview begin to redraw itself every second and put all the subview (annotations) in unknown order.
How to cancel changing order of annotations?
The array of annotations that you get back from mapview.annotations is not guaranteed to be in the same order you that added them in. If you are relying on them vein in a special order you are probably doing your viewForAnnotations function wrong. It is given an annotation as a parameter, you use that to determine what view to draw. Usually people make a custom class that implements the MKAnnotation protocol and has some addition variables in which they store the data needed to create the right view. When viewForAnnotations gets called they check if the provided annotation is one of their special class, and if so extract the data, make the view and return it. There is no need to know the order of the annotations array, and it wouldn't do you any good because an MKMapView can and will ask for the annotations in any sequence it likes.
Side note: Why are you writing your own function for toggling the tracking mode? You can just use the official one and it will do it all for you.

Resources