0

Is it possible to use a let property with a similar function parameter to inout when I do't want to change the property itself but that property's properties?

e.g.

let someLine = CAShapeLayer()

func setupLine(inout line:CAShapeLayer, startingPath: CGPath) {
    line.path = startingPath
    line.strokeColor = UIColor.whiteColor().CGColor
    line.fillColor = nil
    line.lineWidth = 1
}

setupLine(&someLine, startingPath: somePath)

Also if there is a better way to set up a bunch of properties the same way when they aren't in a loop that would be helpful too.

richy
  • 2,716
  • 1
  • 33
  • 42

1 Answers1

3

CAShapeLayer is a class and therefore a reference type.

let someLine = CAShapeLayer()

is a constant reference to a CAShapeLayer object. You can simply pass this reference to the function and modify the properties of the referenced object within the function. There is no need for the & operator or inout:

func setupLine(line: CAShapeLayer, startingPath: CGPath) {
    line.path = startingPath
    line.strokeColor = UIColor.whiteColor().CGColor
    line.fillColor = nil
    line.lineWidth = 1
}

let someLine = CAShapeLayer()
setupLine(someLine, startingPath: somePath)

A possible alternative is a convenience initializer

extension CAShapeLayer {
    convenience init(lineWithPath path: CGPath) {
        self.init()
        self.path = path
        self.strokeColor = UIColor.whiteColor().CGColor
        self.fillColor = nil
        self.lineWidth = 1
    }
}

so that the layer can be created as

let someLine = CAShapeLayer(lineWithPath: somePath)

A complete example for your playground. Note that it uses default parameters to make it more versatile:

import UIKit

class ShapedView: UIView{
    override var layer: CALayer {
        let path = UIBezierPath(ovalInRect:CGRect(x:0, y:0, width: self.frame.width, height: self.frame.height)).CGPath
        return CAShapeLayer(lineWithPath: path)
    }
}

extension CAShapeLayer {
    convenience init(lineWithPath path: CGPath, strokeColor:UIColor? = .whiteColor(), fillColor:UIColor? = nil, lineWidth:CGFloat = 1) {
        self.init()
        self.path = path
        if let strokeColor = strokeColor { self.strokeColor = strokeColor.CGColor } else {self.strokeColor = nil}
        if let fillColor   = fillColor   { self.fillColor   = fillColor.CGColor   } else {self.fillColor   = nil}
        self.lineWidth     = lineWidth
    }
}


let view = ShapedView(frame: CGRect(x:0, y:0, width: 100, height: 100))

result with defaults:

screenshot

vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Thank you so much, totally read the docs wong: Class 'instances' are reference types, Functions are reference types, Everything else is a value type. Thank you for the alternative too! – richy Jun 02 '16 at 19:38
  • This is a perfect example to illustrate, how default values for method parameters come in handy: https://gitlab.com/snippets/20356 @Martin R: Feel free to add this code to your answer if you like to. – vikingosegundo Jun 02 '16 at 20:16
  • @vikingosegundo: Good suggestion, thanks, but is too late for today :) Feel free to edit this one or add your own answer! – Martin R Jun 02 '16 at 20:37