Thứ Hai, 1 tháng 1, 2018

Youtube daily Jan 1 2018

How to install operating system in your Raspberry Pi first you need to format an

SD card of 8 gigs or more as fat filesystem type on Mac OS launch Disk

Utility select the SD card to format next select arrays give a name choose

format as ms-dos fat and click arrays

on Windows open file explorer controlled click on the SD card drive select format

next choose fat as the filesystem and click start to format

now you can install the operating system from raspberry pi org download notes the

easy operating system installer next unzip the noobs zip file and paste all

the files and folders inside the uncompressed noobs folder right to the

SD card

you

next insert the microSD card in your Raspberry Pi plug a mouse or keyboard

connect the HDMI cable to a monitor or TV and power it up by using the two amps

power supply next select raspbian

click to install and wait until finished installing

raspbian operating system

with a successful install the Raspberry Pi should now boot with this new

operating system and this is the easiest way to install raspbian desktop OS on a

Raspberry Pi I'd like to thank you for watching and if you find this video

helpful give us a thumbs up and I see you on the next PI videos Cheers

For more infomation >> How to Install Raspbian on Raspberry Pi 1 ,2, 3 EASY ✅ Install Noobs on Raspberry Pi MacOS, Windows - Duration: 2:48.

-------------------------------------------

"The Golden Ball" - Duration: 8:23.

History is filled with stories of eccentric people whose lives were littered with astonishing

and sometimes improbable stories.

Edward Hughes Ball Hughes (that was his real name) was one such individual- a man who spent

money so erratically that he came to be known by the rather fitting moniker of Golden Ball

Hughes or more simple, The Golden Ball.

Born in 1798 to a relatively well off family, Edward Hughes Ball enjoyed the finest education

money could provide, studying at both Eton and Trinity College in Cambridge.

He also enjoyed a brief stint in the army shortly after leaving college, serving with

the 7th Queen's Own Hussars right up until 1819 when he heard the news that a distant

uncle on his mother's side had sadly passed away.

As it turns out, this uncle had left the young man his entire estate, comprising of two homes

in London, an estate in Essex, and approximately £600,000, or roughly £50 million today ($66

million).

The finances from this inheritance were put into a trust to be doled out to Edward to

the tune of around £40,000 per year (the modern equivalent of about three or four million

pounds).

Around this time, Edward legally changed his name from Edward Ball Hughes to Edward Hughes

Ball Hughes as a nod to the uncle who'd left him his hard earned fortune, one Admiral

Sir Edward Hughes.

Soon after inheriting the money his uncle had painstakingly accumulated over his lifetime,

Edward Hughes Ball Hughes set about transforming himself into the epitome of an English dandy

by spending his inheritance as fast and as frivolously as he could.

Known for being extraordinarily handsome, with an enormous fortune now at his disposal,

Hughes easily assimilated himself into the upper classes of society, peacocking his way

onto the radar of the rich and powerful of the nation at every opportunity possible.

Found at virtually any party of note near London, Hughes, dressed to the nines, would

roll up to balls and galas in a custom made chocolate coloured coach pulled by matching

horses, invariably with a beautiful young woman on each arm.

Hughes' flamboyant dress sense and overwhelmingly affable personality saw him become popular

with the self-styled aristocratic dandies of the day, with his peers affectionately

referring to him as "Golden Ball Hughes" in reference to his fabulous wealth.

Despite his popularity, many preyed on Hughes' seemingly obliviousness to the value of money

and his love of gambling to fleece the young fop at every turn.

He was even known to be willing to bet many thousands of pounds on things as innocent

as a single flip of a coin.

Hughes was such a naive gambler, and so well liked, that in 1824 someone took it upon him

or herself to warn the hapless rake about ne'er do wells who were trying to take his

money, going as far as printing a pamphlet and sending it to him, which stated, among

other things:

Another observation I must make – you were chosen a member of White's Club-house on

the day of your marriage.

Listen, Sir, a WARNING VOICE; there are THREE members of THAT Club who have ALREADY marked

you as a victim to combinations you cannot detect, and to skill you are unable to oppose.

Ruin will follow your steps THERE; you cannot escape.

If you play in private, or at subscription houses you devote yourself to inevitable destruction,

and your whole family to beggary.

In these slaughter houses, carcass butchers of rank and title will knock down your whole

fortune in one night…

The day after the pamphlet arrived, Hughes went to that same gambling club and, indeed,

lost a relatively large percentage of his fortune in one night, a sum of close to £45,000

(about £4 million today).

Thanks to his massive and frequent losses, Hughes' was, at least according to one contemporary's

seemingly ironic account, "perhaps the greatest gambler of his day".

Maria-MercandottiShortly before this gambling debacle, in 1823, the 25 year old Hughes became

infatuated with a 16 year old Spanish dancer called Maria Mercandotti.

According to a contemporary article in The London Gazette,

Mercandotti, who had been gaining ground till she was at the height of public favour, on

the first night of this ballet (the 8th of March) took the part of the king's page

in this performance, and looked and danced it admirably.

Among the number of hearts on whom the bewitching eyes of the fair Spaniard had made an impression,

was that of a gentleman well known as a man of wealth and fashion, Mr. Hughes Ball.

This worshiper, like many others, had long and assiduously devoted his attentions to

Mercandotti; but she was one of those rare examples that now and then occur to ornament

the female biography of the stage, who, in a situation of all others the most trying

to the best virtues of woman, preserve unsullied the integrity of their reputation.

Nevertheless, a few months later, with a packed house set to see the young starlet perform,

she mysteriously didn't show up, forcing the manager to tell the audience the show

was canceled, ostensibly because Mercandotti was sick.

However, in The London Gazette report, it was later noted, "that Mercandotti had a

more agreeable cause of absence than ill health, and that she accepted the hand offered to

her, at length, by Mr. Ball."

When this fact emerged, noted English author William Harrison Ainsworth reportedly quipped:

"The damsel is gone, and no wonder at all that, bred to the dance, she has gone to the

Ball."

Less than a year after marrying Mercandotti, Hughes purchased a 3,233 acre property known

as the Oatlands Estate from the Duke of York where he and his new wife enjoyed the finer

things in life like hunting and banqueting.

Now, you probably think that we mean that the pair did those activities separately,

but this is the Golden Ball we're talking about.

Hughes found a way to combine the two endeavours, hiring a veritable army of servants to follow

him on his hunts carrying food, wine, spare guns and an entire wardrobe so he could change

and hold a feast whenever he got bored with the hunt.

Legal difficulties meant that Hughes didn't technically own Oatlands for three years after

he'd moved in because of an issue of the ownership of a portion of the property from

a previous sale in the late 18th century.

In 1827, Hughes eventually got so annoyed that he demanded his lawyers simply ignore

any objections to the sale using the age-old tactic of throwing money at his problem until

it went away.

By this point, the Duke of York had died and the sale was able to be completed without

much more delay, to the tune of about £145,000 (about £14,000,000 today).

A year after the sale was completed, the Golden Ball ran out of gold and the property once

again went up for sale.

At the same time, Hughes fled the country in the wake of the revelation that he'd

inadvertently gambled away nearly his entire fortune.

In one of the only sound financial moves of his life, Hughes wisely left control of his

affairs to the infinitely more capable hands of his solicitors, Frere and Forster, who

also took over management of the Oatlands Estate, even managing to turn a profit from

it.

Nevertheless, Hughes' debts were such that, despite the estate now being profitable, they

were forced to divide it up and sell it off piece by piece to hold his creditors at bay.

At the same time they were securing Hughes' financial future, his solicitors pleaded with

him to live within his means, agreeing to send him an allowance equivalent in modern

times to several thousand pounds per week.

This paltry amount apparently wasn't sufficient and Hughes racked up even more debt by gambling

and spending exorbitant amounts on food, wine, and clothing while in France.

To be fair, he was technically on vacation…

No doubt seeing the writing on the wall, or perhaps not happy with the change in lifestyle

Hughes' diminishing funds afforded, Mercandotti divorced him in 1839 in search of better prospects.

Even after his financial situation was once again secured thanks to the work of Frere

and Forster, Hughes never returned to England, though seemingly did learn his lesson, living

a "quiet" life, by his standards at least, in Paris where he had three children with

one Eliza Breugnot Momborne and later two children with Anne Henriette de Dauvet in

the 1850s.

Hughes died in 1863 at the age of 65, leaving behind an estate worth a little over £30,000

or about £3 million today.

While this isn't exactly a figure to be sniffed at, it's almost nothing compared

to the enormous sum he once had as his inheritance, an estate that even with mediocre management

should have seen him living lavishly, but still managing to increase his net worth.

For more infomation >> "The Golden Ball" - Duration: 8:23.

-------------------------------------------

🎮 Fun Girls Care Makeup - Ice Princess Dress Up Makeover Learn Colors Hair Salon - Fun Games - Duration: 16:32.

🎮 Fun Girls Care Makeup - Ice Princess Dress Up Makeover Learn Colors Hair Salon - Fun Games

For more infomation >> 🎮 Fun Girls Care Makeup - Ice Princess Dress Up Makeover Learn Colors Hair Salon - Fun Games - Duration: 16:32.

-------------------------------------------

'We need leaders who know that America is made up of neighborhoods' - Duration: 2:12.

For more infomation >> 'We need leaders who know that America is made up of neighborhoods' - Duration: 2:12.

-------------------------------------------

한채아 차세찌 열애|조회수4.989.283 - Duration: 8:17.

For more infomation >> 한채아 차세찌 열애|조회수4.989.283 - Duration: 8:17.

-------------------------------------------

Abandoned Railroad Back to Life Update - Duration: 8:26.

Hello ladies and gentlemen, RailROL82 here, your railroad archaeologist

I'm going to show you guys

sorry about that

I'm going to show you guys an update

here that I filmed a few months ago they're restoring this abandoned

railroad here and I'm going to show you guys I think I filmed it around May or

June I'm going to include a link in the description to the old video to the

video I shot at that time compared to how it is now so you guys can see the

progress. Okay so basically I'm going to also include a link to where I'm at a

Google Maps link so i'm at windsor avenue and service street here at

near West Palm Beach Florida Windsor and then this facing South

this is facing North right so here we see they recently did the pavement

marking

and there you see another northbound tri rail so it's a quiet zone right you can

see the no train horn sign and the rxr

okay and then back when I came a few months ago

This, there was no rail here I

think they had removed the rail and they recently installed this one you can see

the heavy equipment tracks here and then this is gonna be the connection

for the new crossing gate see the ballasts over here the concrete

ties but you can see when it was installed

the new grade crossing

this is facing North West this is facing South East okay so

there's a wye here, they're probably going to remove this old crossing here

because I just saw they have a foundation there for a new one which is

right here

There's no wires in there yet then obviously that's the old one

so

let me give you a zoom in here, here where you saw a trail that's the CSX and it

connects to the FEC over there right, way down there so there's a wye, you got

this one going that way and then you're going to see the other part of the Y where

I'm going to show you, so it's about two blocks south of

where I began filming as I said I'm gonna include a Google Google Maps link

this location and the original video that I filmed about earlier this year so

you guys can see the progress

and here see another southbound tri rail look at that

okay

alrighty guys so us abandoned railroad fans rarely

get to see happy news like this, here you can see that they're installing the

brand new crossing gates at this intersection

Got a progress signal base, gate mechanism WC Hayes, WC Hayes bracket there's no

no lights or bells or anything yet same on this side

We just got

signal base, mechanism and the mast

Progress signal base, WC Hayes gate mechanism, WC Hayes bracket we got that up top and then

this is the old boss buck, that's CSX s line mile post 96 7.85 crossing

number and emergency contact info it's maintained by the SFRTA so you got the

old and the new right there and last but not least let I show you this one

now I don't know why well okay I get it they had the original lights here and they

want to replace them but they're gonna replace them with cross gates so

I guess they expect a lot of rail traffic here and you see the new grade crossing

WC Hayes gate mechanism, WC Hayes arm

progress signal base well that should be

k

and then here you got the old one

WC Hayes old-school signal base look at that,

Safe tran lights

think those might

be incandescent you got no bell here, and the dot tag

sorry emergency contact info, dot tag do not see a dot dot tag on here

but I do see a safe trend bracket as well and then they got a porta potti

relay case in the back there and the old in the new over here as well

that one also has a WC Hayes signal base emergency contact info that's old-school

white ones safe tran lights and then you got the & the new

all righty guys I hope you enjoyed this video please comment below give me a

like and if you haven't yet subscribed to please subscribe so you can see more

Railroad archaeology videos like this, take care guys over and out

For more infomation >> Abandoned Railroad Back to Life Update - Duration: 8:26.

-------------------------------------------

10 Facts About H.H. Holmes, America's First Serial Killer - Duration: 12:21.

For more infomation >> 10 Facts About H.H. Holmes, America's First Serial Killer - Duration: 12:21.

-------------------------------------------

BREAKING!!! Markle CAN'T Marry Prince Harry – Her Secret Is OUT! - Duration: 5:05.

For more infomation >> BREAKING!!! Markle CAN'T Marry Prince Harry – Her Secret Is OUT! - Duration: 5:05.

-------------------------------------------

Fake News! Justin Bieber & Selena are both in Cabo for New Year's Eve - Duration: 3:16.

Hit the subscribe button and press the bell icon to get more take videos

Gomez calls Justin Bieber my husband is fake news a new report

Claiming Selena Gomez calls Justin Bieber my husband is fake news and not

Surprisingly the made-up story comes from Hollywood Life a site

That's so often shown to be fibbing that it's also called Hollywood Lee's

Gossip, Cobb can exclusively correct this fabrication. We're told it's simply not true

According to the repeatedly disproven outlet Gomez is so committed to Justin she even refers to him as her hubby

the side actually

Tips off that it's lying in the first paragraph of its article when it writes that Gomez and her friends are in Cabo San Lucas

for New Year's Eve with Justin reportedly on his way of

Course if the blog truly had a source close to Selena who contends she calls Bieber my husband wouldn't it know for sure

Whether he was on his way to Cabo San Lucas

rather than hedging by saying reportedly

That's hardly

The only sign pointing to Hollywood Lee's being caught once again spinning a tall tale

After noting how not everyone is on board with Gomez is rekindled relationship

With Bieber the site's seemingly fake source states, she started calling him my husband

naturally the habitually discredited Outlet doesn't mention in front of whom Gomez has allegedly called Bieber my husband and

Isn't it odd that?

Legitimate outlets like people for example have not reported this but only a blog that Gomez herself has called the worst

Does Hollywood Lee's really think it's leaders believe Gomez as friends are leaking information about her to her website she detests

Gossip cop will cut to the chase

Holyrood life sometimes publishes fake news on December 8th for example the site posted a made-up

exclusive story that falsely claims Selena Gomez and Justin Bieber have epic New Year's Eve

In that concocted tale based on another one of its bogus

Sources the out left wrongly asserted Bieber was going to whisk Gomez away on a trip where they can be totally alone

Like a deserted island that false food was then followed up by December

18th by an article titled Justin Bieber and Selena Gomez planning to spend New Year's Eve in New York below as

widely reported however

Gomez is ringing in 2018 in Mexico. Yes now the

Untrustworthy outlet maintains peeper and Gomez will not be in New York, but instead he will join her in cable San Lucas reportedly

regardless of Halloween DS pattern of posting complete wised

gossip, cops still fact-checked with an actual Gomez insider

And we're assured she does not refer to Bieber as my husband our impeccable source says the site's latest article is not true

As we enter the new year, maybe it's time for that outlet to resolve to stop making up fake news about Bieber and go

For more infomation >> Fake News! Justin Bieber & Selena are both in Cabo for New Year's Eve - Duration: 3:16.

-------------------------------------------

Stanford - Developing iOS 11 Apps with Swift - 6. Multitouch - Duration: 1:25:23.

[MUSIC]

Stanford University. >> Okay,

well welcome to Lecture 6, Stanford CS193P,

Fall of 2017. So today I'm gonna continue that demo that

I started last time. It's gonna be gigantic demo today,

covering mostly stuff having to do with custom views.

Then I come back to the slides,

just a few brief slides on multi touch and

how we do that. Then we'll go back to the demo and add some

multi touch gestures to our little playing card thing.

Here's the old slide of what's you're gonna learn today,

which you go back and look at this slide after the demo.

Then try to decide, did I learn that, well, we will find

out. By the way between last lecture and this lecture, I

went ahead and finished off a custom string convertible for

all three of these things. I just made suits custom

string,convertible return its raw value, remember its raw

values are these little equals things here. And then rank,

I had to actually implement a little description,

right there, where I returned A for the one. And then

a string version of a number, or the kind J, Q, or K. But

once I implemented custom strings convertible on

all three of these things. And then this code we had back

here where we just printed out ten random cards,

that prints out a lot nicer on the console.

So let's take a look and see what it does now.

See, it just prints it out here as kind of an abbreviated

version, which is, if you're debugging, it's a lot nicer to

be printing your cards out and seeing that.

And you might want to do the same thing in your assignment

number three as well. So that's it for that.

We've completely finished our model for

this MVC, that we're building here, this app,

this PlayingCard, so we have a deck of playing cards.

So now it's time to dive in to drawing these, these cards.

And we're gonna do that with a custom UIView subclass, which

is I'm gonna call PlayingCard view. Now you create a custom

view in the same way you create other classes.

So you're gonna do File > New > File. But here instead of

picking Swift File, which is like a UI independent thing,

you're gonna pick Cocoa Touch Class. That's because our UI

view is a subclass of a cocoa touch or UI kit class.

So I'm gonna call it, playing, playing card view,

it's gonna be subclass of UIView. A lot of other UI kit

things can be subclassed here, but the one I want is UIView.

And it says, where you wanna put it? By the way,

I just wanna remind you all, some of you are putting your

files at the top level, the project level, so they're

ending up like next to your X code project right there.

You really wanna be putting them down a level in here.

This is where we collect all of our classes. So just

a little reminder there, we're seeing that on the homework.

And so here's my UIView subclass, look at this, see?

Subclass of UIView, that's great.

And it even gave me a stub of a very important method here,

which of course, is our draw rect. Now, you notice this is

commented out, in this stub, that's because this iOS

actually looks to see if you have a draw rect.

And if you do, it makes an off screen buffer for

you, and all kinds of preparations for you to draw,

okay, and that's not cheap, it's not free.

So if you don't actually draw in your draw rect,

then you would want to leave it commented out.

Now why would you ever have a UIView, or UIView subclass

that doesn't have a draw rect? Well, that's actually quite

common, you do all your drawing with subviews,

consider UI stack view, right? It's a UIView, it does all its

drawing with views that are stacked inside of it.

It doesn't do any actual drawing itself, it has no draw

rect, right? But we are gonna have a draw rect, of course,

because we are going to be drawing a playing card.

Now I'm actually just, for example purposes here,

I'm gonna draw some of my card with sub views and

some of my card with this draw rect, okay. So that way you'll

get to see one view that actually does both. And

in your homework assignment, you're probably gonna have at

least one view that does subviews, and

at least one view that has a draw rect. So

you'll be able to see all that at action, in action here.

All right, so we got this PlayingCardView. Let's go back

over to our storyboard right here, and put a UI view,

a PlayingCardView basically, into our UI, okay.

So how do we do that? Well, how do we put views in our UI?

We go over here to utilities and down at the bottom,

maybe we drag out a button, or we drag a label.

And of course where is playing card view? Well, it's not in

here, of course, cuz these are all just the things that come

with X-code. But I can drag out towards the bottom here,

this guy, View, which is a generic UI view.

So I drag him out here and his class or

his type is just UI view. I'm going to make my background

a different color so we can see him a little better there.

So I'm just gonna select my background and change it to,

oop, orange, I love orange, there's orange.

San Francisco Giants colors right there.

So here's my kind of generic UI view.

And I don't want this to be a generic UI view,

I want it to be a playing card view, okay, cuz that's what

I've been working on. And the way we do that is

with the different inspector on the right.

You see we've been using this inspector right here,

the attributes inspector. Right next door to it is this

guy. This is the identity inspector,

it inspects the identity of the selected thing.

So here I have a view selected and it's of type UI view,

you see the class? But I can go here and change it to be

a playing card view. So now this is a playing card view,

and any time the system needs to draw it, it's gonna use our

draw(rect) right here. It's a code that we've written.

So that's awesome. Now I'm gonna do a little bit of auto

layout here that you've seen before. So this is nothing

new, but I'm just gonna put this up in the edge here,

put this one down here and I'm gonna pin it to the edges.

So my PlayingCard is gonna be kind of tall and

thin in portrait mode and kind of short and wide in landscape

mode, but that's okay, we'll fix that later. So

I'm just gonna drag up to the corner and set my leading and

top spaces to be pinned. And I'm gonna drag Ctrl+drag down

to this corner and set my trailing and bottom.

So they'd start there, so now if I go and

go into landscape mode right here, you can see that it

pins to the edges, so I have this funny shape. Now,

I'm doing this mostly at the start here because I want to

show what happens inside your view when your bounds change.

Because here when we rotate, our bounds are gonna be

changing very dramatically, from tall and thin to wide and

short. So before we dive into doing a playing card,

I'm just gonna do a little bit of drawing,

show you how drawing works with core graphics and

UI bezier path like we talked about in lecture. So

lets first draw a circle, just a circle in the middle of our

view using core graphics, and see what that code looks like.

So in core graphics, we always get the context first.

So we can't draw in core graphics without a context and

we get that in our drawrect by doing this

UIGraphicsGetCurrentContext. Now, this could return nil,

that's why we do if-let, but it will never return nil

inside your drawrect. Okay, it might turn,

return nil in other contexts, but in this environment,

it's always gonna return,

but we're still gonna do if-let right there. We could

do exclamation point where we're just gonna do if-let.

So now that I have a context, now I can tell the context to

do certain things, move to, okay, I can do move to.

I can do add line to, things like that. Add curve,

I can add these things that basically are drawing a path,

right, like a line moving around. So I'm gonna

make a circle. So I'm gonna use one called addArc.

An addArc is kinda cool, it just like takes a point and

then circumscribes a big arc around a circle.

And I'm just gonna use that to go all the way around and

create a circle. So when addArc is creating a path,

it wants to know what's the center of this circular

path that you're going on.

And I'm gonna make it be the center of my drawing area. And

what rectangle specifies my drawing area? Bounds, okay, my

var bounds does that. So I'm gonna create a CGPoint here,

which, whose x coordinate is my bounds midpoint.

And I'm gonna create the y coordinate is my bounds

midpoint in y. So I'm specifying right in the center

of my drawing area, which is my bounds. The radius,

I'm just gonna do 100 points, nice big circle.

The start angle and end angle here are in radians,

not degrees, not 0 to 360, it's radians, 0 to 2 pi.

Does everyone know radian? If you know what radians are.

Okay, everybody, great, so 0 to 2 pi. And 0, by the way,

is off to the right. 0 is not straight up,

as you might imagine, it is off to the right.

So I'm gonna start off to the right and

I'm gonna go all the way around my circle.

I can go either clockwise or counterclockwise,

it doesn't matter cuz I'm going all the way around. So

how do I go around? Well, that's 2 times pi. And

there's a really nice, little constant here,

CGFloat.pi. Okay, and that's how I can get pi in a CG,

as a CGFloat. And I can go clockwise or

counterclockwise, it doesn't matter. All right, so

now I've created some path, some drawing here.

So I can do other things in my context like,

I can set the LineWidth, for example, not the LineCap, but

the LineWidth, 5 points wide. That's a reasonably thick,

not super thick, but reasonably. I, of course,

can set the colors I wanna draw with using these static

vars in UIColor. Like let's say, green for our setFill.

That's our favorite fill color. And UIColor.red for

our stroke color. Okay, so I can set whatever colors. And

then I can ask the context for example, to stroke the path.

So let's do strokePath here. And you'd think I could then

say context.fillPath. Let's see if this will stroke and

fill, and it won't. And the reason for that is that when

we draw in a context, it's actually slightly different

than using that UIBezierPath I showed you in the slides.

In the context, when we do a strokePath like this,

it consumes the path. Okay, it uses up the path. And so

when we do the fillPath on the next line, there's no path.

We'd have to start again. So

that's one of the big advantages of UIBezierPath. So

let's do this exact same thing here, but using UIBezierPath,

all right? So I'm gonna say let path = UIBezierPath.

We'll start with an empty one.

It had, I'll show you later how to create a BezierPath to

start with a path. And then I can do the exact same things,

almost exact same methods as above. In fact,

I'm gonna copy and paste this exact same code right here.

The names are slightly different, in UIBezierPath,

but they're doing exactly the same thing, like lineWidth.

You don't say setLineWidth,

it's just a var on that objects. So you set it to 5.0.

You still set your colors by doing this. And

here the difference, though, as I can say path.stroke.

And that path, that UIBezierPath,

still exists as an object, so I can say path.fill.

I could also move the path over or

shrink it down a little bit and stroke it again.

You see what I'm saying? So I can use this path that I built

this arc over and over and over. That's the whole point

of kind of building it in this struct here, or this class,

UIBezierPath. So we'll get rid of that.

And let's see what this does right here. And it's gonna be

very similar, but, of course, it's going to stroke and

fill that path. Oops, did I press play?

Okay, there it is, you see, stroked and filled there.

All right, now while we're here looking at a circle,

I'm gonna do something interesting.

I'm going to rotate this phone to landscape. And what shape

do you think we're gonna have here? Anyone wanna guess?

Unfortunately, not a circle. We want it to be a circle, but

it's an oval. So why did we get this? Because by default,

when you change the bounds of your view,

it just takes the bits and scales them to the new size.

Which sometimes that might be what you want, but

a lot of times, this is definitely not what you want,

right? So how do we stop this? Well, what we want it to do is

to call this code again when we change our bounds and

have us draw the circle again in the new space. So

how do we do that? Let's go back to our storyboard here,

take a look at our view. If we inspect our view, at the very

top of the inspector, the very first thing is Content Mode,

Scale To Fill, right?

So it scales the bits to fill when the bounds change. And

we want to change that to be Redraw. So Content Mode Redraw

means call my draw rect again when my bounds change. So

now when we run, we get to see our circle. And

when we rotate to landscape, i's going to redraw, and

thus, draw it as a circle, which is what I intend.

Tha's what our drawing code that does,

it draws a circle. So that's important to note,

especially in your homework. You're doing these set cards.

You got your squiggles, and your diamonds, and all that.

You, when, if your bounds were to change in a set card,

you wouldn't want it to like squish it into some other

shape. All right, so that is enough of kind of

taking a look at drawing with Core Graphics and with

UIBezierPath. Let's settle down now to drawing a card.

Now what are the parts of a card? We've got the corners,

right? The corners of the card, which is the rank and

the suit in the corners. In the middle, we've got either

a face card image of some sort or we've got a bunch of pips.

Those little things are called pips. The hearts and clubs and

diamonds, we got a bunch of pips in there. So that, that's

how we got to build our card. But actually, the card has

another thing, which is almost always has rounded edges,

right? You know, if you've ever played cards,

you don't want sharp edges cuz it catches on things and

stuff like that. So you want nice rounded edges. So

let's start by back, drawing the background of our card

as a rounded rect. Now you actually know how to do this

using the layer of a UI view,

which was in assignment two hints. But

I'm gonna draw it directly, using a UIBezierPath. So I'm

just gonna say here, let path, actually, or you can call it

a roundedRect cuz that's what I want, in my background,

= UIBezierPath. And I'm gonna use a different constructor

than I used before. And you see there's a lot of them,

ovals and rects, but here's one for roundedRect. So

I'm gonna get, do this roundedRect.

It's asking me where you want your roundedRect to fit into.

So I obviously want it in my bounds.

It's gonna fill my entire bounds.

And then this corner radius is how many points the radius of

the turn of the corners is. And for now I'm gonna set

that to a magic number. We don't really want blue,

which is these literals. We don't want these in our code.

These are bad and I'm gonna get rid of that pretty soon

here. Why do we not want those? Because if we actually,

literally have magic numbers like that, we wanna collect

them all into some area where we have our constants.

So we can modify them and

understand what we've chosen and all that.

We don't spread it all out through our codes.

If we're ever going to change the constants,

we're looking at a round, round form. But for now, we'll

leave it this way. All right, so I got my roundedRect.

The first thing I'm gonna do to my roundedRect actually is

I'm gonna tell it that I want it to be the clipping area for

all my drawing. So as I've had this nice roundedRect,

which is the edges of my card, I don't wanna draw outside

that roundedRect. By Rect, my drawing all has to be inside.

Now, I don't think I'm gonna write any code that goes

outside. But in your assignment three, you might.

Because in assignment three, you're gonna have to draw

the squiggle shape. With arcs and lines or something, and

then one of the fill modes is striping. So you're gonna have

to draw up stripes in there. Well, imagine trying to draw a

stripe that goes from one edge of a squiggle to another edge.

This would be almost impossible.

Much nicer if you just have your squigle be a path,

add it as the clip, now you can draw those lines sloppily,

like you're a two-year-old in a coloring book,

draw them paths. And it'll get clipped, so

it's all inside the squiggle. You see why you want clipping?

So here I don't care so much, but I just wanna show you what

it looks like to call that. Now, I want the my card to be

white of course, so I'm gonna say UIColor.white.setFill().

And then I'm going to fill my roundedRect. My roundedRect is

just a Bézier path, so I can say fill.

So let's and see. This worked, cuz now, hopefully,

we should have roundedRect for our card. And we don't.

See it still has sharp edges up here, see these sharp edges

right here? Why does that still have sharp edges?

Well, actually, this code worked perfectly. It drew

a perfect white rounded rect on a white background. So

we cannot see it, it's sitting there on a white background.

So we need to go back to our storyboard here,

and change this so that it's not white background. So

what color background do we want for this thing? Actually,

we want it to be clear. Because when we draw a rounded

rect, we wanna see through the parts of

the corners that is rounded, to whatever is in

the background. So we want it to be clear. But

as soon as we start talking about clear and

see-through in our view, we need to talk about

this switch right here, the is opaque switch.

And as I said in the lecture, this is by default on, and

it's assumed you don't have any see-through parts,

no transparency, and it can be more efficient when it draws.

So if we do use transparency, which is less efficient,

but we need it here,

because we need our corners to show through,

we have to turn this off. So don't forget to turn that off,

if you're gonna do anything transparent in your view.

All right, now we have rounded rect. You see the rounded

corners right there, and we have it in both landscape and

portrait, okay. So that's good. All right, we're off to

a good start. Now, we're gonna do our corners.

So our corners, remember, are rank and suit, and I'm going,

it actually will probably be easier to draw the corners

with an NSAttributedString, directly in my drawRect.

Probably could do it in five lines of code.

But instead, I'm gonna use 15 lines of code, and

do it with a UI label.

Because I wanna show you how you can build your UI view,

out of other views, by making them subviews of yours. Then

we'll do some other drawing with drawRect, which will also

be only a couple lines, all very efficient to do.

So how I'm gonna do this on my UI label, is I'm gonna create

a UI label that uses an attributed string as its text.

And this attributed string is going to look like this.

So if it's gonna have, for

let's say, let's pick five of hearts. So

I'm doing the five of hearts, and this is the corner of my

big card. So I'm just gonna create an attributed string,

which is five carriage return,

heart. That's the attributed string I'm gonna create. To

make this work, my attributed string needs two attributes.

Attributed strings have attributes, I only need two.

One is the size of the font. I wanna make the font big if my

card is big, small font if my card is small.

The other thing is this needs to be centered,

cuz I don't want this five over here, lined up with

the left edge of the heart. I want the five centered over

the heart, right? And I might have like a ten of hearts.

This ten might actually be wider than the heart. But

I want these two things centered. So

I'm gonna show you an attributed string,

how to do fonts, and how to do centering of your text. So

let's create a little kind of utility function.

Pretty generic function. I'm gonna call it,

it's gonna be private, I'm gonna call it

centeredattributedString. So what this function

is gonna do is it's gonna take a string and a font size, and

return an NSattributedstring that's centered with that font

size. So it's gonna take a string,

some string as the string that we're gonna do. In our case,

it's gonna be five carriage return heart, and it's gonna

take some font size. Font sizes are CGFloats of course,

all photo point numbers in drawing are CGFloat, and

it's gonna return an NSAattributedString. So

that's what this little function is gonna do.

Because we need that to draw this corner piece. Okay,

let's do the fonts first.

So I'm gonna create a font. And to do that,

I'm gonna use those preferred fonts. Because this card,

what's on the card, is kind of user information, so

I wanna use a preferred font, not like the system font or

anything. So I do that with UIFont,

static method, preferredFont(forTextStyle.

In the text style, I'm gonna use is .body, the body font,

because it's really not a caption or a footnote or

a headline, it's kind of body text. But I'm gonna scale it,

and luckily, you can just say withSize to a font, and

give it the fontSize you want,

which is this argument to my method. So this is great, so

I've created a preferred font, the body font, and

I've scaled it to the right size that I want.

I'm gonna have to figure out what that size is for my card.

But there's one big problem with this.

If someone goes on, let's go to the simulator here.

Where's my simulator? And

if I go over to Settings on my device, and I go to General,

Accessibility, Larger Text. Look, I have a little slider

that can change the size of the text in all my apps.

Well, all my apps won't include this app unless I deal

with the fact that I fixed the font size here. So what I

really want, is something that's this font size, but

if they put that slider up, I want it to be bigger and

if they put that slider down, I want it to be smaller.

Luckily, there's a great way to do that, which is you can

just reset the font to be equal UIFontMetrics.

So this UIFontMetrics has a great feature in it, where you

can create font metrics for a certain text style.

Again, the body font right there. And

then you can get a scaled font from another font. So

you just give it a font, this one up here that I created,

and it will scale it based on that little slider. So

don't forget this line of code. Otherwise, users

who are visually impaired, or even just old guys like me,

who, you know, need big fonts, we set that a little higher,

and your app is not gonna do it. Your cards,

your playing cards, are gonna still have small text, so

don't forget this line, if you're doing fonts.

All right, how about the centering,

I wanna center the five on top of the heart.

Well, we're gonna do that with another little type, which is

called paragraphStyle. And I'm gonna create

an NSMutableParagraphStyle. So paragraphStyle

encapsulates all the things about a paragraph,

like its alignment and things like that. And so I just set

whatever I want in there. Like in this case, I want

the alignment to be set and I'm gonna set it to center. So

that makes the whole paragraph of text there be centered

horizontally. So that's it. Now, I can just return

an NSAttributedString with those attributes,

and I'm good to go. So let's use the same

exact initializer we used before. So here's the string.

That's the argument to the function right here, string.

And then the attributes right here,

I'm just gonna put the dictionary right in.

I'm not gonna put it in another bar or

anything like that. Let's just put it in. And so I

do NSAttributedStringKey .paragraphStyle for

example. So that's one of the keys, and the value is this

paragraphStyle I just created, and then I can also do .font

of fonts. Notice, I don't have to type this every time.

In fact, I don't even have to type it the first time,

because Swift knows what type of argument this thing takes.

So, it automatically will infer that part of this. So

that's it. Okay, nice reusable function that will create this

kind of attributed strength. So

now I'm gonna create a little private var, which I'm gonna

call cornerString. String,

and it's just gonna return a centeredAttributedString with

this, the five over the heart. So somehow I need to have my

rank plus a carriage return, +suit, and then I'm gonna,

woah, then I'm going to need, some font size.

Who knows what that's gonna be?

Well I have to talk about that,

because its got that font size. It's gonna depend

on how big my card is. My card is big, that's gonna be big.

So we have a couple of things to deal with here. One,

we need the rank and suit. So the playing card has to have

some way to set the rank and suit. Now, I'm gonna make my

rank be an int, and I'm gonna make my suit be a string.

Now this is different than the model we had.

The model had rank and string be enums, remember that?

But who cares? This is a view, it knows nothing about that

model. This is a generic card drawing view.

It does knows nothing of that particular model. So

the fact that it represents its rank and

suit in a completely different way, perfectly fine.

Whose job is it to translate between model and view?

Of course, the controller. So yo're, w're gonna see code

in our controller that translates between the models,

thought of what a rank and suit is in this view.

I also, I don't wanna have to

be an initializer there, it's used as no initializer. So

let's start, let's start with this 5, 5 of Hearts.

Let me go grab a heart from, over here. Here's heart,

copy. All right. So we got 5 of hearts right there. And

there's one other thing too, which is, is this card face

up or face down? So I need a, isfaceup. She's a bull, and

we'll start with a face up, let's say. Now,

when you have vars like this in a view that affect the way

the view would draw, you have to think about the fact that

if this changes the rank, Your view needs to redraw itself,

right? If you change the rank, you gotta redraw. So

how do you do that? This is a really great use for didSet.

So when this rank changes,

someone sets the rank to 11, for a Jack, we gotta redraw.

And how do we make ourselves redraw? Everyone, remember?

setNeedsDisplay.

So that's gonna cause our drawRect to be called,

eventually. So we can't call our drawRect directly. We just

have to tell the system, hey, we need to be displayed.

Our view has another little thing that needs to happen.

We have subviews to drop part of our view, so

we need to have those subviews laid out.

Now, we're not using Auto Layout in our subviews,

we're putting them where they belong in the corners, but

we still need to say setNeedsLayout as well. So

that our subviews get laid out.

Now you don't have to say this if you don't have any subviews

that need laying out, or

that aren't affected by the rank changing. In our case,

it definitely does change the rank. So

we're gonna do that for all of our little public vars here,

because if people change any of these things,

it's gonna change the way our card looks.

Don't forget this piece right here, always gonna want that,

either one of these two, or both, on every time you have

a public var, that someone can change the look of your card.

Okay, so now, we have rank and suit.

Unfortunately, rank is in int, so I can't say rank +suit. And

then also, I have this problem with this magic number here,

somehow I have to pick a font size.

So in order to speed this demo up a little bit,

I actually have a little extension to my playing cards.

Oops, there it is, this little extension right here.

This is the entirety of it, it's not very big. And

this has captured all of my little blue numbers,

my magic numbers, into a struct as static lets.

So this is how we do constants in Swift.

We make a private struct, we give it a name, sometimes it

might be called constants. I've called it SizeRatio,

because all of my constants are about the ratio

of the corner, or of a font, to the size of my card.

So I call this SizeRatio.

And then in here, I have the cornerFontSizeToBoundsHeight,

I have the cornerRadiusToBoundsHeight,

I have the cornerOffsetToCornerRadius,

I have the faceCardImageSizeToBoundsSize.

These are all ratios that I've picked, that I think will

look good. Then I even created some little computed

properties like cornerRadius, which takes the height, and

multiplies it by the ratio. So here's what it looks like to

use a constant that's declared like this, SizeRatio.whatever,

or if you have a constants, it might be constants.whatever.

You see how this kinda looks nice right there.

That's how we do it.

So I have these 3 things,

cornerRadius, cornerOffset, and cornerFontSize which would

have allowed me to get rid of blue numbers.

Instead, use something that's with respect to the size of my

cards' height. I also threw this whole guy in here,

rankString is just a var that turns 1 into A and 11 into

J and 12 into Q, and all the other ones into a number. So

that I can have a string that allows me to go up here when

I'm creating this little string right here. Instead of

saying rank plus character term plus suit, I'm gonna say,

rank string plus character term plus suit.

This, this is the, this means character return, right?

Go to the next line. And so now,

my font size can be this cornerFontSize, one of these,

once I created down here. And similarly, my cornerRadius

right here which was 16 can now be cornerRadius.

That's another one of these that I created. So see

how I've segregated off all of my constants into this nice,

little I even used some extension.

It wouldn't have to be an extension, but

I just put it off in its own space. And while I was at it,

by the way, I also added some extensions to CGRect and

CGPoint like zooming a rect, or sizing into something, Or

getting the left half of a rect, just for convenience.

It's gonna make my code look a little cleaner.

And you already know about how to do that.

We did that with the art for a random and int,

stuff like that. Okay, so we're getting very close to

making this work right now. All we really need to do is

create these UILabels. So I'm gonna create a var for them,

private var. I'm gonna have an upperLeft,

upperLeftCornerLabel, okay,

which is gonna be typed UILabel. And then,

I'm gonna have a lowerRightCornerLabel

to UILabel. Now, I need to create this UILabel,

so I'm gonna create a little function to do that,

private func createCornerLabel, and it's

just gonna return a UILabel. This is gonna be really easy.

I'm just gonna create a UILabel and return it, but

I have to do a little bit of configuration of this.

We'll get to that in a second. So here, instead of this

declaring this label, I'm gonna say =createCornerLabel.

And then here, createCornerLabel, oops,

not Repl_host, how about createCornerLabel.

All right, now, this is going to Once it catches up to me

and compiles, gonna create this error.

What is this error right here? Cannot use instance member

'createCornerLabel' Label within a property initializer.

Well, of course, I'm initializing a property here,

and here, I'm trying to call a method on myself. And

we know that until we're fully initialized,

we cannot call methods on ourself. So with this,

this is the old catch 22. So anyone wanna say how we could

fix this? Okay. Lazy. Good job, everybody. All right.

Lazy, exactly. So lazy makes it, so

these things won't be initialized until they

which will be after the thing is fully initialized. So,

are asked for,

this is equals. All right, so we have this UILabel.

What do we have to do to initialize our label? Really

only a couple things. One is I need to set this bar on label,

which is number of lines, because the default is one.

By default, a UILabel has one line. So if I have a two line

thing, like five\n hearts, it would only see the five.

The heart would not be shown. So I'm gonna change this to 0.

I could change this to 2, but I'm going to change it to 0.

What 0 means is use as many lines as you need, Mr.

Label. So I'm taking it to 0. So that's really the only

thing I have to say. The only other thing I have to do with

this label is add it as a Subview of myself.

If I dont add it as a Subview, then it won't be there,

it will never draw. Okay? So I have to add it as a Subview.

So that's all you need to do to create a CornerLabel.

But, I need to position these labels.

I have to put them in the right place, right? So

I should put one in the upper left and one down in the lower

right. So, where do I do that in my code? Well,

I have to do that every single time my bounds changes,

especially for the one in the lower right. Okay.

The one in the upper left is actually near my origin.

It's probably gonna be right no matter what my bounds are.

But the one in the lower left, in landscape,

it's way over to the right and not down very far, and then in

portrait, it's way down and only a little bit across,

right? So that one in the lower right is moving all over

the place when our bounds change like that,

when we rotate or any reason for

reason our bounds would change. So where can we put

some code that does something when our bounds change?

That's what this method, layoutSubviews is for.

To UIView method, make sure you call super,

because UIView is awesome at laying out Subviews.

It uses auto layout. All that auto layout stuff we're doing,

that's all stuff that UIview knows how to layout

your Subviews. Now, these two Subviews,

I'm not doing any control dragging. In fact,

I'm creating them in code, right? I created the UILabel

in code right here. So, I have to do the layout myself, and

layoutSubviews is where you do it.

Anytime your Subviews need to be laid out for any reasons,

this is going to get called by the system. You don't call it.

If you want it called, you call setNeedsLayout.

And setNeedsLayout, the system will eventually call this.

Just like if you do setNeedsDisplay,

the system will eventually call this. Okay?

Very, very similar. All right, so we now layoutSubviews.

All we gotta do is move this UILabel, this upper left, and

lower right labels, move them to the right spot. So let's do

the upper left, that's a really easy one, actually.

So I'm just gonna set my upperLeftCornerLabel.frame.

Remember, frame, in a UIView, is what positions it,

bounds is where we draw, frame sets it. So

I'm gonna set its origin basically equal to my origin,

but offsetBy, so I added this little offsetBy in CGPoint.

It just moves the point over by some amount,

offsets it. So I'm gonna offset it by this

cornerOffset that I have. So the cornerOffset,

which is one of these things I made from my constants here,

that just gets passed the little curve.

I don't wanna draw this with the curve right here, so

I need to move it in a little bit from the roundedRect.

Okay? So that's it. Now, we're not quite there.

We've positioned it, but we haven't actually set

this string on it. So I'm gonna create another little

function here I'm gonna call configureCornerLabel,

and I'm gonna pass that upperLeftCornerLabel to it.

And inside here, it's a little private func. We will pass

this label. We don't really need an external name, because

the name of the function implies the external name,

it's UILabel. So here, I'm gonna configure it.

And I don't actually have to do very much to configure it.

One thing I for sure need to do to this label is set it

attributedText to be my cornerString. Remember,

cornerString is this thing up here.

This little guy just gets a centeredAttributedString with

the rankStrin\n suit of the right size,

depending on how big our card is.

So we definitely need to do that.

What else might I need to do to my label when I do this?

Well, one thing is I want the label to be the right size.

Okay? I want it to be kind of the perfect size to enclose

this thing. Luckily, label has a method called sizeToFit, and

it will size the label to fit its contents. The only tricky

thing about this though, is if that label already has some

width, and you say sizeToFit, it will make it taller and

keep the width. Well, we don't want that.

We wanted to do the whole thing, so I'm gonna say,

label.frame.size = CGsize.0.

So I'm gonna clear out its size before I do sizeToFit.

That way, it will expand in both directions, across and

down. That's a little old trick about sizeToFit you

gotta know there. And the last thing, really tricky thing,

is what about if we are not face up?

Do we draw these corners not face up? Of course not.

We don't want the back of the card to have that. That would

make it really easy to play a lot of games if the back of

the card had corners on it. We don't want that,

so I'm going to configure the label to be hidden,

not highlighted. Hidden, if we're not face up.

Okay? So if we're face down, then I'm gonna be hidden.

So here's the example of using Hidden.

It keeps it in the Subviews, list, in everything,

keeps it in the right position, just hides it. Okay?

Instead, we're gonna draw the back of our card,

whatever that looks like. Okay. It's a good example

using isHidden right there. Okay. It should work.

Let's take a look and see if we can get that upper,

at least this upper left one to draw. There it is.

Five of hearts. It looks good. Let's see if it works when we

go to landscape. Whoa! Not only it's right position, but

look, it's smaller because the card is shorter, so

we don't wanna use half the card with our big font.

So that's good. What about the other corner? Okay,

well the other corner is a little harder to position

because our origin's in the upper left and

we're trying to put away down to the lower right.

But it's not that bad, so let's just try and

do it. This is our lowerRightCornerLabel. It's

frame.origin. Well, I'm gonna build this incrementally. I'm

gonna start by making a point, which is my bounds.maxX, so

all the way over to the right, and y is my bounds.maxY,

that's all the way down to the bottom. Okay? But

I can't put it there. If I try to put it there, here let's

draw a little picture so you can see. I'm drawing the lower

edge now. Okay, here's my lower edge of my card and

I'm trying to put this thing here. So I can't put it here.

If I put it where this is, this would be the origin,

it would be down here, not even on the card. So I need to

move this point first inside the corner offset, then,

the whole distance of the width and height of this

little thing, so I need to kinda make a double jump here

to get this origin up here, so this will draw there. Okay, so

I'm just gonna do double offset by.

The first offset by I'm gonna do is -cornerOffset and

-cornerOffset that gets me pass the roundedRect.

Then I'm gonna offset again

-lowerRightCornerLabel.frame.- size.width,

and -lowerRightCornerlabel.frame.-

size.height. You see how I had to move the origin

back up there, everybody cool with that. Okay, so

that positions it, this is wrong, cornerOffset, right?

So that position is it, of course we have to configure it

as well. So let's just do the exact same thing here but

we're gonna configure our lower right. Because it needs

to be configured in exact same way. And use the corner string

whatever, so, let's see what it looks like. Lower right,

oops. I didn't finish there lowerRightCornerLabel,

all right Okay, whoa interesting.

Well that's not quite right is it?

Okay, it's in the right spot but that five hearts

should be upside down, right? If you look at a card,

a playing card that would be upside down, okay.

So, how the heck am I gonna turn that thing upside down.

Well, that turns out to be super easy

in iOS because every view has a var on it,

lowerRightCornerLabel has a var and it called transform.

And transform is what's called an affine transform,

how many people know what an affine transform is? Okay,

nobody, basically, almost.

So an affine transform is really simple,

it's just a blob, a thing that represents a scale,

a translation, and a rotation. Okay, just those three things.

So you can take a UI view and rotate it, scale it, and

translate it all you want with just this one little var. Now

of course we are positioning things with the frame and

stuff like that, but this is an additional way to control

it's positioning, scaling, and rotation.

Now this is all going to be bit wise translation. So

it's going to be translating the bits. So if you make it

bigger, it might look kind of jaggy, edged, pixellated.

But we're not going to make it bigger. Instead, we just want

to rotate it. So you might think we can just do this.

Let's take the AffineTransform.identity

transform, so that means unrotated, unscaled,

untranslated, just an identity. And

you think I could just say rotate it.

By the way, transform only has three methods.

Rotate, transform, and scale, that's all it's got. So,

if I created a rotated one, how much would I want to

rotate this if I wanted to turn it upside down? Okay,

in radians? Pi, right? Cuz I want to turn,

turn half way around okay, so it's upside down. So I could

just say CGFloat.pi, but this would not actually work.

This is close but doesn't work so let me show you why that's

not gonna quite work. So if this paper here would do this.

Okay, so here's my corner right here and here's where

this five hearts thing is right now. It's, right side up

like this. Actually here we'll do on a piece of paper. So

here's my five of hearts. And I want it to be

upside down like this, right? Okay, that's what I want.

But, if I rotate it, it rotates around the origin. And

our origin's upper left. So if I rotate it, Pi, whoa,

it's gonna be up there. You see the problem? So

it will be upside down but not in the right place.

So I need to both rotate it and translate it. So

what I'm gonna do is I'm gonna translate it first down to

here to its other corner then I'm gonna rotate it. Woho,

it's gonna work.

Okays So let's do that. Where are we, where is my rotator?

Here's the rotator so I'm going to keep that rotated.

I still want to do .rotated but I want

to do a translate first so I'm going to stay .translated

by and how much do I want to translate by? I want to

translate by the whole width and height of my lower right.

lowerRightCornerLabel.frame.s- ize.width and

the lowerRightCornerLabel.frame.s-

ize.height. So I'm taking the identity, I'm translating it

down to the corner, then I'm rotating it. I could also

have kinda translated it to the center and rotate it and

then move back. That's another way commonly to do

that rotation. But here we go, it's upside down and

it works, even in other bounced sizes. Okay,

excellent, so we've used the subview. We've used layout

subviews to make it always be in the right position,

all is looking well. Let's go check and

make sure that our slider,

remember this slider over here in settings. Remember we can

set it larger, let's go make sure this is working.

I'm going to set this to quite a large size font. And

hopefully when I go back to my app,

it should have a large font but it doesn't.

Why doesn't it have a large font? That is weird.

Well actually, it does, it's just it never redrew.

If I change my bounce, and flip back,

now I get see the large font. So that's a problem.

When that slider moves we need to find out that it moved. And

you can do that in view with a function called

TraitCollectionDidChange. So

traits, we're gonna talk about traits in a couple of weeks.

Traits have a lot to do with are you rotate, are you

landscape, are you portrait, things like that are traits.

But also, your size category in general for your font. So

trait collection gets called whenever those things change.

Here, I'm just going to setNeedsDisplay and

setNeedsLayout, okay. So with my traits,

the thing that control how we draw change,

then I'm gonna redraw. So now if we go back,

right now our fonts are big if we set them big,

so they're gonna start out big. And after I go back and

set them to be small over here in my settings,

go back to normal size, oops, sorry. I'm gonna, got that,

what? There we go, so set it back to normal. Just go here,

go back to our playing card and it rejoint normal.

Okay, because it found out that that slider had moved. So

minor little thing you've got to remember to do this and

we'll talk a lot more about traits down the road. Let's go

back, and do a little bit of layout stuff, take a little

break from drawing our card, and do layout. So right now,

we've got this thing where this card takes up the whole

space, actually, I'm gonna make the card wide again so we

can see it a little better. So I'm just going back here and

make it wide, so this card is not really card-shaped.

Cards are not tall and thin like that and they certainly,

cards are definitely not like this card over here,

no cards look like that. That's ridiculous,

we don't want that. We want it to look more like a card, and

what makes a card look like a card? Well,

it's its aspect ratio. Right, the width, the relationship of

the width to the height, so we want to change that. So to do

that we can't have the edges pinned to the edges anymore.

So let's take our constraints to the pin it to the edges and

instead of making them pinned let's make them be greater

than or equal so that we, our card doesn't go off the edges

but it's not pinned to the edges either. So

how do we do that easily, or you can find out all

the constraints that are on a view by just selecting it and

going to this other inspector on the other side of your

attributes inspector, called the size inspector.

See here's my constraints, these are my four constraints.

So even as I mouse over them, look, they highlight.

So, right now they're all equals, they're pinned.

Okay, equal sixteen, pinned to the edge, equal sixteen.

You can change that equals just by editing them and

changing it to greater than.

We actually did this last time and we can do that for

all of ours. Just let them all just be advisory.

And let's not do the bottom right up against the bottom,

let's go ahead and just do greater than or equal to. And

same thing here, greater than or equal to and we'll do 16.

So it's at least the same on all sides.

So now, these constraints on the edge are just advisory.

They're just saying make sure you don't go past 16 points

from the edge. So that's great. But now,

the lines are all red, you see how everything's turned red?

That's because we no longer specify where this card's

supposed to be anymore. Since we're not pinning it to

the edges, where it's supposed to be. Well, let's first fix

this aspect ratio problem. Okay, I want the card to

have an aspect ratio, you know, kinda like the ad or so.

Basically, five across to eight down seems to be typical

card ratio. And it turns out you can

fix the ratio of a view by doing control drag.

But you don't control drag to another view like we do when

we're pinning to the edge. You control drag to itself.

When you control back to itself,

you're offered the option of fixing the width, the height,

or the aspect ratio of this view. So I'm gonna fix

the aspect ratio. So now, I've added a constraint,look

at it over here, that fixes the aspect ratio.

Now of course, I don't want aspect ratio to be 259 to 461.

So I'm gonna edit to make it five to eight.

So I fixed this after that.

This still doesn't say anything about where the thing

is supposed to be or what size it's supposed to be or

anything like that. So let's put another constraint that

says it's gonna be right in the middle.

So you see how I used the dash blue lines to drop it

perfectly in the middle? Now I'm gonna control drag from

the card back to my outer view right here. And this time,

instead of doing trailing in top which I already have those

greater than or equal to ones, I'm gonna pick center,

horizontally, and vertically. And you notice this says,

horizontally and vertically in safe area. So

every view knows it's safe area.

It's safe area is the place it can draw without overriding or

impinging upon other views space. So for this

orange view, it's safe area does not include this place

where the facial recognition and the time of day.

All that up here, so it wouldn't draw up there.

It also does not include this little bar down here.

If there were bar buttons along the bottom or a title

across the top, it wouldn't include that either and

that's all automatic and not only automatic, as it changes.

This constraints will automatically adjust to that.

So, if you put a title on the top of this view and

let's say very move down, then my card would move down to be

the center of the new safe area. So that's what safe

areas all about. We are always creating constraints between

view safe areas, all right? Okay, so now I've said where

it is but things are still red. Why are they still red?

Well, because I haven't said how big this view is.

I've said what it's aspect ratio is and where it is and

I've said that it can't go pass the edges but

I haven't said what size it is. A very small card would

satisfy all this constraints over here, right?

Very small card would be going out the edges. It could be

the right aspect of ratio, it could be the middle or larger

cards that doesn't go out to the edges, could fulfill all

these, all right? So, how do I tell the system, I want you to

be as big as possible and still satisfy this? Well,

I'm gonna do that by pinning. By dragging to myself,

my width. And I'm gonna set my width which is currently 259,

I'm gonna edit it. By the way, that fix the problem cuz now

look no red because I've set how high it is.

But I want it to be bigger. I'm gonna say I want it to be,

let's say 800 wide. Okay, now as soon as try to

have a constraint to say this is 800 wide.

Wow, we went red again. Now why are we red? We're red

now because these constraints can not be satisfied.

There is no way you can be 800 wide and also no

go off the edge. Basically, so that's the problem.

Now, how are we gonna fix this? Well all these

other constraints besides the width I got to have those.

If I don't have those edge constraints,

it could go off the edge, got to have it. Aspect ratio,

that's what I want card to look like, got to have it.

In the centre, I definitely want the card in the centre.

Width, well I wanted it to be 800 but

really I just wanted it to be big.

So, that 800 width is not as important to me,

in other words, it's lower priority constraint.

So, I can tell the system that by going over here and

editing this constraint, and changing it's priority.

You see priority 1,000 right there?

That's is the max priority, that is required priority.

So, we can pick any priority less than a 1,000 cuz all of

these are at 1,000. And this will be less important.

So we'll still try to satisfy it as best we can.

But it won't override any of the other ones.

We do that by clicking on the priority.

We could type a number, or

we can pick some kind of well known ones,

like high priority. And whoa, look what happened.

All the red went away, it made the thing as big as it could.

It's still satisfying all the constraints.

It's doing that both here and over here.

See, it made it as big as it could and still have that

five to eight aspect ratio in the middle. So,

that's the magic of constraint priorities, okay. Making

constraints that don't matter as much have lower priority.

So we'll try to give you as much of them as it can but

it will give in on those lower priority ones.

Everybody cool with that? Okay, so now we got this thing

looking more like a card. It's got a card aspect ratio.

So let's turn it back to clear, here. And go back to

drawing it, because we still have only done the corners and

we need to do the rest. So let's next to do the face in

the middle and of a face card, we need some kind of image.

I'm going to do that by drawing an image,

and I just happen to have over here, somewhere,

not this. This guy right here.

Face cards, a bunch of face card images. Woohoo, okay.

And I'm just gonna drag all these images into my project.

Well, where do I put them? That's what this

Assets.xeassets is for, the place where the icon was here.

You can drag any images you want in here.

So, I can go grab all of these images, drag them all in.

Now when I do that, it looks like some of them didn't come

in, these ones that say @2x.

You see, @2x? No, those didn't drag in. Yes, they did.

That @2x means it's the same as the one that doesn't have

@2x, but it's twice the resolution.

So it put them as a 2x version, twice resolution.

Now, some devices have three x resolution, like iPhone plus

for example. I don't have any cards in that resolution so

it'll fall back to using the 2x resolution.

But I probably should add 3x resolutions to all my cards.

Now these jpegs that I dragged in,

this is telling me the name of it. And it got it from

the file name of the jpeg, but you can rename these to be

whatever you want.

I've conveniently named them Rank suit. Okay? So that I can

find them. And putting these images in my face card is just

a matter in my draw(rect) of looking these up by name. So

let's go to our playing card view. Back to our draw rect

where we draw our roundedRect here. Now we're gonna say if.

We can let the facecardimage =, better

go wide here, = UIImage. So UIImage is a thing that

represents an image, and if you look at its constructors,

it has quite a few, but one of the ones it has is,

named. And now you just specify the name, and this

name has to match this name that's in xcassets over here.

Okay, so that is our rank string,

Plus our suit. Okay, so that is the name. So if we're able

to find that then we must have found a face card.

So now we're gonna just put that face card image.

Draw it and we draw by saying .draw In and

I'm gonna draw it in my bounds but actually I

don't really wanna draw that face card in my full bounds,

it might smash into the corners, right?

So I'm going to take that bounds and

zoom it down a little bit by one of my constants down here,

this constant right here, so

this is SizeRatio.FaceCardImageSizeR-

atio and I currently have it set to be 75%. So I'm gonna

have my face card be 75% of the full size right there.

And that's it, that's all you need to do to draw images.

Really easy to get them by name and

then just draw them in some rectangle. So let's go change

our card to be a face card, how about, let's say a Jack,

11 is a Jack. Make sure this draws and

it should be 75% of the size of card here.

There it is, it is and when we rotate it draws it smaller.

Cuz it's drawing it compared to our bounds,

which our bounds are changing when we rotate. So

that's super cool. What about pips? So what if we head

back to having the rank B5, then in the middle we draw

five hearts, five little hearts. Well, I'm not gonna

waste our lecture time going through code that does that,

because it's pretty straightforward code and

you're not gonna learn anything new.

You can certainly look at it offline,

I'll be posting this code online. So

I have it right here though, it's called drawPips. So

there's this function drawPips.

The way it works is data driven, so like for the five

rows goes two pips, and then one pip in the middle, and

then two pips at the bottom, right? Or an eight is two

two two and two, etc, so it's just data driven. And

it literally just does a for loop and goes through the for

loop and draws either one pip or two pips and

just goes down and draws however many rows there are.

It does have this kinda cool little embedded func,

you notice that functions can be inside functions in Swift.

This createPipString just creates an attributed centered

string, but it does't have the five. I's just the pip

part of it, but i's still centered which is nice so

it draws it in the center of the card. And it kinda picks

the size by guessing what the right size would be and

seeing how big that is and then adjusting it so

that it picks the perfect size pip to fix,

to fit the space that's available. So you can look and

see how I do that using center attributed string there. Okay,

that's pretty much it. So if it's not a face card, then we

want to drawPips, so let's see if that works for our five.

Looks pretty good and let's see, we'll rotate it, smaller,

it all got smaller. So easy to do this stuff, right?

Now we kinda are at a point with this thing,

there was one other thing, sorry,

we have to draw which is the back of our card, okay.

So it really should only do this stuff if it's face up,

all right. Should only do the face card in the pips if it's

face up and we already made it so that if it's not face up,

it hides our little labels, right?

It is hidden, hides our labels so that's good. But if our

card is face-down then we need to show the back of the card.

So I'm gonna do that with an image as well.

I'm gonna say if let cardBackImage = UIImage

again, named, and I'm gonna call it cardback.

So I'm gonna look for

an image named cardback and if I can find it, then I'm gonna

have draw in. And this time I'm gonna draw it in my entire

bounds because it's not gonna hit any corners,

the corners aren't there because I'm face down. So

I need an image named cardback. So I'm gonna over

here to assets and I have to put an image called cardback.

So I'm gonna grab this image right here,

it's my Stanford image. And I'm just gonna rename

it right here to cardback, so this is my cardback.

Notice it only has the lower resolution version there,

it didn't have an add time 2X but

I can drag higher resolution versions in to provide higher

resolutions just like that. And this one is so

high resolution, it's got a little tree in there even,

okay and that's perfectly fine. No law that says it has

to be just a scaled-up version of the same thing. So

now I have cardback there, so now, let's go and make our

card be face down by setting our isFaceUp here to be false.

Okay, and run, and we'll see the back side of our card.

And hopefully, we don't see any corners,

we don't see any face, we don't see any pips. We won't

see any of that stuff, we'll just have the back of our

card. And this is a high resolution device so

we got the 2X version. And you can see it's actually

kinda jaggy, we really could use a 3X version here,

it would be nice. Okay, now the next step if I were really

developing this is I would want to go up here to my rank

and suit and try every rank and every suit face up and

face down, and make sure this all worked.

Well, can you imagine if I had to do this. Okay, make a six

and then a clubs and run. No, okay so it's seven and run.

It would be tedious as all get out to be going back and

forth running. What would be awesome is, so I can just see

this playing card view right here in the interface builder.

And of course, I can do that, I wouldn't have mentioned it.

So let's go here, and how do you do that?

You just put @IBdesignable in front of your view.

If you put that in there,

then when you go to interface builder,

it will compile your view, put it in the environment and

put it here. Now, it's blank, why is it blank? Well,

it's actually blank because it's face down, and

images don't work with image named in interface builder.

For example, if I put this face up again,

you'll see that it works with the pips, because they don't

use any images. All right, go back to my storyboard.

Look, I got pips, I got my corner things too. Okay, so

it even does subviews. So what about those images?

How am I gonna do the images,

cuz that's problem not just for the card back, but

if I make it be a a face card,

the face card is made with images. And so

I'm getting the corners, but I'm not getting my image.

Well, it turns out there's another version of image named

that you can use, that will work with both. So

it will work image named when you run,

but it will also work with image named when you are,

when you're in interface builder environment.

And it looks the same, I can never even remember it myself,

so I had to write it down here. It's, in: Bundle

(for: self.classForCoder),

compatibleWith: traitCollection,

okay. I think I typed that right. So this is the extra

couple arguments you need, you put it on all your image names

if you want this stuff to work in interface builder.

So now if we go to Interface Builder, all right,

it's showing the image. But this is only half the battle

because, if I wanna look through all my cards and

make sure they're working, I still have to go back here and

change these ranks and suit and

then go back and see it again. And what would be really cool

is if I could bring up the inspector, click on my card,

and instead of just seeing view attributes, if I could

see rank and suit and his face up, wouldn't that be awesome.

If I could just extend this The inspector, well,

of course we can do that too. All we have to do is put

@IBInspectable in front of any var that we want to

be inspectable in Interface Builder. So I'm gonna put it

on all my vars, I'll make them all be inspectable.

The only trick here is that you have to explicitly type

any IBInspectable, you cannot let this be inferred by Swift.

Because while Swift is good at doing inference,

Interface Builder not so much, not quite so good.

All right, so here we go. Now if I click on my view,

look at this, rank, I could try 5.

I could try 12, all right? I can try 2,

I can go even just go all through my cards, like this.

And since I've represented my suit as a string,

I could even have X be my suit right there.

That works? Okay, so that's it for all the drawing stuff.

Let's go back now and learn a little bit about multi-touch.

So I'm gonna go back to our slides here. And we're running

a little late, so I'm going to zoom through these. All right,

so we've seen how to draw, now how do we get multi-touch?

How do we get all these gestures and

stuff people can make with their fingers on the screen?

And you could get get all the touch events yourself,

that's legal. You could, and look at them,

look at every finger when it moves,

but that'd be incredibly tedious, so we don't do that.

Instead, we let iOS look at all those little movements and

turn them into gestures, like swipe, pinch, pan,

tap. So that's the level at which we program this stuff.

Okay, now gestures all represented in iOS

with this class UIGestureRecognizer.

It's a thing that recognizes a gesture from all those finger

movements. All right, that class is abstract, okay,

it itself doesn't know how to recognize any gestures. But

there's a lot of subclasses of it that know how to recognize

various gestures. So when you're recognizing a gesture,

there's actually two parts to it. One is, you have to tell

a view, please start recognizing pinches,

please start recognizing taps. Then you have to

provide a handler so that when it does recognize it,

it calls some function, so there's two parts.

The first thing, asking a view to recognize a gesture,

is surprisingly often done by the controller, or

in your storyboard. That's how you add gestures, usually.

Sometimes a view will add a gesture recognizer to itself,

if it's just totally inherent to what it does.

Like a scroll view will add pinching and

panning gestures to itself,

cuz it's not even a scroll view without those gestures.

But a lot of times, it's the control that does it.

The second thing, the handling of the gesture,

if it something that affects the model,

then the controller is going to handle it.

If it's something that only affects the way things is

viewed, then the view will often handle it directly. So

we'll see examples of both of those in our little demo.

So, the first part, how do you add a gesture to a view?

How do you tell that view, start recognizing this?

Well, usually we do this in the didSet of an outlet

setter. So here I've got an outlet to some view that I

want to recognize pans. Okay, it's some view, and I want it

to recognize pan gestures. So in the didSet of the outlet,

remember this didSet is called when iOS wires up that outlet

to the view that you want to pan. Then I'm going to

create a concrete instance of UIGestureRecognizer called

a UIPanGestureRecognizer. Now all of the recognizers

have the same initializer. It has two arguments, the target,

that's the object that is going to handle this,

it's usually either the controller or the view itself.

And then it has the action, and that's just the name of

the method with #selector around it. You see that

#selector in yellow there? That is going to be called

when this gesture starts to recognize a pan happening.

So then, once we've created a UIPanGestureRecognizer,

we ask the view,

please start recognizing this. And we do that by calling

addGestureRecognizer. And a view can have as many gesture

recognizers as you want.

It could be recognizing 20 different gestures at the same

time, it's perfectly fine.

All right, so now let's talk about the handler. So

when a pan starts to happen, a handler's gonna get called.

And the handler's gonna be that pan method that we saw

over there. And inside that method, we're going to have

to be able to get information about the pan.

Well, each kind of gesture has it's own information.

Like a pinch gesture has the scale you're pinching to,

a pan gesture is where is the pan happening. So if you

look at UIPanGestureRecognizer in the dock,

you'll see it has methods like translationInView.

That tells you where the pan is in that view.

Or velocity, how fast is the pan happening right now?

Or even setTranslation, which let's you reset

that translation in view, so you get incremental panning.

Instead of the continuous length of how far you've

panned since the start of the pan,

you get how much you got since the last time the pan moved.

Okay, which can sometimes be useful. Now,

the abstract superclass UIGestureRecognizer,

it also has a very important var called state. So

this whole gesture recognizer thing is a state machine, and

this state var represents that.

So as soon as a gesture becomes possible,

like a pan. Probably a finger touches down,

now it's possible.

And then as soon as it moves, it moves into the began state,

okay, so this pan has begun. And then as the finger moves,

it stays in the changed state. But it really keeps moving

to the changed state from the changed state over and

over. Now every time one of these state changes happens,

that handler gets called. Whoever's handling this thing

gets a chance to do it. So for a pan gesture,

you get .changed called every time the thing moves.

And then eventually the finger goes up,

and it ended, and you get .ended. So your handler's just

called every time the state machine changes.

Now, some things, like a swipe, are discrete, either

the swipe happened or it didn't. You don't get .changed

as your finger's flying across the screen, it's a discreet

gesture. You just get .ended, or for a swipe,

.recognised gets sent to your handler once, and that's it.

But for continuous gestures, you get the .changed.

Now, there's also two other interesting states, .failed,

and .cancelled. So .failed can happen when you have multiple

gestures, and one of them wins.

Like let's say you have, I don't know, a tap gesture and

a pan gesture. Well, as soon as you go mouse down,

it could be either of them.

But as soon as it doesn't it come right back up as soon

as you touch down. Soon as you come back up, it's like,

it can't be a pan anymore, so that one's cancelled,

cuz It failed, basically. So it can go into failed states,

but that's only if it actually starts up. It wouldn't be

recognized in the first place if it didn't get that far.

And then so cancelled is another one that's

interesting. And this happens a lot with drag and drop.

Which is, you started something, and it started up,

and it's going good. But then a drag and drop happens, and

now it's canceled. Whatever gesture you were recognizing.

So you do wanna look for failed and canceled, and

make sure you clean up or whatever. Take away something

off the screen or whatever, because your gesture has

failed, or has been cancelled by something else. All right,

so given this information, what would our pan handler,

the handler for the pan look like?

Okay, so it's just pan with the argument being

the pan gesture recognizer itself handed back to us. And

we switch on the state, we always switch on the state.

And if it's changed or ended, and

notice I'm using fallthrough there, but I could have just

said .changed, .ended there. So if it's changed or ended,

my pan is still moving, or I've just finished it.

Then I'm gonna find out where the pan was by calling

translationin: view on the recognizer.

Then I'm gonna do something based on where the pan went.

And maybe if I'm looking for

incremental pans, I'll reset it back to zero. So

that the next one will be from zero and be incremental. So

that's it, simple to do these handlers. Now what are some of

the concrete handlers besides PanGesture?

Well there's PinchGesture. Its information is the scale. So

if I start here with a pinch, and I go twice as wide,

well that's scale 2.0. Or if I start here and

go half as wide, it's 0.5. And there's also velocity for that

one. There's RotationGesture, which is like turning a knob.

A two-finger gesture turning the knob.

And in radians, it'll tell you how much the knob has been

turned in radians. There's a SwipeGesture, and you can,

now swipe is a little different than these other

ones in that you configure the swipe. How many fingers?

What direction, left, right, up, down?

And then you turn the swipe gesture on by adding it. And

then when the swipe happens, you'll just get .ended, your

handler will get called with .ended. So it's just, there's

no, it's different in that you configure it up front and

then it just tells you whether it recognized it or not.

There's TapGesture,

which feels like it would be like swipe,

a discrete gesture, but actually,

since it does double tap and other things, you're always

looking for .ended only with the TapGesture, usually.

But you also configure it like a swipe gesture how many taps,

how many fingers etc. There's also long press. Long

press is you hold your finger down on the screen for enough

time and it starts recognizing it. This is surprisingly

a continuous gesture, because as you're holding it down your

finger might be moving a little bit and

that's okay it's not a pan. Okay,

cuz it can only move a little bit. But

if it does move a little, you'll get .changed.

And you can configure how much movement you allow and

how long it has to be pressed before it's a LongPress.

This one gets interrupted a lot by drag and drop.

Because drag and drop uses LongPress. That's how you pick

something up with drag and drop is LongPress.

So if you have a LongPress, And there's some drag and

drop going on, you know the system is very smart about

figuring which one you actually intend. But

it could cause your long press to be cancelled.

All right, so let's see all this in action with a demo,

we only have five minutes left, but I think we can do it

in five or ten minutes. We're gonna add three gestures

to our playing card. Were gonna add a swipe,

which is gonna flip though our deck of cards. So that's gonna

affect our model. Our model is that deck of cards, so

that's something our controller is gonna have to

do. Then we're gonna have tap will turn the card over. We're

gonna do tap by adding the gesture in the story board,

not even in code. And then we're gonna have pinch which

I'm gonna use to resize the face card faces. And

that's the view only thing, so the handler for

that will be in the view. And since I won't be back to

the slides on Friday, no section again,

Homecoming week. This time we have conflicting schedules, so

we couldn't do structured section this week,

unfortunately. Next week we'll start doing multiple MVCs,

View Controller Life Cycle, and hopefully we'll get into

animation as well next week. All right, so here we are,

let's make our thing look a little better.

Let's go get back and get a nice, nicer thing,

maybe clubs this time.

And go back here so that x will have our clubs. Okay,

so we have nice looking cards. And, let's do the swipe first.

So the swipe, to do the swipe let me get both our

controller and our view up on the screen at the same time.

So here's our controller. It just has a deck of cards,

it doesn't really do anything. wanna add a gesture to this

playing card view that is swipe. I need an outlet to it.

My controller can't talk to that thing with an outlet.

So I'm just gonna control drag like I would drag anything to

make an outlet. Click it here, it's gonna be an outlet.

It's gonna be my playingCardView is the outlet.

Here it is. When this gets wired up,

I'm going to immediately add adjuster recognizer.

So I'm gonna do that in the didSet of this, so that when

iOS sets it I get to execute my code. I'm gonna do a swipe.

So, I'm going to create a swipe gesture,

UISwipeGestureRecognizer.

And the constructor is this target action thing.

Since swipe is going to flip through the cards, it's going

to affect the model. So it has to be handled by me,

the controller. Okay, so self is the target. The view can't

touch the model, so there's no way it could do the swipe. And

then the selector can just be any function. So,

I'm gonna have a function here called nextCard, which goes to

the next card. It's not even gonna have any arguments.

That's gonna be the action I want to be called when a swipe

happens. So, I just say #selector and

then I gave the name of it.

Next card, it has no arguments but if it did I would just put

the args in there. But it doesn't have any arguments so

we don't need that. Selector(nextCard). So

that's my swipe gesture. Now we need to configure the swipe

gesture. So for example I can set its direction.

I could say it swipes to the left for example. Swipes to

the right you could even say, swipes to the left or right.

Could put a little array notation there, for

left and right. So now I've got my swipe,

it's gonna be a single, what have we got?

Yeah, so this is an error right here. I'm gonna click

on it. It's gonna cause our screen to get all wonky here,

so let's move it around. Let's look at this error right here.

It says, the argument of #selector refers

to an instance method nextCard(), which it does.

That is not exposed to Objective-C. My gosh,

this whole mechanism is built on Objective-C, mechanism of

target action. So any method that is going to be the action

of a gesture recognizer has to be marked @objc. That exports

this method out of Swift into the Objective C run-time

which underlies the running of the iOS. Even with Swift code,

still got the Objective-C run-time. Okay, so that's what

that's all about. This always has to be ,just mark it objc,

It's not a big of a deal, just got to mark it. All right,

let's go back to our split screen here. This and this,

rearrange everything. Back to automatic.

All right, so now that we have this SwipeGestureRecognizer,

we need to ask this playingCardView,

please start recognizing it. So we say playingCardView,

add this GestureRecognizer(swipe).

And now it will start recognizing it.

And that's all we need to do. Now this next card

is the thing that's gonna flip through our cards. So

how do we implement that? I'm just gonna say if I can get

a card out of my deck. Because my deck might be empty.

That's why I have to do if let there.

Then I need to set the playing card view's rank

equal to something. And I need to set the playing card view's

suit equal to something. Now here's where the controller's

doing its job of converting between the two. So

we're going to convert by saying the card's.rank,

luckily we have order which does the card's order, and

card.suit has its raw value. Okay,

so this is just converting between the model and

the view there. Everybody got that? So

let's give it a try, see if this works.

So this should swipe through random cards by doing swipes.

So here we go we go, swipe, sure enough, look at that.

Swiping through. So that was really easy, right? Just have

that deck. All we had to do is just set the playing card view

to show a different card each time. All right,

the next thing we're gonna do is tap to flip the card over.

So tap, I'm not even gonna do this code right here.

Instead I'm gonna go over here, and

grab a tap gesture from, for this view, from here.

It's down towards the bottom. Look at all these gestures,

pinches, rotations, swipes. Here's tap, and

I'm gonna drag it to the view I want to recognize a tap.

Which is my playing card view. I drop it, and it shows up,

if we zoom in you can see it, right up in this title bar up

here. You see that right there, Tap Gesture?

You can click on it and inspect it.

Right, how many taps? How many touches?

You can also control drag from it to set an Action. So

I'm gonna set an Action here. I'm gonna call it flipCard,

cuz that's what I want it to do, flip the card.

I want to fix that anything. Just like any Action,

I want it to fix the argument. So here's my flip card.

And inside flip card here, I'm just gonna say

playingCardView.isFaceUp = not playingCardView.isFaceUp.

Okay, I'm just gonna flip the card over, and that's it.

So some gestures are really easy to write. And actually,

I abbreviated that a little bit. And now if I click, you

see how it's flipping it over. Okay, now I know we're rushed,

but actually I'm going to do the right thing here.

This really shouldn't be like this. I should switch

on the sender, which is the recognizer's state, and

make sure that we are in the ended case to do this.

Now, it'll usually work to not do that,

but I don't wanna show you something that's

really kind of not correct. Okay, and then the last

one we're gonna do is pinching to set the size of the face

card. Well, to do that, I need to go back to my view count,

my view, my custom view over here. And

I need to make it possible to change that, So right now,

actually, let's go here. Okay, view.

Okay, so right now the size of my face card, remember that's

a constant. This SizeRatio.faceCardImageSizeTo-

BoundsSize, so I'm gonna change that to be a var.

I'm gonna call it faceCardScale. Okay,

so I need to create a new var to do that. So let's go up,

do it all at the top. So we can easily see it here,

var faceCardScale. It's going to be a CGFloat.

I'll set it equal to that constant. Don't forget to do

this. Okay, although we don't really need

setNeedsLayout because changing the card size,

the faceCard does not affect the corners, okay. So

I don't need to relayout. So I've got that faceCardScale,

so now I'm gonna create a little func that is going to

be a handler for a pinch gesture.

Okay, I'm gonna call it, adjust, I had a good name for

here so it's easy to understand what it is.

What did I call this thing? adjustFaceCardScale(byHandlin-

gGestureRecodnizedBy recognizer: UIPinch),

now, this is an intentionally long name there.

So that you'd understand that this is the handler for

the gesture. And since it's a handler, it needs to be @objc,

of course. And, inside here, I'm just gonna switch on

the recognizer's state, as I always do.

That's what we do in standard in these handlers. And

if it's changed, so the pinch has changed or

if it's ended, then I'm going to set my faceCardScale,

this thing I just created up here, okay,

to be*= recognizer.scale.

Now, I only want incremental changes because I'm changing

the scale each time. So, otherwise, it would

just start to be exponential. So I'm gonna reset

the recognizer's scale to 1.0 each time that this happens.

And then we're gonna ignore all other states of the state

machine. We don't care when it began and all that, stuff. So

now we're gonna have this adjustFaceCardScale(byHandlin-

gGesture recognizer) be added back in our controller as

a pinch gesture. So here I'm gonna create a pinch gesture.

Let pinch = UIPinchGestureRecognizer,

same target inaction thing as the other one, but

this time the target is going to be the playingCardView.

It's gonna handle this directly.

It's not gonna go to the controller, and

the selector is that method we had over there.

Okay, it's in our view, and I'm gonna call it pinch. Okay,

and now I just need to tell the playingCardView to add

this gesture recognizer pinch, and it will start recognizing.

Okay, so let's take a look. Oops,

what did I do wrong here? What does it say?

Unresolved, okay, let's use scape completion here, adjust,

sorry, PlayingCardView. I need to say that it's in

PlayingCardView. That's the problem there, handler.

Sorry about that. Okay, so let's find a face card.

Here it is. How do you pinch in the simulator?

You hold down Option, you get these grey things, and

when you mouse down, you get to pinch. So

see how that's only effecting the view?

It's not effecting anything else, effects all the cards

And that's it. Okay, sorry to rush that at the end. You'll

be doing all this stuff in your assignment number three,

which just went out. It's due in a week,

in other words before lecture next Wednesday. And

I will see you all then,

actually, I'll see you on Monday.

And if you have questions,

I'm here, as always. >> For

more, please visit us at stanford.edu.

For more infomation >> Stanford - Developing iOS 11 Apps with Swift - 6. Multitouch - Duration: 1:25:23.

-------------------------------------------

Liverpool officially unveil record signing Virgil van Dijk - Duration: 3:26.

Liverpool officially unveil record signing Virgil van Dijk

Liverpool have completed the signing of Dutch centre-back Virgil van Dijk, after agreeing the terms of the move with Southampton on December 27.

A key area identified for improvement and a key target who could be an upgrade: Jurgen Klopp now finally has his man for the middle of the defence.

The Reds were proactive in arranging the deal as early as possible after a failed summer move, and now with the January transfer window open, van Dijk has finalised his move to Anfield.

With a price tag of £75 million, van Dijk is another example of the club being prepared to do whatever necessary to land the exact signing Klopp wants—and the defender has also been quick to voice his happiness at the switch.

"I am happy to be here and I can't wait to get started," he told LiverpoolFC. com.

"I think the most important thing is the size of the club, the culture of the club, the players, the manager and obviously the fans, who make the club this special.

"With the history at the club and everything around it – even the training ground and stuff – it is just a perfect, perfect match for me, and a perfect match for my family as well.

"I think it'll be something special," he said.

"I think Anfield is a very special stadium and it is my home right now as well.

"I am just looking forward to being on the pitch, especially as a [home] player at the stadium.

It's going to be nice, especially the evening games and the European nights.

"I hope to win trophies.

Every player wants to win trophies and with this squad we have and the progress the club is making, I think we are very close to it.

"Obviously we still need to do it and we will see what the future brings.

The Dutchman will wear the No.

4 shirt for the Reds and is eligible to play in Europe across the second half of the campaign as well as domestically.

For more infomation >> Liverpool officially unveil record signing Virgil van Dijk - Duration: 3:26.

-------------------------------------------

World's Top 10 Most Beautiful Women in The World 2018 - Duration: 3:30.

World's Top 10 Most Beautiful Women in The World 2018

For more infomation >> World's Top 10 Most Beautiful Women in The World 2018 - Duration: 3:30.

-------------------------------------------

Dog Cane Corso Derrek celebrates the New Year. #canecorso - Duration: 2:15.

For more infomation >> Dog Cane Corso Derrek celebrates the New Year. #canecorso - Duration: 2:15.

-------------------------------------------

Hasan Caglar Tanır Mısın Hasan Çağlar Who is the Opening Speech - Hasan Caglar - Duration: 2:05.

For more infomation >> Hasan Caglar Tanır Mısın Hasan Çağlar Who is the Opening Speech - Hasan Caglar - Duration: 2:05.

-------------------------------------------

Milling Three Interlocking 'Olympic' Rings - Duration: 2:58.

Milling Three Interlocking 'Olympic' Rings

For more infomation >> Milling Three Interlocking 'Olympic' Rings - Duration: 2:58.

-------------------------------------------

Vocal, commanding and comfortable on the ball: Van Dijk on the strengths he'll bring to LFC - Duration: 6:00.

Vocal, commanding and comfortable on the ball: Virgil van Dijk on the strengths he'll bring to Liverpool

Virgil van Dijk has given an insight over what he'll bring to the Liverpool team and has highlighted his wish to work with manager Jurgen Klopp.

Having completed his £75 million move from Southampton to the Reds, van Dijk's first interview has shown fans what to expect once he's in the team.

Anyone watching him for Southampton, Celtic or Groningen will be aware of the Dutchman's major strengths as a defender, but the man himself adds another attribute to his repertoire, one which the Reds have been sorely lacking in at times.

In particular, that's the ability and willingness to organise and direct the defensive ranks.

"I am vocal, I am obviously pretty tall, I like to command the defensive line and have the ball as well," van Dijk told LiverpoolFC.

com.

For many fans, that alone would be worth the majority of the club record fee, with the lack of leadership an oft-repeated fact since the departure of the likes of Daniel Agger, Jamie Carragher and Sami Hyypia.

But Klopp won't be looking to the new No.

4—the number Hyypia used to wear at Anfield, incidentally—just for his direction of the back four; he's also a tremendous player on a technical level.

"I like to play out from the back and be comfortable on the ball," van Dijk continued.

He's also clearly keen to work with Klopp, likely a factor in the Dutchman choosing Liverpool over alternative potential moves.

"Obviously there is a lot of improvement still to come, but I think the manager can help me with that.

"Everybody obviously from a Liverpool perspective knows how he is; how lively he is, how he can make players better and give them confidence as well.

"It just suits me as well.

I think he can make me a better player and I am just looking forward to working with him.

"I think this is the right time for me to be here and to develop all sorts of aspects of my game.

I am looking forward to doing that, that's the main thing.

"Since he's come in, I think he has made a lot of progress until now and I think it is only hopefully going to get better and better.

Hopefully I can contribute to that as well and keep working hard.".

Van Dijk's leadership and tall stature aren't the only similarities he has with Reds icon Hyypia—they now share having played for the same club, wearing the same number.

And the Dutchman is well aware of the Finnish defender's contribution, both at Anfield and back in Virgil's very first club.

"I had No.

4 when I played for Groningen back in Holland, so I was always a big fan of No.

4 anyway.

"Unfortunately at Southampton, my good friend Jordy Clasie had No.

4, so I didn't want to take it from him!.

"I just like No.4.

Obviously here, Sami Hyypia had it here as well and played for my team where I played 10 years in Holland, Willem II, so it's a bit special.

"I am going to give my everything, try to keep clean sheets and hopefully try and be a threat in front of goal as well.

"I think the main thing is just to organise, try to keep clean sheets.

I will give everything I've got in every game.".

Clean sheets and organisation will be music to Reds fans' ears, and they'll be hoping the new addition helps bring exactly that from his first matches on the Anfield pitch.

For more infomation >> Vocal, commanding and comfortable on the ball: Van Dijk on the strengths he'll bring to LFC - Duration: 6:00.

-------------------------------------------

THANKS FOR 2017! - Duration: 2:12.

Hello and welcome to a new video!

I want to start this video to say thanks!

Thank you so much for 2017!

2017 was not the best year, but it was a good year.

I never thought I would get over 700 subscribers in less than a year,

in just 8 months.

Now I will tell you a bit about my channel.

On April 13, I uploaded a one minute long video titled "Welcome to my channel."

There, I talked about what my channel would be about.

One day later, on 14 April, I uploaded a Q&A, it became very popular.

It now has nearly 1 500 views.

On April 15, it became the biggest change on my channel, I would do a series of Hydra.

One would ask a question about Hydra and I would answer it.

The first video of Hydra came out April 16, and then I have continued to make such videos,

until some told me to do as Hydra,

namely to roast.

The series (about Hydra) ended on 30 April.

My first roast-video uploaded on May 4 where I roasted THboi,

now he is called THEO.

Since then I have continued to roast.

Altogether, I have uploaded 72 videos, and received over 33,000 views 2017.

I know it's not much, but it's still a lot.

Now I'll tell you what I will continue to do and not do in this year.

What I will do this year is to continue to roast people, of course.

What I should NOT do this year is that I do not roast people they don't want it, for example, if you want me to roast a person,

and the person does not want it so I do not do it.

Suggest your own channel instead!

I hope that 2018 will be a much better year than 2017!

That's all for me!

Remember - like and share the video and subscribe to my channel.

Have a good one! (Happy New Year!)

For more infomation >> THANKS FOR 2017! - Duration: 2:12.

-------------------------------------------

new listing, house for sale, new construction, 65 roosevelt blvd. Sayreville. nj russell hayek - Duration: 4:01.

hey guys this new construction here brings us right into sayreville we're gonna

be doing a quick walk through of this 2200 square foot four bed two and a half

bath this three-story colonial with a unique layout floor plan allows

the lower level slightly under grade with full sized windows, all stainless

steel let's just take it inside to show you

oh if you need more information like to see it just shoot me a text give me a

call numbers in the description box

floors are ready for rugs

alright guys that wrap things up here need more info just shoot me a text

informations in the description box until next time have a good one

Không có nhận xét nào:

Đăng nhận xét