Stanford – Developing iOS 9 Apps with Swift – 4. Views

Just another WordPress site

Stanford – Developing iOS 9 Apps with Swift – 4. Views

[MUSIC] Stanford University. Okay, well welcome to Lecture four of Stanford’s CS193P, spring of 2016. Today our topic is views. Okay, views are the rectangular areas on screen that we draw in. Its also the places where we handle multi-touch, we’ll be talking about that next week. So today is, it’s all about the drawing side and I have, of course, have a demo where we’re gonna draw a custom view, okay? So let’s talk about views. The view is that rectangular area, as I said. It defines a coordinate space, okay? So, any time you’re drawing or handling input, or whatever, you need a coordinate space to be defined for you. And, use that space to draw and to handle touch events. This kind of view setup is hierarchical, as you might imagine, so, you can imagine that you have some view, like maybe this is the view that contains your entire UI for an MVC And then, you’ve got some sub views maybe they’re buttons, or whatever, and they might be inside a view, like let’s say a stack view or something like that And, maybe those are in another view, okay? So, you can see how these things are hierarchical, right? You’re building your views in a hierarchy, a view hierarchy we call it, okay? Now, these views can overlap, obviously And, they also, even if you have a view inside a view, so a view, let’s say in this view right here, if you had another view inside it, it could actually extend outside the bounds of its parent, that’s legal. And, you can set a switch in the view whether it’s going to clip, and only show this part, or whether it’ll allow this thing to draw outside of its parent, okay? So, that’s how we build our user interface, is by kinda grouping these things together You’re totally familiar with that in the calculator And, when you build something like this, every view ends up having a single super view, right? That’s the view that it’s inside. And, any given view could have any number of sub-views, okay? Like the stack views could have any number of things stacked inside of whatever The sub-views, you can find them for a view by looking at this VAR, the CUI view VAR called sub-views You see it’s an array of UI view there, and, we’ll talk a little later about the order of those sub-views matters And that’s it basically, okay? That’s how we represent this new hierarchy There is a UI window in iOS, but it almost doesn’t matter, okay? You’re never gonna interact with it There’s always only one, per app. Actually, you could have more than one if you had like an external screen, okay? Like you were doing, what do we call, the, the screen cast, it’s not coming to me, where you can, have a second screen I can’t think of it but, like on Apple TV, you could have a second screen for your device. Whatever, so then you might have two UI windows, but it wouldn’t matter cuz you’re almost never gonna create one or send a message to one or whatever. So, it’s all about views, it’s all about this view hierarchy that we’re gonna build okay, in iOS. It’s unlike on the Mac, where of course the Mac you’ve got windows, right, separate windows. You don’t really have that, in iOS, not enough room really to do that. This hierarchy is most often constructed in Xcode graphically Like you did with the calculator, okay? But, you can build this hierarchy in code The two methods are add subview, and remove from super view, that’s putting them in and taking them out., Notice that add subview is sent to the future super view of the view saying, hey, or add this sub view to yourself. Remove from subview is actually sent to the view you want to remove, okay? So, remove from subview from super view rather is kind of like remove yourself from your super view, okay? Where does the view hierarchy start? It starts right at the top, in that MVC that we see in the storyboard, there’s a view that fills that whole space There is a pointer from your view controller to that top level view, okay? That pointer is called view. So, if you look at view controller, right, everyone knows what view controller is? That’s where you put a lot of your code in the calculator, right? Where you wired up all your outlets and actions That class, view Controller has a var called view You haven’t used it yet. But, it is a pointer to the top level UI View. Okay, and that’s an important view to have a pointer to because you’re gonna be adding subviews to it, etcetera, especially if you’re doing it programmatically You really need this var so you can call add subview on it and put some things in there And, this view is automatically hooked up for you, in your storyboard. So, you don’t have to do anything It’s just automatically hooked up, okay? And, this top level view is the view whose bounds will change, for example, when you rotate your device, right? The bounds go from being tall and thin, to being short and

wide, okay? That’s the bounds of this top level view Now, when you change the bounds of this top over view, if you have constrains, like if you put it in the calculator where we tied the stack view to the edges? When those edges change, of course, the stack view gets pulled around and stretched And, the stack view knows how to resize and distribute the things inside of it That’s part of what the stack view does. That’s pretty much all it does actually So that’s why rotating, changing the bounds of this top view cause a ripple effect where everything re-positions inside, okay? Now, let’s talk a little bit about initializing a UI View, okay? As always we want to try to avoid doing an initializer if we can just get away with just saying equals whatever, but if you have to have an initializer because you just feel like you just can’t initialize a VAR somehow else. Then you have to be careful with UIView because it actually has two important initializers, okay? One of them is required, that’s the second one, init with coder. That init is the init that’s used to create the UIView when it’s coming out of a storyboard, okay? So, if you built this view by dragging it out into your storyboard, when the storyboard gets reconstituted at run time, then this is the init that’s gonna get controlled, init with coder The init with frame, that’s the init that you’re going to call if you create a view in code, okay? And, that frame that you’re doing, specifying is the frame of this view in its super view, in other words where it’s going to be, where this view is going to be. And, it is legal to, to just do init with no arguments. That’s gonna essentially be ZeroRect You’re just gonna put it, like, up here in the left-hand corner really, really small You can set a frame later to move it. Anyway, since you have two of these things, and one of them is required, the second one, you’re gonna end up implementing both, okay? Because you’re gonna want your views to be able to work from storyboards or you want people to be able to, you know, instantiate them from code, okay? So, I recommend putting, all your initialization code in something like a set up function here. And then, override both of these two and call set up from both of them That way they’ll both be doing exactly the same set up, right? Makes sense, kinda obvious. But, I just wanna make sure you know you gotta do both of these [COUGH] All right, another initialization mechanism that you can do for UI view, but only works for views coming out of storyboards, is to put your code in this method awakeFromNib() Okay, awakeFromNib() is actually called on any object that comes out of a storyboard, okay? But, not called at all in you call an object in code. And, so, you can, you know, put same kind of set up stuff that you would put in the other one as long as you’re fine with your view only working when it’s coming from a storyboard, okay? All right. So, now let’s talk about the drawing Okay, I’ve got this UI view and I wanna draw Well, before I can show you how to draw, you know, draw something inside of these Your custom view, and I need to talk about some types, some data types, okay, the first one here is CG float. So, we don’t use doubles or float, I haven’t really talked about the float struct in Swift, but it’s just like double It’s just, float is single precision, and double is double precisions, that’s why it’s called a double But we don’t use floats or doubles when we’re drawing, we use this special struct called CGFloat, okay? And that means that sometimes, you’re going to be doing calculations in doubles and then you’re gonna want to draw, with the result you’re gonna have to convert it to a CGFloat. By doing CGFloat called as initializer, there’s an initializer for CGFloat that takes a double luckily and the other takes a float, okay? So always using CGFloats and you’ll run into some trouble here and there, because you’re trying to pass doubles into API that takes CGFloats, cuz it’s drawing API, okay? There’s a couple of other obvious structs There’s CGPoint that just has two bars in it, one is the x, and one is the y, tight? That represents a point and then a CGSize, same thing, a struct with two things, a width and a height. Okay, those are easy. Then there’s CGRect CGRect gets it’s own slide because even though it’s obvious, it has an origin which is a CGPoint and a size which is a size, right, it’s a rectangle, has an origin and a size. It also has a lot of methods on it, okay? Cool methods you can use or vars and methods like finding the minimum x value of this rectangle or the mid y point of this thing or even intersect this with another rectangle and give me the intersecting part like this slashed area here, okay? Or this one intersects which says does this rect intersect this other rect. You can imagine there are a couple of dozen of these kinds of utility methods So you want to definitely get to know them so you don’t end up writing these methods yourself when you want to intersect two rects or whatever, okay? So those

are the main types that we are going to use when we draw. So you’re gonna be familiar with those types. All right, let’s talk about the coordinate system we’re gonna draw in in our view, okay? The origin is in the upper left, upper left, okay. It’s not lower left like Cartesian coordinates or like the Mac okay, when you draw on the Mac, if you’re building a Mac app, it’s in the upper left That means increasing y means you’re moving down the screen, okay. So if you look at this point I created up here, 535, notice it’s 500 over in x, but only 35 down in y That’s why it’s way over on that side there, okay. The points that we are talking about here in drawing when I mention all of this, or the unit if you will are called points, okay. Now a point is not a pixel. Some iOS devices are extremely high resolution like the IPhone Plus, the IPhone 6 Plus, very, very high resolution. It has three pixels per point, okay Some of the other devices have two pixels per point, some have one. Now yo’re always drawing in points Usually, you do’t care too much about the pixels If you have a lot of pixels, it just means the lines that you draw are gonna look really smooth or the images that you have are gonna be really detailed You are gonna be able to use a lot of image data to draw them, okay? But if you do care, and actually in assignment three, you are gonna care, so pay attention. If you do care, you can find out by asking a UIView what is your content scale factor? That’s basically how many pixels per point okay The boundaries where you draw in, so this is super important and this is where a lot of confusion comes in, that’s why I spend a lot of time in this even though it’s very simple but people just get these things messed up Let’s talk about the rectangle in which you draw, okay, cuz you’re gonna draw inside a rectangle. When you are drawing, you’re using this var in your UI view It’s called bounds. It’s a CGRect. That is the rectangle in which you’re drawing in your own coordinate system, in the coordinate system you’re drawing in, okay. So any time you’re writing drawing code, you’re using this, okay? There’s another thing called frame, which is also CGRect, which people confuse between these two. But frame is completely different. It has a completely different purpose, and it’s in a completely different coordinate system Okay, so if try to use frame instead of bounds, it might work in certain circumstances but then be messed up in others So what’s frame about? Frame is about where your view is in it’s super view? Frame is a rectangle, a CG rect that completely encloses you in your super views coordinate system. Okay, so when I wanna put some view somewhere, I have to specify where in it’s SuperView it goes I do that by specifying it’s frame. And of course, since I’m talking about putting it into SuperView, that’s in the SuperView’s coordinate system, not in the drawing, coordinate system on the inside there, okay? Similarly, centre, a lot of people think, great, that’s the center of my view But it’s not, okay? That’s the centre of your view in your SuperViews coordinate system. So that’s positioning you, okay? Frame and center are positioning you They have nothing to do with your drawing When you’re drawing, you’re using your bounds, okay? So I do not want to see you using frame inside your drawing code, or centre. Got it? And I’ll emphasize this again in the demo. All right, so one thing about frame and centre, you might think that the size and width are going to be the same for the frame and centre, but they’re not because views can be rotated If you had a rotated view like view B, okay, it’s bounds is 200 wide by 250 high you see that, but look at his frame 320 by 320 why? Because this is the smallest rectangle in the super views coordinate system that will completely contain this rotated view, okay? So the width and height are not the same, okay? This is the frame 320 by 320, this is the bounds. When you’re drawing in B, you don’t even know you’re rotated, so you want to make sure that you’re using this coordinate system right here, bounds, okay? All right, creating views, okay, most of the time you’re creating views in your story board by dragging them out Now if you have a custom view that’s drawing something custom like today we’re gonna do a thing where we draw a face view, it’s gonna be a view Okay Looks like this, got a couple eyes. Smiley face, okay? I’m drawing, it’s got a skull there. When I’m drawing this, there’s no face view in the object palate, right? I can’t drag that out into my story board So, how do I get my face view to appear somewhere in my story board Well, the answer is, I’m going to drag out a generic view, okay, a generic UI view, unsubclassed UI view, and then

I’m going to change it, edit it in this identity inspector, which I’ll show you in the demo to change the class of it, so it’s a subclass of UI view. And it’s in that subclass of UI view that I’m gonna put all my drawing code, all my face drawing code, okay? Now on rare occasion, you will create a view in code, okay. You do that just by doing, calling UIView’s little constructor here You’re gonna use the one with frame, not the one with coder, okay. You can also do UIView with no arguments, that means the tiny little UIView You’ll have to set it’s frame otherwise So here’s what it looks like to create a view in code Here I just created a rectangle which is 20/20, 150 So that’s like 20, 20, 150 So this is this rectangle right about there and the, so then I’m creating a view. This view happens to be a UI label UI label is just a sub class UI view So it’ s UI button, so it’s UI stack view. All of these things are just sub classes of UI view. So I’m creating a sub code view using that frame thing using that frame thing, okay? I’m even setting the elabels text, all right? Then I’m going to say view, let’s say this code is in the view controller, say view.addsubvie{labe} Then all the sudden it’s gonna appear here, okay? Here’s that 20/20 And it’s 100 by 50, okay? That’s it. Very simple to add views with code, okay? Add subview. All right, custom view. So why do I want to create my own custom view subclass? Obviously you want to have a smiley face, okay? So you need to create your own custom one to do that. And you might have some pinches or swipes or something, which we’ll do next week. For your face, you need a custom view to do those things, okay? So let’s talk about the drawing end of that today. How do I draw? It’s really easy. You’re just gonna subclass UI view and you’re gonna override this one method, drawRect, okay? DrawRect takes one argument, which is an optimization only, which is what part of the view the system wants you to draw It might want you to draw the whole thing But maybe it just wants you to draw the eyes, okay? Now you can ignore that and draw the whole thing anyway, and it will work. Or if you can efficiently just draw the eyes, then you might decide to just draw the eyes, okay. But this argument right here is purely an optimization It can be ignored if you want Okay, never call this method If you ever call this method in the code you submit for homework, I’ll be personally going over and slapping you on the wrist, okay? Because this, this is never, ever, under any circumstances, no exceptions are you calling this thing The system calls drawRect You never call it. So, how do you get your face to draw? If you want it drawn Let’s say the eye is closed And you want to draw the face so the eyes are closed. Well you call this method here set needs display on your view And that tells the system, hey this view needs to be redrawn. And the view at some point in the future when it’s appropriate, will call your drawRect, okay? Now why is it done this way? Well if you think about it Your view lives in an environment where there might be subviews and you’re in SuperView and they’re overlapping There’s all kinds of things happening. And you can’t just run along and redraw one of those things okay they might be transparent, seeing through to each other, the system has to manage that okay and there’s also performance reasons to do it You might change, close the eyes, start frowning, etc, the nose starts running I don’t know and all those things are happening all at once, we don’t wanna redraw it every single time. The, one of them changes. You wanna wait until all of them have changed and then draw once your new face, okay? So the system is the one that decides. Now this is setNeedsDisplay() in Rect Just lets you set this little rectangle right here So this is an optimized version, an optimized version of setNeedsDisplay() in Rect Maybe just call it with the i’s. Okay, if you know that only the eyes have changed But this is how you get a view to redraw, okay? All right, so how do I implement this drawRect thing, okay? I got this drawRect thing, how do I implement it? There’s two ways, really There is a, kind of a C-like, a non-object oriented In Swift, it’s just functions, global functions way of doing it called Core Graphics Okay, Core Graphics and then there’s object oriented way using a class called UIBezierPath, okay? They’re both using Core Graphics underneath the covers so I’m gonna talk a little bit about the Core Graphics Concepts and they’re going to apply to UIBezierPath as you can see So what are the concepts of Core Graphics? Very simple. First, you’re gonna get a context to draw in. So that context might be drawing on screen That’s the context you’d want if you’re in drawRect But you could have other contexts like drawing for a printer, drawing into an off screen buffer, okay? Those are all contexts of draw so that’s the first thing you do In if you’re using this kind of like C-like function one you’re gonna use this UI graphics to get current context inside of drawRect

to get the context that’s appropriate for drawRect, okay? So then number two is you create paths So these paths are made of arcs and lines, rectangles, circles, whatever. You’re pu- putting together these Paths, this path that you’re building, okay? And that’s the thing that’s gonna be drawn, okay? So you build this path. Then you set attributes that you’re gonna draw this path with like, the color of the lines Any fonts if you’re doing texts Textures if you’re filling things with textures Linewidths, linecaps, those kinds of things You set all those things up and then you stroke the path which means draw a line everywhere the path is or you fill the path which means fill in the space contained by the path with some color or texture, okay? That’s it, this is the basic concept of how you draw The UIBezierPath does the same okay it’s just the UIBezierPath It has methods to draw Line two, arch two, those kind of things instead of having these great functions. You know these global functions You use UI color to set the stroke and fill colors This is a class we’ll talk about and then when it comes to stroking in fill, those are methods on UIBezierPath So UIBezierPath just encapsulates all that core graphics staff in to a nice class It’s nice because you can find everything you want Basically everything you want to do to draw except for colors, fonts, texts and images. Those four things are not in UIBezierPath but all other drawing is in there Okay, so how do you do this? Lets, I’m only gonna talk about the UIBezierPathway cuz it’s object oriented, we love object oriented programming here. So here’s how you would, create a path and draw some So we’re gonna do a triangle Okay, so first I create a UIBezierPath, okay theyre are one initializers with argueness we’re gonna use the one we just created, a blank, blank path Then, we’re gonna move around So, I’m gonna move to 8050, which is like right here Let’s say it’s 160 wide and 250 high, or something So, 8060s right about there Then, I’m going to add a line to this point over here, 140, 150. Remember, origin is up here, positive numbers are going down, okay? Gonna add another line right here. Okay, to 10150, and then I’m going to close the path, there’s a method called close path, and that just goes back to the starting point, so that closes it, and boom, I’ve created a triangle. Now I’ve misled you a little here, because no drawing on screen would actually happen if you put this in your draw rect Okay, if you put these lines and this code in your draw rect, nothing would happen. Because all you’ve done here is create that path. You have not drawn it on screen You haven’t stroked it or filled it. So how do we do that? How do we get it onto screen? Well first of all, we need to set the colors that we’re gonna use to stroke and fill. So I want my triangle to be red lines with green fill in the middle So I’m setting green color as my fill color and red color as my stroke color Notice that I send these as to a UIColor. I don’t send them to the BezierPath So it’s kinda odd that you do your setting of the colors by sending it to UIColor So we’ll talk about UIColor green color, what that means in a couple slides. So I’m setting my stroke and fill and then here I’m saying the line width of my path to three points, three points wide, okay? Now I can just say path.fill and I get my filled path, see? Filled with green Notice there’s no line around the outside. But then if I say path stroke, now you get a line around the side. And you can see it’s red. And it’s line width is three, got it? So you’re going to have code like this in your draw erect If you wanted your view to be a view of a triangle Okay, any questions about that? All right [COUGH] Now, you can use UI Bezier Path to draw more complicated things like rounded rects and circles and things like that, especially by using a lot of the initializers of UI Bezier Path, but there’s also methods there. So you’re going to have to study UI Bezier Path and see what it can do, okay, it can do quite a lot Another interesting thing about UIBezierPath is you can set it as a clipping path. So, let’s say you were drawing a playing card, right? Playing cards have rounded rects. They never have sharp corners, right? They have rounded rects Well, you could Could create a UIBezierPath here using this, create a rounded rect, set it as the clipping path, and then just draw your card in the inside And it would never draw in those corners, cuz it would be clipped to the rounded rect. Okay? So, addClip is kind of a cool Bezier path method The Bezier path can also do hit detection. So you can see whether a point is like inside the triangle, right? If you have that Bezier path that’s the triangle, you can do hit detection on it, whether it contains a point

So that’s kinda cool, too, right, doing some game or something and people have to touch on a certain kind of funny shaped thing, not a rectangular thing Then it’s nice to be able to do hit detection with it Okay? And there’s lots and lots of other stuff, you need to check the documentation. All right, UIColor. We saw that UIColor, green color thing, on the previous slide. This, what kind of method is this? Do you guys remember from last lecture? The green color What kind of method? Type method or instance method? It’s a type method Right because we’re not sending it to a UI color, we’re sending it to the type, UIColor UIColor’s a class and so we’re sending this method to it So it would be defined as static or class, funk, green color inside UIColor class Okay? By the way, you can also create colors, not just picking these well-known colors like green color. But there are initializers for RGB, red, green, blue. HSB, that’s hue, saturation, and br-brightness. You can even set, create a color that’s a pattern. Okay? It’s like some image that you have. You’d make a pattern out of it And when it draws, it will be drawing with that pattern It’s kind of cool. Here we see views have background colors So you’ve already seen that We set the background colors of our buttons in the calculator. You noticed that when we did that in the attributes inspector, we had to scroll down to the bottom because the attribute inspector is object oriented and it was showing all the inherited thing. Well we had to go down to The UIView level to set the background color of our buttons, okay, cuz button inherits that from UIView. Okay? Interesting thing about colors, they can have transparency Okay, meaning they kind of show through. That’s called alpha. How many people have heard the term alpha when it comes to drawing? Okay, so less than half of you So alpha just means how transparent it is An alpha of zero means fully transparent So if you had bright red but it was alpha zero you wouldn’t see anything because its fully transparent You’re seeing completely through it with no blocking Alpha of 1 means fully opaque, meaning you would not see a single pixel of anything behind something that was fully opaque. And between 0 and 1 is various degrees of being able to see through Okay, that’s called alpha. And you can create colors, like here’s a yellow By sending this message colorWithAlphaComponent, okay, is this a type method or an instance method? Raise your hand if you think it’s a type method. Raise your hand if you think it’s an instance method Hardly anyone raised their hand for either of them That’s great. But if you were to raise your hand for instance method you are correct. Okay This is an instance method That’s because we use this type method yellow color to get an instance of a color and then we sent it this instance method to get a half transparent version of yellow. So this is half transparent yellow right here, and if we drew with it it would draw yellow in our view, but we would be able to see through, to things behind, perhaps even to other views, like our super view, behind If you want to draw with transparency in your view If you want to draw with colors that are transparent You have to set in your view this far opaque to be false As a performance optimization the system has to assume the view is opaque okay? That it doesn’t draw with transparency. That’s because you can imagine things that are transparent overlapping, think about the work that the system has to do to figure out what’s showing through from behind Okay? That kind of compositing, it’s called, takes processor power and memory Okay? So, it’s gonna assume that everything is opaque. So it doesn’t have to do that, but if you are drawing with transparency, that’s fine, just set this opaque to false, to let the system know, no I’m not opaque. I’m gonna draw with transparency Now another thing that’s cool, is you can make your entire view transparent, by setting the alpha property on the view itself, okay? So you could draw your whole view, your triangle, let’s say, set the transparency to 0.5, and you’d have a half transparent triangle, even though you drew all with opaque colors, you’d still have a half transparent triangle because you set your alpha to 0.5 Okay? Using alpha is really cool for doing effects like fading views out. Okay, sometimes you want a view just to fade out over time, you want to animate that, alpha is one of the things you can animate, we’ll talk about animate in a couple of weeks, so alpha is cool for doing that. All right, now let’s talk about this view transparency and how that works when you’re drawing with transparency If you have non-opaque views, okay, say they’re drawn with transparency, then what happens is that sub views list that shows all of the sub views is in order where the first thing in the sub views list is in the back okay. The next thing is in front of that, and the next one’s in front of that, the next one’s in front of that and so it’s gonna show through like that, get it? So the sub views list matters okay The sub views list is built by add subview, everything is always put in the front when you call add subview. But,

there’s another method called insert subviewat, that let you put it anywhere you want You put a subview in the back Like if you say, insert subview at zero, it will put it up at the back Okay. So, just note that, that subviews orders obviously matters. You can completely hide a view by setting it’s hidden to true If you set it’s hidden to true, it will not receive any events, no touch events. Nor will it draw what it draws It will still be in view hierarchy, okay, but it’s as if it’s not there. Now why would you want this? Well you might have a view that only appears when a certain button is in a certain state So you put it there You set it hidden. When the button goes to that state you unhide it and it’ll appear Now to be frank you probably animate it’s appearance with alpha okay so it would zooooo appear like that Instead of jumping on screen that’s kind of disconcerting But you still would probably use hidden to have it hidden in the first place. Because you wouldn’t want it for example getting a touch of answer on like that until it was shown What about drawing text You do not draw text using a UiBezier path. Text is really just a bunch of Bezier paths in a font. A font really defines a bunch of Bezier paths for each character, each gliff. It’s called. So we have higher level ways of drawing text by basically saying here’s a string, draw it. Okay that’s a high level way to get all those bezier paths drawn, you don’t want to be dealing with that at the UI bezier path level for sure. But most the time, we don’t draw text even in our drawRect. We draw it by using UILabel which you’re used to all ready, okay? We just have a rectangle? Boom, we put it on here If we wanted to say hello on this guy’s forehead, we might put a UILabel right there say hello. Okay, but what if we did want in our draw rect What if we wanted to put some text in here and we didn’t want to put it as a subview, a UILabel subview on our face view. And the way you do that is with a class called NS attributed string Okay, NSAttributedString And you create it by, this constructor here. Usually you pass a string in here What an attributed string is, it’s a string that for every character has a dictionary of attributes that say how to draw it. And those attributes are things like, the color of the character or of the glyph, the font to use obviously, maybe a background color, those kind of things, right? You have a dictionary that has all those kinds of settings for every single character Now often you have long runs of characters that have exactly the same color and font or whatever, so you would have one dictionary for all of them. But that is the basic way that AttributedString works. And once you have an attributed string, okay, maybe you’ve set these dictionaries on the characters, then you draw it in your drawRect by saying text, that’s the attributed string. You send the method here, drawAtPoint, and then you give it a point And it’s going to draw that text with the upper left corner being at that point So, if I wanted to do that hello and I would have drew it right here. The hello would appear like this. Okay, this is the upper left and it would appear, the text would appear here Okay, got that? And I could find out how big this is gonna be by using this size method, okay, the size property, actually of attributed string, okay? So that’s how we draw a text. Now this is a little bit of a nasty class to use, to be honest, NSAttributedString, for a couple of reasons. But all the reasons come from the fact this is an Objective-C class that really didn’t get a very good Swift treatment yet, okay? So there’s two major differences that make using it a kind of complicated in Swift, okay? One is that mutability is not done with var and let. Okay, normally if you wanted an array that you can add things to do, you would just say var x array, and since it’s a var you can add to it. Okay, if you said let x of an array, then you couldn’t add to it Well that’s not true for NSAttributedString You can’t say var NSAttributedString, that’s still immutable. The way you do mutability is with NSMutableAttributedString, it’s a different class, okay? So if you wanna built an attributed string and start setting the attributes on it, you need to use MutableAttributedString instead, okay? You create it the same way with some string but now you can set the attributes of it or whatever. So that’s one thing that’s kinda weird, okay? Is this mutable, you have to use this mutable version of it By the way, NSAttributedString is not a string, a Swift string, nor is it an NSString even an object string. It’s its own thing. It does have a property string and another property called mutableString that will give you back a string/NSString using that bridging thing but it itself is not a string. You can’t pass it as an argument to something that’s accepting a string, okay? NSAttributedString is a different thing. Now,

the second thing that’s difficult with Swift and attributed string is the range here, okay? You’re trying to set attributes This is how you set attributes in the thing Here’s the dictionary I’m gonna show you what’s in that dictionary in a second And you’re trying to set it for a range of characters in the string. You want the font or a color to be something for a range of characters. Well, this range is not a Range, it’s an NSRange. Okay, NSRange is different than Range And NSRange, the index is in here Okay, it’s a struct also that has a start in and a range, basically. A distance, start in a distance. But these indexes are into the Objective-C NSString. Now, what’s the difference between a Objective-C NSString and a Swift string? Well, as I told you before, a Swift string is fully Unicode compliant, okay? So, things like emojis and stuff like that might be multiple characters. So the length of an NSString might be different then the length of a Swift string, okay? Swift string has a lot of possible Unicodes in there, whereas an NSString might not necessary do the full Unicode treatment. So, bottom line, they’re different Now, if you have just normal text which I hesitate to even say that because of course you want to build apps that work But if you have text where there’s no Unicodes in there worldwide that are multiple characters long You don’t have emojis in there and stuff Then they’re gonna be quite similar, these ranges, but otherwise, you might have to be really careful to make sure that you get the range to be the NSString range That might mean taking the Swift string that you have, converting it to an NSString, which is really easy cuz it’s bridged automatically And then, looking into the NSString to see how long it is and where things are Okay, I apologize for this Of course, I have never worked for Apple, so I have nothing to do with it But, this is the way it is Hopefully, one day soon, Apple will come up with some nice more Swifty way of doing this. What is in this, by the way I’m not gonna ask you to do this very much in your homework. Okay, so don’t worry too much about that What are the attributes you could put in this dictionary? Exactly what you would expect Okay, the foreground color is the color of the text The stroke width is how thick you’re gonna stroke the text. The FontAttributeName is the font, the UIFont. There’s a class called UIFont, okay? You put those in a dictionary and then you can set that for whichever characters you want in your attributed string Now let’s talk about fonts, by the way. Fonts are super important in iOS, okay? They are critical to the look and feel of it. You can see there’s all kinds of different fonts here, right? You see some bold, some not, some kind of heading fonts, there’s system fonts like up here Look at the use of fonts here, how important that is, okay? So fonts are very important and if you’re gonna build a good app, you really gotta pay attention to the fonts So how do I get the fonts or pick the fonts that I want? Well there’s really three ways to do pick it, okay? Number one way is using prefered fonts. So, preferred fonts are the fonts you’re gonna use for the user’s content, okay? The user, the stuff the user is actually, there, like if it’s a calendar app, then it’s all of the things about their appointments and things, okay? If it’s the weather app, it’s the temperature and things like that Those are part of the user’s content. You get these mostly in storyboard by going to attributes inspector and you pick the font. And we’ve only picked the system font because we’ve always just had buttons, which is a system font thing. But for content, you would pick in there prefered font. Okay, and I’m gonna talk about what those referred font styles are in a second. In code, your gonna use this UIFont static type function called preferredFontForTextStyle and say what kind of text style you want and it’s gonna give you UIFont, okay? So what are these text styles? Okay, there’s about eight or nine of them, but some examples are headlines, body font, footnote font, and you should use the one that’s kind of appropriate to what your UI’s doing at that time, okay? There’s like caption font, a couple of other things, all right? And so, you know, sometimes you play with these The difference between a caption and a footnote can sometimes be subtle so you might try both and see which one really feels the best. But, you’re gonna use these various preferred fonts to build a cool looking UI, okay, that’s beautiful and all that The second kind of font thing is systems font, okay? systemFontOfSize, boldSystemFontOfSize System font’s what we’ll been using in our calculator, those go on system elements like buttons, okay, that’s where you would use a system font In our display in the calculator, we probably shouldn’t have used a system font there because really what’s in the display is kinda the user’s content. Probably we should’ve used a prefered font but I hadn’t shown you the slide yet so can’t introduce it all at once, okay? But that probably would be better And the kind of font we want to use there might be instead of a, sometimes you want to use a specific font, okay, so the third way here Is to use a specific kind of font

Like maybe in the calculator display we wanna use something that looks like LED segments You know what I’m talking about? The old style, funny calculator thing back when we had LED displays [LAUGH] So we might wanna font this LED font which they make those. In that case, you wanna check out UI font and UI font descriptor, especially, because those are how you pick a specific font from a specific family, okay. Like the LED font family, okay So those are the three ways Preferred system or highly customized okay, how about drawing images? Just like there’s UILabel for drawing text, there’s something called UIImageView for drawing images. So, you could just put an image if I wanted to put image on this guy’s forehead, I could just put UIImage here and have my image here. Okay, put it as a sub view of my face view So, that’s one way to do it But, if I want to draw UI image in my draw rack, it’s very similar to the text, I’m going to get a UI image, okay There’s a number of ways I’ll show you here to do that But, the main way is you’re gonna do it by name You’re gonna put the image in that images.xcassets Do you remember that thing I kept moving out of the way into supporting files? Okay Images.xcassets, so you’re gonna drag an image in there, give it a name, and then you’re gonna say image named that name and you’re gonna get a UIImage. This is optional because it’s my fail Okay, you might have forgotten to drag that image in there or something. Who knows? But once you have this UIImage in your hand. By the way there are other ways you can do it You can create it from a file Just some image data you got from the Internet for example That’s another way to create a UI image. You can even do it by drawing graphics onto an off screen buffer. You have that image in your hand, you draw it the same as the text You say draw at point That’s the upper left But you also can do what called draw erect Which will draw the image but scale it to fit this rect, okay? Or you can draw it as a pattern which will tile it okay? It will take that rect and use it as a tile to fill in the rectangle Okay, so this code would be the kind of code that would be in your draw rect. Okay the last thing here above you is redrawing on bounds change, okay. When your view’s bounds changes, what happens to the face inside here? Okay so, if I had this face and it was in a portrait thing here. Let’s say it looked like this, okay. Face. And I rotated my device in this bounds of my view changed to be like this. Landscape You think well I’m a face would you have to redraw and it would probably look about the same. The answer is not It would look like this, okay? It would get stretched out And that’s cuz the default when your bounds change is to scale all the bits, to not redraw, okay? And that’s a performance thing as you can imagine. It’s a lot more, a lot easier just to stretch those bits out than to ask draw rec to go again. So you can fix this though with this property in your eye view called content mode. Okay, UI content mode? And some of the value of it can be to move the contents to the left to right top, bottom top, right top left. Okay you could just move it, not stretch it out but just move it to that place in the new bounce You can scale it. This is the default, ScaleToFill, okay? And that’s a stretching out behavior Or the holy grail, Redraw If you set your content mode to Redraw, it’ll call your drawRect again, okay? You often want that. Maybe most of the time you want that, okay? All right, everybody got that? We’ll be doing this in the demo, too, so you’ll see it Okay, so I’m not going to come back to this slide So, just tell you what’s coming up after the demo No section on Friday, as we said. Next week, gestures, multiple MVCs and View Controller Lifecycle, okay we will talk about next week And right now I’m going to do at demo where I’m gonna do custom UI view to draw this face thing, okay. That’s the timer saying we should start the demo Let’s do it. All right, so I’m not going to be doing calculator here, this is going to be a completely new application, alright, so I’m going down here to create new XCode project Okay, here it is, it’s still in iOS application though, we’ll do single view application I’m gonna call it, Faceit, okay? It’s a face drawing app so I’m ca-calling it Faceit. Make sure it’s Swift, not Objective-C and it’ll be a universal app cuz we’re eventually gonna do multiple MVCs with this thing too. No core date or testing, okay? We’re going to put it in the same place we put the calculator here, not source code control yet. All right, so here’s our new app, I’m going to do the same thing I always do with this, I called that images, that x, assets,

but it’s called assets.xz assets This is where you would drag in your images if you wanted to do that UI image named foo thing. You’ll put them in here, but, obviously, I don’t need these things, as usual, so I’m just gonna group them into that supporting files so they’re not distracting you every time you take a look over here on the left, cuz all we really care, care about, again, is our storyboard and our view controller. Now, again, we’re talking about view controller lifecycle next week, so we’re gonna delete these, all right? Now, the first thing I’m gonna do is actually rename this ViewController, because it gives me this [LAUGH] generic name, ViewController, which we talked about last week, not so good, okay? Well, I’m, I don’t want that. I’m gonna, I want mine to be called FaceViewController, because it’s gonna show a face So I could just say FaceViewController, and I might think, okay, I’m good to go, FaceViewController. But of course, that’s not good enough. First of all, I probably wanna rename the file, because in Swift, generally the name of the file should be the name of the most important class in the file, okay? Cuz that’s what people are gonna expect when they see the name of the file So that’s one thing But that’s not enough, either. Cuz if I go back here to my storyboard, and I look at my view controller right here I can actually look at this inspector up here. If you pick up your view controller and look at his one right here It’s called the identity inspector I can actually see what the story board thinks the class of this view controller is And you can see that it thinks it’s view controller, okay Generic view controller. And of course I renamed so that’s not what I want. So I can change it though, just by clicking here and changing it to face view controller, okay So in your assignment to, it’s not a required task, but I strongly recommend that you rename your view controller Assignment two is about the calculator. Rename it from calc, from View Controller to be Calculator View Controller You will definitely want that for assignment three But I recommend doing it in assignment two. Okay, just so you, this is all you have to do, what I just did It’s not that hard, but it’s good practice Okay, it’ll help you understand that the storyboard has classes of things in its identity inspect, inspector that have to match up with what’s in your code, okay? All right so we got that renamed where we want to draw our face okay so we need a face view a UI view a subclass of UI view it does that. So let’s create a subclass of UI view. Anytime we’re adding something to our project we go file new and I’m gonna create a new file right here and this file’s gonna be iOS source. It’s gonna be a Cocoa Touch Class, cuz it’s gonna be a subclass of UIView. Any time we create a subclass of something in Cocoa Touch like UIView or UIViewController or whatever, this is what we want So I’m gonna double-click that. Here it says subclass of, it’s already on UIView But you can create subclasses of NSObject, especially if you’re doing Objective-C Or UIView controller or any of many, many, many, many other classes. But we’re gonna do UIView here I’m gonna call my view Faceview Okay, cuz that’s what it is, a view that draws a face Okay, I’m gonna put it in the same group right here, this group that has all this stuff in it. Okay, same thing We’ll put it in there And here it is Notice that it gave me a drawRect Look at that, drawRect But it’s commented out Now why did it give me a drawRect commented out? And this is because unless your drawRect actually does something, do not have a drawRect, because if the systems sees that you have a UIB that has a drawRect, it’s gonna think that it needs to get you to draw itself all the time. But if you don’t actually draw anything, maybe you just have subviews, okay, you don’t draw anything, then you don’t want the system wasting its time trying to get you to draw yourself, okay? But of course, we are going to draw, so I’m gonna uncomment out my drawRect here and start drawing my face Now my face is gonna look like we drew before here, okay? It’s gonna be a rectangle and here’s my bounds, let’s say, that I have to draw in I’m gonna draw my face in the middle, okay? It’s gonna be the smaller of the width or the height so the, its face fits completely, right? And then I’m just gonna have a couple of round eyes and a smiley face And we’re gonna make it so this smile can be a smile or a frown or it’s movable basically, changeable Okay, so that’s, that’s what we’re gonna build right here, okay? So since I want this thing to be in the center, and I want it to be the smaller of the width or the height so it fits, I’m gonna create two vars to start off for the center and this radius of this thing. So let’s do that Okay, so let’s, first let’s do the radius here, so I’m gonna say var I’m inside my drawRect here, just implement this. I’m gonna call this the skullRadius cuz this is the radius of my face’s skull, okay? And I’m gonna make that equal to the minimum of the width or the height of my view Now what is the width or the height of my view? Now there’s different variables we

could look at here. We could look at this rect, okay? I could say let width equal rect.size.width Would that be right? No, that would not be right, because this rect is just an optimization that says what part of the view to draw, okay? Well, my face needs to kind of draw in the whole view or won’t be the right size, okay, it would be all small So this is not the right one I could say frame.size.width Would that be right? No or yes? No, I see a couple of shaking heads no. The answer is no Okay, frame is the rectangle that contains me in my superviews coordinates I’m drawing myself, I can’t draw in my superviews coordinates I need to draw in my coordinate system, okay? So what we want here is bounds, okay. Bounds is the rectangle that I’m drawing in in my coordinate system here, okay? Same thing height, bounds.size.height, okay? And also I want my skull’s radius, I’m not doing the diameter I want it to be divided by 2 Now it’s kinda silly to do these local variables Probably a lot better just to take this and copy and paste these right in here like this. Okay, let’s make some more room here. All right, so I’ve got the radius of my skull. That’s good. What’s the other thing I needed, is the center of my skull, so I’m gonna call that skullCenter. Okay, and what is the center? Well, can I say center? Is that good? No, center is my center in my superviews coordinates That’s where I am, okay, not the center. Now here’s two interesting ways to get the actual center of my bounds Okay, one is, believe it or not, is I can say, convertPoint. This is a UIView method, convertPoint, convert center, this point’s center, from view, my superview, okay? [LAUGH] So I would be converting that point, the center, from my superviews coordinates to my coordinate system. This would be right. This would work, cuz now I’m in my coordinates system. Same point, but it’s in my coordinate system So that’s one way we could do it We probably wouldn’t do it that way. Instead, we’d probably use some of the vars that are on CGRect. For example, I’d probably say something like the skull center is a CGPoint whose x, okay, x and y of CGPoint, right, whose x is probably my bounds.midX and my y is my bounds.midY. Okay, so midX is just a property on CGRect which tells you the x that’s midway across this, the rectangle Same thing midY. Okay, so I’ve got my radius and my center. I put these as vars, but really they probably wanna be lets, okay, cuz I’m, I’ve calculated, I’m not gonna change them after this. All right, so now that I have this, I need to create a Bezier path for my skull, for the circle here So I’m just going to create a local variable here called skull. It’s going to be of type UIBezierPath, and so UIBezierPath. And you can see UIBezierPath has a bunch of initializers here I could use this one, ovalInRect, because a circle is an oval. But I’m gonna use this one arcCenter because I have the radius in center I don’t I don’t wanna create an oval in my entire bound I’d have to create just some kinda rectangle that gets my, only my skull. So I’m gonna use this one, arcCenter, which takes a radius and a center, which I have right here And then a start angle and an end angle as it goes around the arc, and either clockwise or counterclockwise. Okay, so let’s do that. So what is the center of my arc? skullCenter, okay, that’s the center of this arc I’m gonna draw that’s gonna be my skull. The radius is the skullRadius, right, that’s the radius I’m going around Now startAngle to endAngle, that’s in radians Does everyone know what radians? Raise your hands if you know what radians are. Okay, almost everybody, good. So radians, 0 to 2pi radians to go all the way around the circle So I’m gonna go from 0 to *_PI, okay And then I can either go clockwise around or I can go counterclockwise. In this case I’m going all the way around, so it doesn’t matter. So I’ll just go counterclockwise, whatever, okay? So you can see how this has drawn an arc, so I’ve create a Bezier path which the path is around a circle, okay? Now well, I have an error here? What’s, what do you think this error right here is? Look at that. Cannot convert value of type ‘Double’ to expected argument type ‘CGFloat’ It’s pointing to this little thing right here, this _PI, okay? Well, this is what I was telling you about before All these drawing things are in CGFloat. What type is this? What type is that expression? >> Double? >> It’s a double, right. Okay, so we can’t use a double there. It has to be a CGFloat So we have to convert it to a CGFloat by doing this,

okay, CGFloat. Now how come this is not complaining? Okay, I told you last time that if you see a literal 0.0, it thinks that’s a double Didn’t I tell you that? Well, I lied. Because when it sees 0.0, it can convert it to a number of different types, since it’s a literal Okay, Swift can only do this automatic typing version for literals, okay? So 0.0 is a literal, so it can convert to a number of different types Double, Float, CGFloat It knows how to do that, okay? So why does it pick CGFloat here? Because it knows this method takes a CGFloat. And when it sees a literal and it sees CGFloat is the argument type, it tries to convert it to a CGFloat if it can Which it can, okay? Everybody got that? All right, so I have this skull It’s of type UIBezierPath I can set attributes on this skull now, like maybe it’s Line with maybe we’ll make it 5.0 point that’s 5.0 points wide. Right? If I wanna set a color, I don’t say skull set color something like that I create the color I want. So let’s make our skull be blue okay? So blueColor, which is the type method on UIColor And I’m gonna say set. There’s setFill, there’s setStroke, and there’s also set, which sets both the fill and the stroke. Okay? Now, to get it to draw, I just need to say skull.stroke, okay, and that’s going to draw along this Arc, then I drew with this line width and with the color that set. Okay, that’s all that’s necessary to draw the skull of our face here So, now we have this nice UIView, this custom UIView It draws the skull of a face anyway. How do we get it into our UI? So if we go back to out storyboard over here Right now it’s blank There’s nothing in here There’s only this background view And I promised you that there was a Var in the Faceview controller that pointed to this view And I’m going to show it to you by right clicking on this You see it right here? When I mouse over it you see how it’s highlighting it? This is a outlet called View, just like you have an outlet on your display on your calculator, this one is an outlet or var, which is a type UI view and it’s connected to this thing right here so it’s automatically connected up for you., you don’t even need to control, drag it or anything, okay? But we’re not gonna be adding our viewing code, so we don’t really need that var, I just wanted to show you it was there I’m going to add my view by dragging it out. And if I go down here to my palette, obviously I’m not gonna find face view in here Okay. IOS didn’t know about face view when it built Xcode. But I can go down to the very bottom here and grab one of these. Okay? This is a generic UI view Okay not a sub class of UI view just the UI view. So I’m gonna drag it out and put it here Now I’m gonna do a cool thing okay I’m trying to show you bit by bit a little more of this constraints thing so I’m gonna take this thing I’m gonna us the blue lines okay I’m gonna put it all the way up in the corner here and then I’m gonna put the other edge all the way down in the corner down here and I’m using blue lines you see blue lines? Appearing. Those blue lines are making this thing attach to well known point In this case, the edges So I want my face view to fill the entire view, okay? The entire view controller’s view. All right, but just doing the blue lines isn’t enough as we learned, okay? That’s just kind of telling the system what you intend To make it do it you actually have to have constraints like those things we control drag So I could try and control drag to an edge, control down to this edge, all that, but there’s an easier way. If you did all blue lines and that’s all you needed, you could go down here to the same place where you update frames and instead do Reset to Suggested Constraints. And that will use the blue lines to put some suggestive constraints. Now, let’s see what it did. You can see all the constraints on a view by going over to the inspector and going to this tab right here, which is the size inspector And if you look in the size inspector, down toward the bottom, you can see constraints. You see them? And this is showing me all the constraints and it put one trailing, that looks good. Leading yeah, top nice, bottom perfect. So it put exactly the constraints I want because it followed the blue lines okay so now I have this view constrained to stick to the edges Perfect, because then when I go landscape or portrait my bounds are constantly being resized To fit the new shape Okay? Now the other thing I need to do is this is a generic UI view If I ran right now, it would come up blank because it has no draw rects Okay? I did that nice face view draw rect but this is not a face view. So how do I set this to be a face view? Exactly the same way that I set this view controller to be

a face view controller. I go to the identity inspector and instead of, so here is when I did the controller, I click on this view and instead of it being a generic UI view, you see, I change it to be face view Got it? Okay. So let’s run, okay it should work, let’s run on Iphone six, for example. And hopefully, we’ll get the skull of our face to draw Perfect it worked okay So here’s our skull it picked the smaller of the width or the height they went to smaller so picked is drawing the whole side, if I rotate? Uh-oh Stretch-a-roo. Okay? So that’s this problem with the content mode of our face view is set to be scaled to fill. Okay, so it’s scaling our thing So we don’t want that So let’s go back here and go to storyboard and select out face view right here, go to the attributes inspector The very first thing is the content mode. And you can see it is scale to fill, and i want it to be redraw In other words when my bounds change, call my draw rect You see that? Okay here we go, works in landscape works in portrait. Okay, it’s even switching from using the width to the height >> Because that gets smaller >> Okay, sound good Now one thing that’s kind of a bummer Here in my interface builder, I don’t see my face How come I don’t see my face here? And it is possible to make the face appear here, and we’ll do that next week, okay? Cuz it’s nice, when you’re building your storyboard, to be able to see your custom views in there. All right, so let’s go back to our face view and add some more Let’s add some eyes. We’ll add some eyes to, our face, here, and to do that, I’m gonna start having some little helper functions here along the way I’m gonna make it so that my eyes and the mouth are all relative to the size of my skull, what ever my skull size is, I’m gonna make everything else relative to it obviously. So I’m gonna take this skull center and radius, and take them out of drawrect and make them vars, okay These are gonna be vars. Now when I tried to do this, and you’ll try this in your homework I’m sure You’re gonna get this error It stays instance member bounds, okay? Is, cannot be used in type face view. And you are gonna get so frustrated, cuz you’re gonna say bounds is definitely an instance member of face view, how come I can’t use it here? Okay? And the answer of why you can’t use it here is because you are in the initialization phase You are initializing this. And during initialization, you cannot use your class It’s not initialized yet So you can’t call vars and methods like bounds. Okay? Everyone understand that? So, you will see this message I’m sure. And you will post on PL as a Piazza probably and say, what’s going on? But I’m telling you right now what’s going on During an initialization you cannot, until you’re fully initialized, you can’t access your own properties. So, what are we going to do here about this? Well, I’m just going to change this to be calculated. Okay? To be a computed property Okay. I’m gonna just return this value right here. Okay Now, two things about computer properties. Notice that I didn’t say get}, If you have a computer property that only gets, you do not need to put together in there. Okay And we never would Look much nicer not to put it Same thing here, this is a CGPoint We’re going to return this Okay, not gonna put the get in there. All right, that make sense? Now one other thing I wanna do is, my skull is all the way out to the edge. I’d like my skull to be able to be kinda scalable, to be smaller than the edge So I’m gonna add a public var called scale, okay, which is going to be a CGFloat And it’s going to scale my skull. And I’m just gonna do that by here when I’m calculating the radius, I’m just gonna multiply it by my scale. And I’m gonna set it to 90% so that my skull’s kinda 90% of all the way in Now I’m gonna use these two vars, okay, these computed vars, in all my other calculation. Eyes and mouth, all these things, I’m gonna use the same thing. So we’ll do eyes today, and then mouth, we’ll either do mouth at the start of next lecture, or maybe I’ll just post, I’m gonna post this code, by the way, on Piazza afterwards Maybe I’ll just post the mouth code so you can take a look at it But let’s do these eyes first How do we do the eyes? To do the eyes, I need kind of the ratio between the skull radius and

the eye size. So to make things quick, I actually am gonna type those in real fast, here they are. Okay, so here’s all the ratios from the skull’s radius to the eye’s offset to the eye’s radius to the mouth’s width, height, and offset, etc. Notice how we do constants in Swift We create structs and then we have type variables, static Type variables, okay, which are lets. They’re typed like this too. That has the value, okay? So this is how we do it Notice these are capitalized and of course as the name of a type we always capitalize the names of types Don’t forget that Okay, some of you don’t like to do that. Please do it In Swift we capitalize all type names. And we also capitalize these, okay, these static things that are basically constants in this struct And I’ll show you, we’re gonna access these by saying Ratios dot this, okay, cuz this is the name of the type This is the, the value in it So I’ll show you that when we start using these So how am I gonna do this? How am I gonna make my eye here? I’m gonna create a new method here. First of all, let me create a little type here, which is an enum. I’m gonna call it eye. It’s gonna have left eye and right eye. That’s just so I can talk about my eyes in my API. And then I’m gonna have a func, which I’m gonna call pathForCircleCenteredAtPoint, okay? It’s going to take a midpoint, which is a CGPoint And I’m gonna have withRadius, which is gonna be a CGFloat And it’s gonna return a UIBezierPath. So this is gonna be a utility function, okay? It’s private actually, make sure we get this private And this is private also Okay, these two are actually private. I’m gonna try and get in the habit of actually putting my privates in here so that we get the, our things proper This is properly public, okay? So this function is just going to take a center point and a radius and give us a Bezier path, exactly the same thing we’re doing here. So I’m actually even just gonna copy this, cut it actually, and put it here Okay, so we got that And the center is not the skullCenter, it’s the midPoint. And the radius is not the skullRadius, it’s this withRadius. Now let’s just kind of point out this weirdness of having something that reads nice when you call it, because when I call this down here I’m gonna say pathForCircle with CenteredAtPoint, the skull’s center, withRadius the skull’s radius That reads really nicely, like English. Okay, got this nice preposition in here But when I’m inside my code, it’s kind of weird that this is called my withRadius Okay, that doesn’t really make sense I really want this to be called radius inside So this is where I’m gonna have the internal name and the external name that we talked about. See that? Okay, so that’s all that this is gonna do. I’m not gonna return it directly though. I’m gonna let the path equal this and then I’m going to use this to set my lineWidth as well In fact, let’s just cut and paste this as well up here So I’m gonna have all my lineWidths be the same. Okay, this is probably something I want to make a var out of, just like I have the scale, probably want the lineWidth also to be settable, but for speed we’ll keep going here And then we’re gonna return that path. Okay, got that? Make sense? By the way, when we have a really long line right here that wraps, one way that we can kind of make it look nicer is just put every argument on its own line. Like that, okay? Just a little more readable that way when it’s really long. So I’ve got this right here, and I’ve replaced this skull thing with this, okay? By the way, I don’t really use skull, except for to do this stroke So let’s take this, cut it out of here, and put it here, okay? Everyone see what I did there? I’m just chaining calling this and then calling stroke on it And it’s pretty obvious this is my skull, because I got skullCenter, skullRadius Okay, so now I have this path for circle, I can use that to draw my eyes as well. So I’m gonna add another private func here called get eye, what did we call it, pathForEye, pathForEye and it’s gonna take an eye, which is of type Eye and it’s gonna return a UIBezierPath Okay, so this is gonna get an eye, either the left eye or the right eye depending on what this argument here is right here. And to do that I need the eyeRadius So we’ll have the eyeRadius, which is going to be equal to the skull’s radius, divided by one of these ratios up here, okay, in fact, this ratio right here So we’ll say Ratio., Ratios., this one is SkullRadiusToEyeRadius, okay?

And then I’m gonna let the eyeCenter equal the I’m gonna actually call a function here, getEyeCenter for the given eye Okay, and so let’s do that Private func, getEyeCenter for given eye. And that’s gonna return a CGPoint which is gonna be the center All right, so how do I get the eyes centered here? That’s pretty straightforward Here I’m just going to say, what did I decide to do here on that one? Yeah, so I’m gonna let the eyeOffset = skullRadius / Ratios.SkullRadiusToEyeOffset Okay, so I’m just, see how I’m just doing all the positioning of everything based on the skullRadius and the skullCenter? So then I’m gonna let the eyeCenter = skullCenter So we’ll start with the eye being right in the middle of our face, and then I’m gonna move it up and over, right? So first of all let’s move it up by saying that the eyeCenter.y -= because y minus is up, plus is down for the y-axis, the y offset. So I’m gonna move it up by the y offset. And then depending on which eye it is, okay, if it’s the left eye I’m gonna move the eyeOffset.x to the left, okay, minus, oops, this is eyeCenter. And actually this should be eyeCenter also We’re gonna move the eyeCenter to the left to by the eyeOffset And if it’s the right eye, then I’m gonna move the eye to the right by the eyeOffset Okay, so that tells where our eye is. So I’m gonna return the eyeCenter here. Okay, everyone got that, where the, where the eye is? So we have a warning here, what is it? Let var, okay, so this needs to be var Or no, this needs to be a var, I guess. This needs to be a let, okay, and the lets and vars are right, yes. Okay, so here we’re gonna get the center of the eye using that function, so we have the radius and the center, for the eye. So, now we can just return, return a path for a circle centered at point, the eyeCenter withRadius the eyeRadius Okay, so we have this path for eye, now we just need to stroke this path. So we’re gonna say pathForEye, for eye, let’s do the left eye And stroke that. And then path for I. Lets’ do the right I, and stroke that, okay? Notice, by they way, I can say .left here. I don’t have to say i.left.because it’s going infer that path for I is going to be an I, okay? Everybody got that? Success? So hopefully now when we draw we’ll get some eyes on our face. Didn’t quite work, okay? So, let’s close what happened there We got one eye, the left eye looks good, but the right eye is kind of stuck in the center. So why is that? Let’s look here, well, looks to me like I moved the, for the right eye, I moved the center y back to this, where it was before, see I moved there, so this really needs to be the x, see that? It’s over on that Okay, bingo. Got a face, can rotate him, it’s looking good. So now we did the mouth, okay, let’s see if we have time for the mouth, yeah, we might, we’ll get started on the mouth anyway. So here I’m doing the same thing, private funk, path for mouth this time, okay, there’s only one mouth, and it’s going to return UI Bezier Path okay, and then we’re gonna do the same thing down here We’re gonna say pathForMouth().stroke Okay, so how are we gonna do the mouth? I’m gonna have to use a bezier curve to do the mouth How many people know what a bezier curve is? Raise your hand if you know Almost nobody. Okay, So Bayesian curve is just a line you draw between two points, but you have two control points somewhere, where, it tries to draw a tangent line to the control point and start the curve on there And then draw the tangent line to the other control point and tries to draw another one there, so you can make curves Okay, using these little control points So I have to determine the start and the end, and the two control points So first I’m gonna create a rectangle to contain my mouth here. I need these mouth ratios, so the mouth width, height, and offset, I’m gonna make as ratios to the skull radius, okay? Save a little time by doing that. And then I’m gonna make the The rectangle changes them out by equal a and this I’m going to use the X, Y width height intizler here So

the X is just the center x- mouthWidth/2, okay? So my mouth is going to be whatever the mouthWidth is from the skullCenter. Move it over. And the y is similarly going to be the skullCenter.y +, actually The mouth off set, because we’re going to put the mouth down below the center of the face, so we’re going to do it down. The width is just the mouth width, and the height is the mouth height, okay, and just to show you what this is like, I’m going to create a rectangle, UI Bezier Path has a constructor which creates a rectangle using mouth rect Okay, so let’s run that, let’s return that actually Okay, that’s the path we’re going to use, we’re just going to do a rectangle first, I’m not going to do those control point things yet. So our rect is going to be a rectangle, so this is where we’re going to do the mouth, if it’s smiling, it will be down here, if it’s frowning, the mouth is going to be up here. Okay, so we are going to put this here This is going to be the start point of my busy path This is going to be the end point I’m going to put one control point here and one control point here for a full smile And so it going to start heading down towards this control point bottom out. And then start heading towards the tangent line between here and this one. So, that’s what is going to make a smile. Okay? Don’t worry about it too much if you don’t know B├ęzier path So here, I also, I’m gonna type this in really fast just to save some time here. Most important thing is this mouth curvature This is just a double, which is somewhere between -1, which is a full front, and 1, which is a full smile Okay and so the smile offset, first I’m gonna make sure it s between one and going to be that one to minus one times the mouth’s height That’s why I’m going to put my control point all that way day at the bottom if the smile is one All right, so here so here I’m gonna start at the mouth’s upper left. I’m gonna end at mouth upper right, okay? My first control point is a third of the way along the bottom. And the second control is a third of the way on the other side, okay? And on the bottom, wherever the smileOffset puts it. Okay, so in full smile this is gonna be along the bottom of the Rect. Could be up above the rack. Okay, so I’ve got that so now I’m just gonna return UIBEzier path here that incorporates all that Let’s actually do this let’s say let UIBEzier path. I’m just gonna create a blank one then I’m gonna tell the path that to move to the start Move to our starting point which is start, that’s this thing right here. Okay then I’m gonna create a bezierPath or bezierCurve which is add curve to point that’s the way you add a bezierCurve to a path it goes to the end point which is this right here, and here’s my 2 control points cp1 and cp2 Okay, that’s these two guys All right, so I’ve done that I’m gonna set the line width equal to 5.0 and return the path. Okay? So let’s see if that works, we have our mouth here set to be 0, which is not a smile or a frown, it should be just kind of straight line Cuz our control points are gonna be right along the line sure enough this is not a very happy camper let’s make them very sad Okay aw that looks very sad but I don’t you saying I don’t wanna sending you guys out of here sad so we’re gonna go to full happy here. There it is. Very happy Okay. Now, one thing I’m gonna do, last thing I’m gonna do before we leave is this mouth curvature is currently a local variable inside this private method. I’m actually gonna make this public. Okay, so I’m just gonna take it out of here I put my public bars up here at the front, loose scale. Put it there, I’m gonna make it a var so it’s public. So now other people using my face view can set how happy it is, right? Cuz I’ve made this public so they can set whether it’s a smile or a frown. And that’s gonna be really valuable next week when we stat having multiple NVCs cuz we’re gonna wanna be able to use other NVCs to show things, okay? So just to show this still works, the mouth curvature is still a full smile. There we go Okay we’ll pick this up next week >> For more please visit us at Stanford.edu