1

I initially create a CAGradientLayer on my first scene in viewDidLoad. It's inserted like this:

self.view.layer.insertSublayer(myCAGradientLayer, atIndex: 0)

That works fine. But now I need to change the gradient while the app is running. The user will do something on scene 2 and come back to scene 1, where the gradient changes. I build up a new CAGradientLayer and add to the view the same as above.

But using viewWillAppear doesn't work.

Here is an example:

let gLocations: [Float] = [0.0, 1.0]
let gLayer: CAGradientLayer = CAGradientLayer()
gLayer.colors = [UIColor.yellowColor().CGColor, UIColor.greenColor().CGColor]
gLayer.frame = self.view.bounds
gLayer.locations = gLocations
self.view.layer.insertSublayer(gLayer, atIndex: 0)

Add the above to viewWillAppear. Then add it into a several conditionals using different colors. Only the first conditional chosen appears. Any of the other colors in the other conditionals doesn't appear.

I think part of the issue is that I'm always doing:

self.view.layer.insertSublayer(gLayer, atIndex: 0)

Otherwise, the gradient will appear on top of other UI components. I'm using several different gradients and they all use the above code. But I'm guessing they all can't be inserted at index=0.

Is there some other way to change the gradient?

4thSpace
  • 43,672
  • 97
  • 296
  • 475

2 Answers2

1

The ViewWillAppear function should work. It will be called every time the view is about to get active.

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

Update
The first one is only displayed because your CAGradientLayer color is always set to be gLayer.colors = [UIColor.yellowColor().CGColor, UIColor.greenColor().CGColor].

Whenever you want to change the color you need to save this in the memory so that you know this when you enter the view again. This is an alternative solution.

Create a NSUserDefault to save which color you want to show.

// Set - set a new color whenever you want this to be displayed when you show the view next time
// forKey is the unique value to access the object you have saved
NSUserDefaults.standardUserDefaults().setObject("red", forKey: "color"

When you show the view do this:

// Get
let color = NSUserDefaults.standardUserDefaults().stringForKey("color")

if color == "red"{
   gLayer.colors = [UIColor.redColor().CGColor, UIColor.blueColor().CGColor]
}
else if...
Rashwan L
  • 38,237
  • 7
  • 103
  • 107
  • I've added some example code to the OP. Add that several times using conditionals with different colors in viewWillAppear. Add a counter if you want do you can toggle between different conditionals (and colors). – 4thSpace May 07 '16 at 06:44
  • @4thSpace, if I understand your issue right: you have a gradient color, when the user goes to another view and then comes back you want to change the gradient color to another one? – Rashwan L May 07 '16 at 08:52
  • Yes. There are 3 different gradients involved. But like I said, only the first one ever displays. – 4thSpace May 07 '16 at 15:02
  • @4thSpace, check the update and tell me if you need further help. – Rashwan L May 07 '16 at 17:01
  • You are wrong. gradient.colors is always changed depending on which conditional you hit. – 4thSpace May 07 '16 at 17:19
  • Indeed they are but if you have added your code in viewWillAppear you will always have the same color. My idea was to add an if-statement to be able to change colors. – Rashwan L May 07 '16 at 17:24
  • Like I said, I'm using conditionals. So the colors always change but the gradient doesn't update with those changed colors. – 4thSpace May 07 '16 at 17:30
  • I have created test project that changes color every time the view appears. You can download it [here](https://www.dropbox.com/s/ksv1wm5tp2aipci/Test123.zip?dl=0). When I declared `let gLayer: CAGradientLayer = CAGradientLayer()`within `viewWillAppear`it did not change color, but when I declared it as a global it worked. Checkout if this helps you. – Rashwan L May 08 '16 at 06:03
  • 1
    Thanks for the great example. – 4thSpace May 12 '16 at 04:03
1

You can search your layer from sublayers:

myCAGradientLayer.name = "my gradient layer"
        ...

extension UIView {
    func getMyGradient(name:String) -> CAGradientLayer {
        if let layers = self.layer.sublayers {
            for layer in layers {
                if (layer.name == name) {
                    let caGradientLayer = layer as! CAGradientLayer
                    return caGradientLayer
                }
            }
        }
        print("Sorry your gradient doesnt exist in this view..")
        return CAGradientLayer()
    }
}

To retrieve your gradient:

let myCAGradientLayer = self.view.getMyGradient()
if myCAGradientLayer.name == "my gradient layer" {
   // do whatever you want with the same first gradient added 
}

Try to make setNeedsDisplay to your view, to re-render itself if there are problems around display update..

Alessandro Ornano
  • 34,887
  • 11
  • 106
  • 133
  • I'm not sure how this helps. – 4thSpace May 07 '16 at 06:43
  • Sir your have express the problem to how to switch your gradient and the problem how to do in viewWillAppear. So now, after your update, it's more clear, you must change the gradient , the title was not understandable – Alessandro Ornano May 07 '16 at 06:51
  • 1
    I still don't how your code helps. You can see in my sample, I'm always inserting gradients at index=0. So there should ever be only one gradient. I always overwrite. Unless I'm misunderstanding something. – 4thSpace May 07 '16 at 15:21
  • Why you insert everytime your layer? Dont you retrieve from sublayers as explain in my answer? I dont see the needed of re-insert an element just added to your view.I think you must work to one and only one layer, and as explain you will not have more problems. – Alessandro Ornano May 07 '16 at 15:32
  • Once you find the layer you want, how do you get it to display? – 4thSpace May 07 '16 at 16:26
  • I think you must debug self.layer.sublayers and see how many layers you have added. Usually index 0 is the bottom. Look this post http://stackoverflow.com/a/11015144/1894067, if you have insert layer with index 0 and you have another layers involved, you "sendSublayerToBack" and probably you dont see it, sorry for my english – Alessandro Ornano May 07 '16 at 16:55
  • 1
    It looks as though I need to remove any of the layers I have added so that only one of those layers are there at a time. – 4thSpace May 07 '16 at 17:40