Learning Swift Attempt #3 - Draggable Views
Hey guys, this is Mac Heads 101. Today, I'm going to be trying to make another app in Swift. So the idea I had for today was to make an app where you can drag around certain objects on the screen and create new objects and such. That'll pretty much be it.
But let's go ahead. I'm going to call it "Bad Objects," and I'll hit next create. Of course, I will delete the tests immediately, so there we go. The second thing I will do will be to edit our UI. First, I'll make it an iPhone size, and I'm going to drag on a couple of buttons to create the different objects that we're going to be able to drag around on the screen.
By "object," I really just mean some kind of image of some sort of object. I'm going to be creating a class for each one just so that I can learn how to create classes in Swift. So how about I make one of them a piece of toast? If I recall, I'm going to have to make that button a little wider than it needs to be for some reason.
What other objects are there? How about a baseball cap? And what other objects exist? How about a MacBook? Yeah, that's appropriate for Mac 101. So, MacBook, piece of toast, and egg, baseball cap. Now, of course, I'm going to find the images for these, so let's just Google it. Boom!
Okay, so let's go to images. Wow, these are some really nice pictures of toast! I really wanted one with a transparent background, but I guess I can generate that myself. So I'll pick one without a shadow. Oh, that doesn't look too appetizing, though. Yeah, this looks delicious! Okay, we'll do this one. Oh, but it doesn't have a white background.
So in case you're wondering, this is pretty much how I make every single app. I just find images on Google Images and get rid of the background, and I'll do a lousy job because it really doesn't matter for this. Now I'm going to crop it to be a square—or square-ish—so how tall is it? 396? Can I get it that narrow? Of course I can! Boom!
It's not the best toast; you can see that cropping there was terrible. But who cares? So I have my toast. I'll find a baseball cap, and you know what? I'll probably speed up this process of me finding images.
All right, so I know there is a correct way to add images, and I think it's through this. I click on image.xc assets, and I'm going to add a new image set, I guess. Can I name it? Can I name it MacBook? Oh, I need a 1x and 2x! So, I got to decide now how big I want these images to be. I guess the normal one will be 44 by 44, and the bigger one will be... well, I guess the bigger one will be 88 by 88.
So here will be the 2x MacBook. So MacBook at 2x, and if I resize it to be 44 tall, this will just be the MacBook at 1x. I'm not sure if you're supposed to put "at 1x" before the 1x icon; in fact, I bet this does that for you anyway.
So I'm going to add the other two resources in the same way, and I'm going to speed it up again. Now I'm wondering why this toast looks so much smaller 1x than it did 2x because the image should be 44 by 44. You know what? Who cares! It doesn't have to be good.
Now I'm going to make... I guess I'll make three actions or maybe I'll just make one so that we’re done, and I can just use an if statement in here. Oh, and I'll get to try out a switch statement maybe. I'm not sure how that works.
So how about "object added"? Of course, here I should be able to just... should I be able to do this? I want touch up inside; that's when they actually touch the button and tap it like normal. Touch up inside.
Okay, now I'm going to look up switch statement in Swift to see if I could use that. I'm not sure if you can use that to compare strings. Oh yeah, we were already on this page the other day. So switch statement, and do they have any examples? Switch case.
So let's try switch, and oh, I gotta add a sender. So can I do this? Case MacBook break. Case cap break. Case, what was the other one? Toast break. Am I allowed to do this? Ah, tilde equals? What is that operator?
Yeah, so I do not see anything there. Could not find an overload for a tilde equals that accepts space applied arguments. Let's search this. That is so annoying that Google just doesn't recognize this one symbol, so it won't search it for me!
Wow! Okay, how about I try into a... I'm going to look up this to see if it declares that operator or if anything here does... tilde equals? Anything equatable is tilde equals able? Okay, that'll be a mystery for later. Maybe I'll play around with it at the end of the video.
But all this has taught us is that we say if the button, the title label.text is equal to maybe tilde equals for comparing like scalar values or something. But I don't want to make any wrong assumptions there. So this is how we'll do it with an if statement. I want to try to do it with a switch statement, but it's not possible, and that makes sense; in most languages, you wouldn't be able to put a string in a switch statement, so that's fine.
So now we have our if statement, and I'm going to save this. We probably won't need the GUI anymore, so I'm going to create... I think I thought I was going to create three new classes and have one for each object type, but we only really need one. I'm going to go, of course, to iOS Cocoa Touch Class, Cocoa case class.
What's a case class? Oh, that's for unit testing, which I specifically said we weren't going to do. Okay, so let's go ahead here, and I want it to be a subclass of UIView. I want to call it Object... oh, but there's no way I can call it Object. I'll call it ObjectView, and I'll click create.
Now I will drag it over with the rest of our classes, and if I recall, all I have to do is implement... I don't know, the thing is I like to use two tabs. Well whoops! I like to use two tabs, and when it generated my main source file, it looks like it used two tabs. But when it generated this new file, it actually didn't use two tabs, so that's a little funky. Not sure what's up with that, but our init...
We're also gonna have... you know what? Maybe we said trump class UIImageView so that way we can be an image. That's great! Okay, so I'm going to implement something called touches began, and look it has it right there. Touches moved is actually what I want, and I guess there's no return type.
So I'm not sure what the funk override... oh, I guess I need to type override because it's a subclass method, but I already had typed funk there when I hit for the suggestion, so it was still there.
Okay, so this is pretty neat, actually. The way I can... I have to specify that I'm overriding a subclass method just to put it in that way, it's more explicit. But anyway, I think I can do var touch: AnyObject? And isn't that cool? There's actually a type AnyObject!
Of course, now I can access it. So touch equals touch is AnyObject, and now I'm going to say self.center equals touches.location or touch.location in view self.superview. I'm not entirely sure how... uh, what a CGPoint is. Like, how do I create a CGPoint? Can I just do this? Yeah, oh, that's neat! So I can call it like a C function, and it looks like a normal constructor.
All right, so why does it give me a warning here? Touch inferred to have type AnyObject? I want it to be, I guess I want it to be a UITouch. Okay, and now that's very nice. I think this is all we're going to need here, and since it's an image view, we can set the image here.
So I'm going to create it here; I'm going to say ObjectView... oh, I don't need to declare it that way. View new view, and I'll give it a frame. And I do like CGRect. How about this? I can call CGRectMake. That's pretty nice!
So I'm gonna give it—I'm gonna start it at maybe a hundred, a hundred. The width will be 44 and the height will be 44 like we decided, and I'm gonna give it the frame. I really hope that worked. Do I have to do this? Yes?
Okay, and now I'm gonna do new view.image equals UIImage. Oh wow, I just started typing in Objective-C and obviously that crashed the editor because now there's no color anymore. Yeah, so that's not good. So UIImage, how do I do this? Image named? Why is it deprecated? I saw a red line through it, so it must be deprecated.
So let's look it up. Oh, that's not going to help us; I want to look it up in Swift where it's deprecated. So we'll look it up, UIImage image named in bundle compatible. Oh my goodness, image named, but that's also deprecated. That's not good!
So how do I deprecate it? But this is available in iOS 8 and later, so why is it... why is it red and deprecated, huh? Let's just look up UIImage image name swift. It's some sort of class method, but I'm not sure how class methods work in Swift.
Working with Cocoa data types, class method static... what are they even called? I don't even know. I'm going to look plus that thing. So okay, this page is not gonna have anything helpful, this page will not either. And great, that fantastic!
So, here's how you declare it; here's how you call it. That looks fine. So I maybe this isn't deprecated. I don't know why it was underlined. Well, okay, saying it now use object control construction. Oh, so they just wanted me to use a constructor instead.
Maybe that's a new thing in Objective-C as well. So, what is it called? MacBook, and here I'll do cap, and here I will do toast. You know what I can actually do? I'm noticing that the title is just the same name I used for the image file, so I can say new view.image equals image named b button.title label.text.
Is there like a lowercase string? There we go, and I don't even have to call it because it uses some magic getter stuff, and new view.content... there's like a content mode I want it to be scaled to fit that way the image fits in the view.
Finally, I want to do self.view.addSubview(new view). So perhaps this will already work, so let's see. Let's click on toast. Oh no, it crashed! That's something new, so we'll get to investigate this.
Object added? Object added? What is going on here? Send touch events? What is happening? Okay, so it looks like in our touch event method... oh no, and our object added method. Why is it saying unrecognized selector sent to instance? It's calling it on our view controller? Invalid argument exception?
Oh ha! Do we have to do that possibly? Or maybe I have to rehook it up now that I have those in there? So let's go back here, get rid of these because these are hooked up to object added without a colon, so they're not passing any arguments. Is that what's happening? That's kind of interesting because I replaced the...
Let's just test it out with this one, cap button. Okay, so I can't drag it around, but that's a separate problem. So I'm gonna hook up the other two buttons. Okay, and now I can create all these ridiculous objects on top of each other. Whatever, for some reason, I still can't drag them.
So let's see what happens if I put a breakpoint here. I never get it, so that's strange! Let's look it up! This is probably just a Cocoa thing. I'm not using any gestures, I don't think. I don't even know. There's no scroll view, there's no nothing.
So what is happening that is making this not work? What if I implement touches began as well? Wow, that is annoying how it keeps the override funk that I just typed. Is there some special type I have to implement? Or is it a void? It's a void, and is my type signature right? I assume it is.
What happens if I get rid of the override? It does recognize that it needs to be overwritten. So I'm going to print out touches began and touches moved. Literally nothing is putting out; it's not even getting that I'm touching it.
I'm just going to make it a UIView. self.backgroundColor equals UIColor.redColor(); I don't care! Here I'm not going to set the image. Why am I not allowed to do that? Oh, I need to call super.init first. That makes sense! Great!
So when I add an object, it's just a red square, and it works. I can drag it around, so why couldn't I drag around an image view? Huh, well, that should be easy enough because now I've narrowed down the problem to being an image view.
Okay, touch events. Wow, I keep taking... touch events, UIImageView, blah blah blah. Make your image view user interaction enabled. Ah, okay! So if I do that... oh, it's not... yes? Do I need to pass true? What is yes?
I guess yes. It's gone! It's too bad. It was the only thing that said Objective-C apart. Okay, so I can drag the objects around, and maybe it's not perfect because it snaps to the middle of them whenever I drag from any part of them, but it works. I'm pleased that I was able to figure out how to do that. Great!
Okay, now let's just look into the tilde equals operator a little more. So I'm going to look up... can I like go to this documentation type? Tilde equals? There's no... that's the problem with operator overloading. There's no way to like look it up.
I don't know how to find out what this is like equate symbol. That was something, so determines the equality of two values of the same type, numeric types. Now, the equatable looked like comparable, has less than and it should have greater than as well, but I guess you don't have to implement greater than; you only have to implement less than. Neat!
Printable has a string—get this is kind of interesting. I still want to find out, so where am I looking right now? Creating a string, operators, array, dictionary, equatable, comparable, printable, debug printable, sorting... I don't see any tilde equals. Or was it equals tilde?
Let's go back to the switch statement thing and let's see. Switch name, not swift statement branch statements allow the program execution. It really doesn't say much. Does it say tilde equals? Equals tilde? Huh, I'd like to try to overload tilde equals at some point to see what happens.
I'm going to do that in the next video I upload. I'm going to figure out all of this stuff about operator overloading, so tune in for the next video!
Anyway, thanks for watching! We did manage to make the app where you drag stuff around. I think this video was a little shorter than the last ones, which is great! So thanks for watching, subscribe, and goodbye!