Swift: Size vs bounds vs frame [duplicate] - ios

This question already has answers here:
Cocoa: What's the difference between the frame and the bounds?
(12 answers)
Closed 5 years ago.
I'm making a simple game in Swift, and I was trying to find a good way to get the center of the game scene. At the moment I'm doing this:
CGPoint(x: size.width / 2, y: size.height / 2)
Seems simple enough. However, when checking, I found these four things also exist as part of the GameScene class:
self.frame
self.size
self.view.bounds
self.view.frame
I'm quite confused. Which one am I supposed to use? They all look the same to me. What's the difference?

The frame is the location in the views superview, so if it's a 100x100 square at 100 pixels from the left and the top its {100, 100, 100 100}.
The bounds is the rect, but ignoring the position in a superview. A bound-rects origin will always be 0,0. So the view in the example above would be {0,0,100,100}
Size is is just the same as bounds.size, {100,100}

Related

Mapbox default compassView when repositioned gives weird outcome

I have a situation where I have to reposition the map box compass view to a different location. The compassView is now rotating when I rotate the map taking some other point as its(compassView) axis and gives me a weird outcome. Screenshot is attached, the black mapBox default compass icon is rotating, refer the screenshots. Is this a MapBox sdk bug? if so, are there any work around? And tweaks? I am confused. Expert advices needed. Thanks in advance.
Hey I found another method where I will get the same result of the compass in the map box. I've placed a button and then
func mapViewRegionIsChanging(_ mapView: MGLMapView) {
compassViewUpdate(direction: Double(bearing))
inside compassViewUpdate method
func compassViewUpdate(direction:Double) {
self.compassButton.transform = CGAffineTransform(rotationAngle: CGFloat(-direction.degreesToRadians))
}
#Sarang here is a work around. Happy coding.
A built-in approach that's available in the Mapbox iOS SDK. Using these methods
to move the compass will avoid the distortion caused by .frame and .center
changes.
Generally Changing the CompassView Location
mapView.compassViewPosition = .bottomLeft
mapView.compassViewPosition = .bottomRight
mapView.compassViewPosition = .topLeft
mapView.compassViewPosition = .topRight
Use compassViewPosition to get the compass generally where you want it on the
screen.
Fine Tuning the CompassView Location
mapView.compassViewMargins = CGPoint(x: 64, y: 16)
Default x, y = 8, 8
The margin is to the outside/along the border of the view. So for .bottomLeft
the compass view will move 56 right and 8 up versus .topRight where the
compass will move 56 left and 8 down.
try changing the compassView.center instead of changing its origin or frame. I am guessing it has approximately 40 pixels width x height, and I changed to bottom left using the following:
let centerCalc = CGRect(x: 5, y: frame.height - 45, width: 40, height: 40)
compassView.center = CGPoint(x: centerCalc.midX, y: centerCalc.midY)
It should work!

Get origin of image after aspect fit [duplicate]

This question already has answers here:
How to know the image size after applying aspect fit for the image in an UIImageView
(20 answers)
Closed 6 years ago.
I want to get the CGRect value of the image after it is being "aspect fitted" onto the screen. All the solutions I found online only gives the CGSize. However, I want the origin so that I can draw a canvas on top of that image to perform drawing only on top of the image rather than the whole imageView.
Thanks,
let rect = CGRectIntegral(AVMakeRectWithAspectRatioInsideRect(imageView.image!.size, imageView.bounds))
Try to execute below code
var img=UIImageView(frame: CGRectMake(50, 50, 100, 100))
var imageOrigin=img.frame.origin //This will give you image x and y position
print(img.frame.origin) // this will print (50.0, 50.0)

Getting actual view size in Swift / IOS

Even after reading several posts in frame vs view I still cannot get this working. I open Xcode (7.3), create a new game project for IOS. On the default scene file, right after addChild, I add the following code:
print(self.view!.bounds.width)
print(self.view!.bounds.height)
print(self.frame.size.width)
print(self.frame.size.height)
print(UIScreen.mainScreen().bounds.size.width)
print(UIScreen.mainScreen().bounds.size.height)
I get following results when I run it for iPhone 6s:
667.0
375.0
1024.0
768.0
667.0
375.0
I can guess that first two numbers are Retina Pixel size at x2. I am trying to understand why frame size reports 1024x768 ?
Then I add following code to resize a simple background image to fill the screen:
self.anchorPoint = CGPointMake(0.5,0.5)
let theTexture = SKTexture(imageNamed: "intro_screen_phone")
let theSizeFromBounds = CGSizeMake(self.view!.bounds.width, self.view!.bounds.height)
let theImage = SKSpriteNode(texture: theTexture, color: SKColor.clearColor(), size: theSizeFromBounds)
I get an image smaller than the screen size. Image is displayed even smaller if I choose landscape mode.
I tried multiplying bounds width/height with two, hoping to get actual screen size but then the image gets too big. I also tried frame size which makes the image slightly bigger than the screen.
Main reason for my confusion, besides lack of knowledge is the fact that I've seen this exact example on a lesson working perfectly. Either I am missing something obvious or ?
The frame is given as 1024x768 because it is defined in points, not pixels.
If you want your scene to be the same size as your screen, before the scene is presented in your GameViewController, before:
skView.presentScene(scene)
use this:
scene.size = self.view.frame.size
which will make the scene the exact size of the screen.
Then you could easily make an image fill the scene like so:
func addBackground() {
let bgTexture = SKTexture(imageNamed: "NAME")
let bgSprite = SKSpriteNode(texture: bgTexture, color: SKColor.clearColor(), size: scene.size)
bgSprite.anchorPoint = CGPoint(x: 0, y: 0)
bgSprite.position = self.frame.origin
self.addChild(bgSprite)
}
Also, you may want to read up on the difference between a view's bounds and it's frame.

Coordinates for Center of Screen for iPhone 6S [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I would like to position an object in the center of my UIViewController. I have tried to use frame.width/2 and frame.height/2, for example, with a UIView:
let newView = UIView(frame: CGRect(x: frame.width/2, y: frame.height/2, width: 100, height: 100))
That method did not position the object in the center of the view as I expected. How can I position the object to the center of the view using the x-y coordinates of an iPhone 6s?
To get the actual center coordinates of the window, I'd use:
let centerX = UIScreen.mainScreen().bounds.maxX / 2
let centerY = UIScreen.mainScreen().bounds.maxY / 2
But otherwise, in whichever ViewController you're working, the center of the view is a CGPoint, the position of which can be found with:
view.center
If you just want the x and y coordinates you can get them by just adding a .x or .y after view.center.

SpriteKit: What's up with the coordinate system?

I'm teaching myself how to do SpriteKit programming by coding up a simple game that requires that I lay out a square "game field" on the left side of a landscape-oriented scene. I'm just using the stock 1024x768 view you get when creating a new SpriteKit "Game" project in XCode - nothing fancy. When I set up the game field in didMoveToView(), however, I'm finding the coordinate system to be a little weird. First of all, I expected I would have to place the board at (0, 0) for it to appear in the lower-left. Not so -- it turns out the game board has to be bumped up about 96 pixels in the y direction to work. So I end up with this weird code:
let gameFieldOrigin = CGPoint(x:0, y:96) // ???
let gameFieldSize = CGSize(width:560, height: 560)
let gameField = CGRect(origin: gameFieldOrigin, size: gameFieldSize)
gameBorder = SKShapeNode(rect: gameField)
gameBorder.strokeColor = UIColor.redColor()
gameBorder.lineWidth = 0.1
self.addChild(gameBorder) // "self" is the SKScene subclass GameScene
Furthermore, when I add a child to it (a ball that bounces inside the field), I assumed I would just use relative coordinates to place it in the center. However, I ended up having to use "absolute" coordinate and I had to offset the y-coordinate by 96 again.
Another thing I noticed is when I called touch.locationInNode(gameBorder), the coordinates were again not relative to the border, and start at (0, 96) at the bottom of the border instead of (0, 0) as I would have guessed.
So what am I missing here? Am I misunderstanding something fundamental about how coordinates work?
[PS: I wanted to add the tag "SpriteKit" to this question, but I don't have enough rep. :/]
You want to reference the whole screen as a coordinate system, but you're actually setting all the things on a scene loading from GameScene.sks. The right way to do is modify one line in your GameViewController.swift in order to set your scene size same as the screen size. Initialize scene size like this instead of unarchiving from .sks file:
let scene = GameScene(size: view.bounds.size)
Don't forget to remove the if-statement as well because we don't need it any more. In this way, the (0, 0) is at the lower-left corner.
To put something, e.g. aNode, in the center of the scene, you can set its position like:
aNode.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame));

Resources