0

I am trying to use a Swift function to place a circle in the centre of a view so it is always on centre regardless of screen size. I can draw the circle at a point defined by a set of arbitrary x and y values but I need the function to supply these values instead.

I have created a function called screenCentre() to read and return two parameters that are the centre coordinates. However Xcode warns that the

“Result of call to screenCentre() is unused”

I’ve worked through Swift tutorials on functions and closures and understand how to pass arguments to a function but I am still not clear how to use values returned by this function.

Here is my code:

import UIKit

class ViewController: UIViewController {

   let radius = CGFloat(20)
   let fillColour  = UIColor.clear.cgColor
   let lineColour  = UIColor.red.cgColor
   let lineWidth  = 1.0

   var x: CGFloat?
   var y: CGFloat?

   override func viewDidLoad() {
       super.viewDidLoad()

       screenCentre()
       print(screenCentre())

      // arbitrary set of coordinates used to draw circle

      circle(x: 150, y: 170)

   }

   func screenCentre() -> (x: CGFloat, y: CGFloat)
   {
      return (self.view.bounds.size.width / 2, self.view.bounds.size.height / 2)
   }

   func circle(x: CGFloat, y: CGFloat) {
       let circlePath = UIBezierPath(arcCenter: CGPoint(x: x,y: y), radius: radius, startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)

       let shapeLayer          = CAShapeLayer()
       shapeLayer.path         = circlePath.cgPath

       shapeLayer.fillColor    = fillColour
       shapeLayer.strokeColor  = lineColour
       shapeLayer.lineWidth    = CGFloat(lineWidth)

       view.layer.addSublayer(shapeLayer)
   }
}

UPDATE

By declaring a constant I am able to use values returned by this function. Sam_M and Kevin Bunarjo answered the question as asked.

However Daniel T and PEEJWEEJ both identified a related problem I hadn’t recognised. Once I applied fixits the extension solution offered by Daniel T now gives me a way to rotate the screen around the centre. So I marked it as the best answer. Thanks to everyone who contributed.

Here is the updated code.

    let centre = UIScreen.main.centre
    circle(x: centre.x, y: centre.y)
}

func screenCentre() -> CGPoint {
    return CGPoint(x: UIScreen.main.bounds.midX, y: UIScreen.main.bounds.midY)
}
Greg
  • 1,750
  • 2
  • 29
  • 56

5 Answers5

2

Your screenCentre() function won't work in viewDidLoad because the view is not yet sized to the screen, therefore its center is not in the middle of the screen.

Use this instead:

func screenCentre() -> CGPoint {
    return CGPoint(x: UIScreen.mainScreen().bounds.midX, y: UIScreen.mainScreen().bounds.midY)
}

Note that I am using a CGPoint instead of a tuple, but the effect is the same. Also, the above function doesn't need to be in your view controller or any other class since it doesn't reference self. It can be a global function.

Since Swift style guidelines encourage making methods over global functions, you might prefer to put the function in an extension like this:

extension UIScreen {
    var centre: CGPoint {
        return CGPoint(x: bounds.midX, y: bounds.midY)
    }
}

Which can be called like this:

let centre = UIScreen.mainScreen().centre
print(centre)
Daniel T.
  • 32,821
  • 6
  • 50
  • 72
  • If there are several views that need circles, make them all subclasses of your circle view, or add a circle view to each of them. – GetSwifty Oct 14 '16 at 16:52
1

In your ViewDidLoad method, you are only calling the method, but not storing the returned values. All you need to do to fix this is to create a variable and assign it to the call of your function.

Example:

let center = screenCentre()
print(center)

Now, the variable center will contain the coordinates of your screen's center. And in subsequent code, you can use center like you would with any other variable.

kbunarjo
  • 1,277
  • 2
  • 11
  • 27
1

Your screenCenter function returns a tuple containing two CGFloat values. These values are labeled x and y so you can access them by name when querying the function’s return value.

override func viewDidLoad() {
    super.viewDidLoad()

    let center = screenCentre()
    //center.x contains the x value returned from screenCenter
    //center.y contains the y value returned from screenCenter

    circle(x: center.x , y: center.y)
}
Swifty
  • 3,730
  • 1
  • 18
  • 23
0

One thing you can do is use the _ to discard the return value from the function if you have no need for the value being return.

let _ = screenCentre()
Marlon Monroy
  • 144
  • 1
  • 4
  • 1
    You missed an `=`. Also, this solution is fully correct but doesn't make any sense to do if your function doesn't mutate anything like this `screenCentre` function doesn't. – Connor Neville Oct 09 '16 at 23:18
0

First of all, UIViews have a center attribute, so you don't need to calculate it.

Second, the behavior may be inconsistent if changing it with viewDidLoad, and won't react to any changes to size/rotation.

I would recommend making a subClass of UIView that manages drawing the circle and doing something like this:

class ViewController: UIViewController {

    var circle: CircleView?

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        centerCircle()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        centerCircle()
    }

    func centerCircle() {
        circle?.center = self.view.center
    }
}
GetSwifty
  • 7,568
  • 1
  • 29
  • 46
  • thanks. See my edit. I am still trying this approach as I have several UIViews that need circles. – Greg Oct 10 '16 at 21:43
  • I finally worked out how to make a subClass of UIView and have a new question [http://stackoverflow.com/questions/40059009/why-does-uiview-not-stay-on-centre-while-it-rotates] – Greg Oct 15 '16 at 12:45
  • I finally created a subClass of UIView that draws buttons arranged in a circle and it almost works [ see http://stackoverflow.com/questions/40558939/how-do-i-rotate-a-group-of-buttons-programmatically-in-swift]. – Greg Nov 12 '16 at 02:35