iOS Views and Animations: Learning by Stealing · Conclusion | raywenderlich.com


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/267496-ios-views-and-animations-learning-by-stealing/lessons/8

Really enjoyed the course and would love to see more courses like this. Also learnt that colour literals convert to CGColor if it knows that’s the type required, that was new to me. :+1:

2 Likes

Thanks @slater, really glad you enjoyed it!

1 Like

Sam,

Great course - I really liked that you showed a lot more than just how to build the shield animation. Learned a lot of programming techniques. It’s nice to see how you organize your code. I also liked that I could follow along on an iPad. I would also like to see this as a series, especially if you keep teaching more than just the particular animation.

1 Like

Hi @samdavies, usually how do you manage the custom UIView when rotating device? From my understanding, if the device is rotated, we have to remove these sublayers, calculate and add sublayers again in order to make they are in the middle of the view. Am I correct? Thanks for your time.:hugs:

Hi @crafttang

That’s a great question, and one I’m not 100% sure I can remember the answer to. The issue with device rotation is not the rotation itself, but the potential bounds change of the layer itself. On macOS, layers can have a layout manager that can handle this kind of thing for you, but that doesn’t exist on iOS.

CALayer has a property needsDisplayOnBoundsChange, which, if you set it to true, will ensure that the setNeedsDisplay() method gets called on the layer when the bounds change. You can use this method to resize each of the sublayers, and paths to update the size and location of the layer content.

This is a fairly fiddly process, and only needs to happen if the layer hierarchy needs to change size. If it’s just changing position then it should work without any issue.

Alternatively, you could apply an affine transform to the layer to account for the change in size / location, but I wouldn’t necessarily recommend this. It’ll remain rendered at the original resolution, but then be scaled up/down as appropriate.

Sorry that I’ve not given you a definitive answer—partially because there isn’t really one. There may well be other options that I’ve not thought of too. Hope what I’ve written is helpful.

sam

Sam,

I learned so much from this kind of deconstruction. I do hope you will take on some others in the future. I didn’t realize how many skills I actually possessed. You gave me ideas on how to deconstruct other animations that I find interesting.

Keith

1 Like

@fweissi I’m so glad to hear that the course gave you the confidence to try and deconstruct other cool animations—that was precisely the aim! Hopefully we’ll have a chance to do more courses like this—it was fun :slight_smile:

@samdavies Fantastic course. Deconstructing custom controls is a favorite activity, and yet one still that I consider myself fairly amateur at. So this was a wonderful exploration not merely in doing it but in using CALayers. One request; is there a way to add notes to the course material (maybe in the conclusion) that lists the apps you mentioned for converting svgs to code? It’d be an easier step than finding the episode in the list.

Hi @lordandrei

Thanks for your kind words—glad you enjoyed the course. I find it a great way to pull together the knowledge I learn from looking at frameworks individually, and to experiment with different ways of achieving things.

The author notes for this video include links to the tools I mentioned:

https://www.raywenderlich.com/267496-ios-views-and-animations-learning-by-stealing/lessons/5

Do you mean that those notes should all be compiled together in the conclusion as well?

sam

definitely one of the best video courses on the site IMO. I would love to see more courses deconstructing bits of apps. For instance, do a course that introduces some technology like scrollviews and then deconstruct and build the default weather app and build on the initial lessons.

1 Like

Thanks @onceunpopularideas. We’re keen to create more courses like this—having feedback like this is helpful to prioritise the work.

sam

Best tutorial on the site; many more like this please.

I would like to ask for a segment video that explains all the utility methods and properties and how you came up with them and why.

Just having them makes it so much easier, so I feel the ability to know when and how to create them yourself is just as important as the animation and layer syntax.

1 Like

Hi @annemarie1185

Thanks for your kind words. I always use utility functions so as to not distract from the main purpose of the video. However, I now realise that this kind of course would have benefitted from delving into what the helper methods were and how to create them. I’ll bear that in mind next time I work on something like this.

cheers

sam

Coming from C and Obj-C, I find Swift’s syntax to be utterly ludicrous and overly complicated with an excessive amount of seemingly verbose symbols rather than words.

Looking through your helper methods I found this line.

Can you please explain the syntax and why / how you constructed this line and what it’s doing please?

public typealias StateChange = ((State) -> ())

I get what ‘typealias’ is for the but the syntax at the end to me, trying to learn the language looks like the ‘designer’ of Swift is trolling us.

Thank you

Is it worth ‘adding’ a new segment to the course going over why you needed them (with drawings maybe?) and how you created them and the syntax of the commands broken down?

Hi. Sorry. Another quick question.

I’m playing around with the code from the final coursework materials download.

I’m playing with resizing the UIView so I can make it ‘dynamically’ fit whatever layout is needed, and there seems to be an issue with the helper method

pathForCircleInRect

Because if I say drop the size of the whole view to 150 x 150 in the line:

let button = ButtonView(frame: CGRect(x: 0, y: 0, width: 150, height: 150 / aspectRatio))

Then the button is no longer centred in the view but it’s more towards the top of the view.

However scaling it up to 600 x 600 works fine.

Could you please help work out what’s going wrong?

Thanks

Hi @annemarie1185

Swift Closure Syntax

As with many things, I’m sure that Swift will feel less ridiculous as you become more familiar with it. At the end of the day it’s just another programming language, and they’re all much of a muchness :wink:

In the typealias line:

public typealias StateChange = ((State) -> ())

We’re effectively defining a type with a function signature—i.e. a variable of type StateChange is a closure. You can determine this from the fact that there is an -> in there. The left-hand side of the arrow specifies the types of the closure arguments, whilst the right-hand side shows the return type.

In this case, the closure would take an argument of type State and return nothing—i.e. void.

You could write it as the following instead:

public typealias StateChange = (State) -> Void

I guess it’s roughly equivalent to the following in C:

typedef void (*StateChange)(State state);

(My C is rusty at best, so that’s quite probably incorrect).

Path for Circle in Rect

I’m not entirely sure of the issue here. If I resize the button view as you explained, then it just makes the button smaller:

image

I am aware that there is a problem if the button view is not square, which is definitely not intentional:

This is because I didn’t test it in non-square shapes. The easiest way to handle that would be to ensure that ButtonView can only ever be square. I’d probably do this by putting another view inside ButtonView that contains all the mechanics of the button, and is forced to be the largest square inside the container view. Either that or put some additional effort into thinking about sizing each of the individual components.

Sorry not to be able to give you a definitive answer here—hope it helps.

sam

1 Like

Sam

THANK YOU SO VERY MUCH for replying and taking the time to break down that syntax.

I LOVE this version - so much clearer and less verbose:

public typealias StateChange = (State) -> Void

If that’s legal in Swift why isn’t it preferred? I have no idea.

As for the shield thing, I have an image, but I can’t post it here in the forums, but when it’s at 150x150, the circle is almost at the top of the shield rather than almost centred with your usual examples. Yes, because it’s a square that’s probably what’s throwing it off. I’ll look at that again and see if I can fix that in the helper class so it works correctly regardless.

Thank you again for this tutorial and for taking the time to reply. Just conversing with you about this has been worth the subscription costs.

1 Like

Hi @annemarie1185

No problem—glad it makes more sense now.

It’s quite possible that the syntax I chose isn’t preferred by anybody other than me at that point in time. The extra ( and ) are there to make it clearer to me exactly where to parse it, but completely unnecessary. As for () instead of Void—it fits in with the pattern of “returning nothing”. Arbitrary choice really I guess.

Good luck with fixing the other issues :slight_smile:

sam