diff --git a/.gitignore b/.gitignore index 34033d9..6bd3ad7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,17 @@ bilicookies .vscode +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db +Desktop.ini + # Xcode # # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore diff --git a/subtitles/4. Views.srt b/subtitles/4. Views.srt index 883d6c0..dcd84ad 100755 --- a/subtitles/4. Views.srt +++ b/subtitles/4. Views.srt @@ -21,498 +21,622 @@ CS193P 课程,iOS 应用程序开发 5 00:00:15,782 --> 00:00:20,785 So today, our topic is to talk about custom views, okay, +今天我们要讲的是自定义视图 6 00:00:20,854 --> 00:00:25,123 specifically the drawing side of having custom views. +特别是在这些视图中绘制内容 7 00:00:25,192 --> 00:00:28,193 And this is gonna be a more typical lecture than last +以后上课的形式都和今天差不多 8 00:00:28,262 --> 00:00:30,762 time because I'll be doing some slides and +上次全是幻灯片是因为 9 00:00:30,831 --> 00:00:32,964 explaining the concepts to you, and +我全在讲理论知识 10 00:00:33,033 --> 00:00:36,301 then I'll go into a demo that shows you how we do it all. +现在我们是要实际运用 11 00:00:36,370 --> 00:00:39,104 So what is a view? +那什么是 view, 视图呢? 12 00:00:39,173 --> 00:00:42,540 A view is a subclass of UIView, +视图继承 UIView 13 00:00:42,609 --> 00:00:45,643 which is in UIKit in iOS. +UIView 属于 iOS UIKit 的一部分 14 00:00:45,712 --> 00:00:48,313 And all it does is carve out or +它的作用是“挖出”,也就是 15 00:00:48,382 --> 00:00:51,883 represent a rectangular area on screen. +代表屏幕上一个长方形的区域 16 00:00:51,952 --> 00:00:55,019 And that rectangular area defines a coordinate space +以这个长方形构成一个坐标系 17 00:00:55,088 --> 00:00:57,990 that we're gonna draw in and that we're gonna get +这就是我们可以绘制的区域 18 00:00:58,058 --> 00:01:00,124 multi-touch events like pinches and +这个区域也会接受多点触控 19 00:01:00,193 --> 00:01:01,660 swipes and all that stuff. +比如捏合,轻扫事件等 20 00:01:01,728 --> 00:01:03,095 So today, +于是今天 21 00:01:03,163 --> 00:01:06,131 I'm just gonna focus on the drawing side of that all and +我先只会专门讲如何绘制 22 00:01:06,199 --> 00:01:09,268 then we'll start talking about the gestures on Wednesday. +手势的处理我们留到星期三 23 00:01:10,537 --> 00:01:14,439 So these views, these little rectangle areas +这些视图,这些长方形的区域 24 00:01:14,508 --> 00:01:17,542 are put on screen in this hierarchical way. +是组织为层级之后显示在屏幕上的 25 00:01:17,611 --> 00:01:20,779 And that just means that the views have subviews +这意味着视图当中可以有 26 00:01:20,847 --> 00:01:21,913 inside of them. +多个子视图,subview 27 00:01:21,982 --> 00:01:25,450 Now any given view can only have one superview, +但只可能有一个父视图,superview 28 00:01:25,519 --> 00:01:27,185 that's the view that it's contained in. +也就是包含它的那个视图 29 00:01:27,254 --> 00:01:29,054 But it can have any number of subviews, +但是子视图可以有很多个 30 00:01:29,123 --> 00:01:30,689 so views made out of it. +所有它包含的视图都算 31 00:01:30,758 --> 00:01:33,324 So for example, on the calculator, we had for +拿计算器举例子 32 00:01:33,393 --> 00:01:35,493 example, stack view, okay. +我们有 StackView 33 00:01:35,562 --> 00:01:37,195 It had a lot of subviews, +其中有很多子视图 34 00:01:37,264 --> 00:01:38,897 all the buttons that we stacked in it. +也就是被我们叠起来的那些按钮 35 00:01:38,965 --> 00:01:41,400 In fact, some of the stack views had other stack views as +事实上,还有的 StackView 的子视图 36 00:01:41,468 --> 00:01:42,067 their subviews. +也是 StackView 37 00:01:42,135 --> 00:01:44,302 And then those stack views had more subviews, +每个子视图 StackView 又有更多的子视图 38 00:01:44,371 --> 00:01:45,771 which were buttons or whatever, okay. +也就是那些按钮一类的 39 00:01:45,839 --> 00:01:49,674 So that's how we build our UI is this hierarchical +所以 UI 是通过这种层级结构 40 00:01:49,743 --> 00:01:52,077 collection of these rectangular areas. +通过一层层的长方形视图构成的 41 00:01:52,145 --> 00:01:56,014 Now, at the very, very, very top there's a special UIView +在这个结构的最顶层,有一个特殊的 UIView 42 00:01:56,083 --> 00:01:59,751 called UIWindow class, we don't deal with that in iOS. +它是一个 UIWindow,虽然 iOS 里不常用 43 00:01:59,820 --> 00:02:03,021 In fact, the only time you would ever do anything with +事实上唯一需要用到 UIWindow 的情况 44 00:02:03,090 --> 00:02:06,491 the UIWindow is if you were building an app that maybe +是你需要编写一个能投影 45 00:02:06,560 --> 00:02:08,193 projected to a projector. +到投影仪的程序 46 00:02:08,261 --> 00:02:10,328 So that you had two screens, your device and +这种情况下你有两个屏幕——你的设备 47 00:02:10,397 --> 00:02:11,963 then maybe some external projector or +和那个投影仪 48 00:02:12,032 --> 00:02:14,199 something, then you might care about UIWindow. +这个时候你就需要考虑用 UIWindow 49 00:02:14,268 --> 00:02:17,069 But otherwise, it's all about UIView, okay? +但其他情况下 iOS 都只会用到 UIView 50 00:02:17,137 --> 00:02:19,871 All of our arrangement of the screen is all about how we +所有屏幕上的布局都是 51 00:02:19,940 --> 00:02:22,574 arrange the UIViews. +组织这些 UIView 52 00:02:22,642 --> 00:02:25,444 Now this hierarchy, okay, these rectangular areas inside +一般来说,设计这个层级结构 53 00:02:25,512 --> 00:02:28,680 of rectangular areas, is almost always built +这一层套一层的长方形区域 54 00:02:28,749 --> 00:02:31,316 in Interface Builder, inside Xcode, okay? +是通过 Xcode 的 Interface Builder 55 00:02:31,385 --> 00:02:32,817 That's how we built the stack view stuff. +还记得我们是怎么创建 StackView 的吗? 56 00:02:32,886 --> 00:02:34,752 We dragged out a bunch of buttons and +我们把一堆按钮拖到界面里 57 00:02:34,821 --> 00:02:35,920 then we selected them and said, +选中之后然后选择 58 00:02:35,989 --> 00:02:38,890 "Embed in Stack View." Well, that wrapped it in there. +"Embed in StackView",封装到 StackView 59 00:02:38,959 --> 00:02:42,094 But we can also build that hierarchy by dragging views +同理,我们也能够把视图 60 00:02:42,162 --> 00:02:43,929 out of the utilities, +从右下角的工具区里拖出来 61 00:02:43,997 --> 00:02:47,132 bottom of the utilities window there, inside other views. +放到其他的视图中 62 00:02:47,200 --> 00:02:48,132 So you can drag, +所以你可以拖拽 63 00:02:48,201 --> 00:02:51,703 do it by dragging-dropping inside of other views. +拖拽然后放进其他视图里 64 00:02:51,772 --> 00:02:53,338 It is possible to do it in code but +虽然我们也可以写代码实现 65 00:02:53,407 --> 00:02:55,207 usually we're doing it graphically. +不过通常我们都是用 IB 完成 66 00:02:55,276 --> 00:02:56,375 If you're doing it in code, +如果你要通过代码实现 67 00:02:56,443 --> 00:03:00,912 the two main methods involved in building and +有两个方法是你肯定要用到的 68 00:03:00,981 --> 00:03:05,050 destroying this hierarchy, are addSubview, okay, +一个是 addSubview 69 00:03:05,119 --> 00:03:07,418 addSubview, takes a view as an argument. +接受一个 UIView 作为参数 70 00:03:07,487 --> 00:03:11,489 You send it to the "soon-to-be" superview of that +然后把它交给“准”父视图 71 00:03:11,558 --> 00:03:12,708 In other words, you ask another view, +也就是你告诉另一个视图 72 00:03:12,709 --> 00:03:13,859 view. +告诉它说 73 00:03:13,927 --> 00:03:16,928 please add this other view as subview of yourself. +请把这个视图收为你的子视图 74 00:03:16,996 --> 00:03:19,864 Now when you're doing the opposite, taking some view out +反之,如果你要从层级中踢出视图 75 00:03:19,933 --> 00:03:22,467 of the hierarchy, you don't send it to the superview. +你不用通知它的父视图 76 00:03:22,536 --> 00:03:24,436 You send it to the actual view itself, +你告诉你要移除的视图 77 00:03:24,505 --> 00:03:27,305 basically remove yourself from this view hierarchy. +你自己把自己踢出去吧 78 00:03:27,374 --> 00:03:29,507 So you send removeFromSuperview +让你想移除的视图 79 00:03:29,576 --> 00:03:31,977 to the actual view you want removed. +调用 removeFromSuperview 方法 80 00:03:33,280 --> 00:03:35,347 Now where does this hierarchy start? +这个层级结构从哪里开始的呢? 81 00:03:35,415 --> 00:03:37,048 I guess you could say it starts in UIWindow. +准确的说是那个 UIWindow 82 00:03:37,117 --> 00:03:39,517 But for our purposes, we don't even pay attention to that. +但是我们并不需要太在意它 83 00:03:39,586 --> 00:03:42,054 It starts at the top level view +所以我们把 Interface Builder 里 84 00:03:42,122 --> 00:03:44,956 in that scene in Interface Builder. +显示的最顶层视图当作结构的最顶层 85 00:03:45,025 --> 00:03:47,225 The scene that's controlled by our view controller, right? +也就是每个视图控制器控制的场景 86 00:03:47,294 --> 00:03:49,527 That rectangular area that we work in. +提供给我们布局的那个长方形区域 87 00:03:49,596 --> 00:03:50,261 There's a top, +就当它作为最顶层 88 00:03:50,330 --> 00:03:54,499 top level view that covers the whole space up there. +最顶层的视图覆盖了所有可用的区域 89 00:03:54,567 --> 00:03:56,701 And there is an important instance variable, +有个重要的属性 90 00:03:56,770 --> 00:03:59,771 property, in UIViewController. +UIViewController 和 91 00:03:59,840 --> 00:04:02,907 Okay, so all subclasses of UIViewController get +UIViewController 的子类 92 00:04:02,976 --> 00:04:03,842 this property. +都有这个属性 93 00:04:03,910 --> 00:04:07,946 It's called view and it's a UIView and a top level view. +叫做 view,也就是最顶层的这个 UIView 94 00:04:08,015 --> 00:04:12,084 And it's very important to understand that in an MVC, +这是很重要的一点,对于 MVC 而言 95 00:04:12,152 --> 00:04:15,520 the controller has this, always has this var which +控制器需要有通过这个变量 96 00:04:15,589 --> 00:04:20,459 points to the very top of that view hierarchy in its scene. +指向其控制场景的视图层级中的最顶层 97 00:04:22,429 --> 00:04:25,430 This top level view is important because for example, +这个最顶层的视图很重要,因为比如 98 00:04:25,499 --> 00:04:28,599 when you rotate, it's the thing whose bounds changes, +你旋转之后,最顶层的视图的边界 99 00:04:28,668 --> 00:04:29,801 that top level view. +整个都跟着变了 100 00:04:29,870 --> 00:04:32,336 And you're gonna learn a little later that when +之后你会学到 101 00:04:32,405 --> 00:04:35,606 the bounds of a view changes, there's a mechanism for +当一个视图的边界发生改变之后 102 00:04:35,675 --> 00:04:39,043 offering all of its subviews an opportunity to change. +会有一个给所有子视图更新的机制 103 00:04:39,112 --> 00:04:40,712 So that's why when we rotate device, +当我们旋转之后 104 00:04:40,781 --> 00:04:43,281 that top level view changes from being tall and +最顶层的视图从瘦长型 105 00:04:43,350 --> 00:04:47,085 thin to being wide and less tall. +变成了矮胖型 106 00:04:47,154 --> 00:04:49,654 And that causes all those stack views and +这就会导致所有那些 StackView 107 00:04:49,723 --> 00:04:52,123 everything else to start getting resized as well, +所有的子视图跟着改变形状 108 00:04:52,192 --> 00:04:56,361 because they're all subviews of this top level view, okay? +因为它们是最顶层视图的子视图 109 00:04:56,430 --> 00:04:59,497 If you were going to add views to the view hierarchy +如果你要添加一个视图 110 00:04:59,566 --> 00:05:01,866 programmatically rather than dragging and +通过代码而不是拖拽实现 111 00:05:01,935 --> 00:05:04,502 dropping them, then you would need this view because it's +你需要用到这个视图,因为它是 112 00:05:04,571 --> 00:05:06,204 the top of the entire view hierarchy. +整个视图层的顶层 113 00:05:06,273 --> 00:05:07,606 And you would kinda work your way down +你可能会想知道你需要 114 00:05:07,674 --> 00:05:09,907 to find out where you want to put that view. +把那个视图放在哪 115 00:05:09,976 --> 00:05:12,410 But we don't otherwise actually look at this view +但其实我们不需要知道把它放哪 116 00:05:12,479 --> 00:05:14,846 much because we usually have outlets, rights? +因为我们有出口,对吧? 117 00:05:14,915 --> 00:05:17,982 IBOutlets--like the display that points to the label--that +比如指向标签控件的那个 display 变量就是个 IBOutlet(出口) 118 00:05:18,051 --> 00:05:19,484 gives us access to that label. +这个 IBOutlet 能让我们去修改那个标签 119 00:05:19,552 --> 00:05:20,451 That's all we want, so +这就是我想实现的,那么 120 00:05:20,520 --> 00:05:22,988 we don't have to go looking at the top level view and +我们不再需要从顶级视图开始 121 00:05:23,056 --> 00:05:26,290 looking all down the views, okay? +一个一个地去找了,对吧? 122 00:05:26,359 --> 00:05:28,059 So this is important to know about but +那么这就是我们重点需要知道的 123 00:05:28,128 --> 00:05:31,896 surprisingly you don't access it that much, okay. +但好在我们不需要过多的去使用它,好吧 124 00:05:31,965 --> 00:05:33,764 This view is automatically hooked up for you in +这个视图会自动连接到 125 00:05:33,833 --> 00:05:35,967 Interface Builder when you drag out a View Controller. +你拖出到 Interface Builder 的视图控制器 126 00:05:36,035 --> 00:05:38,002 It's just all magically hooked up, +就这么神奇的连接上了 127 00:05:38,071 --> 00:05:40,071 you don't have to worry about that. +你完全不需要担心 128 00:05:40,140 --> 00:05:43,241 Okay, let's talk about initialization of the UIView. +好了,接下来我们将讨论初始化 UIView 129 00:05:43,309 --> 00:05:46,378 @@ -2377,530 +2501,662 @@ lines and arcs and things like that. 501 00:21:32,692 --> 00:21:35,359 Then you set drawing attributes in the context, +然后在上下文中调整绘制属性 502 00:21:35,427 --> 00:21:37,962 like the colors you wanna use, the fonts if you're doing +比如你想要的颜色,字体 503 00:21:38,031 --> 00:21:41,432 text, line widths, those kinds of things. +线宽度,等等 504 00:21:41,501 --> 00:21:43,300 You set those all up, and then you stroke and fill. +当你设置好后,就 stroke 和 fill 505 00:21:43,369 --> 00:21:44,801 And that's it, stroking and +然后就完成了,描边和填充 506 00:21:44,870 --> 00:21:47,804 filling are actually the only two directives that actually +是仅有的两条命令 507 00:21:47,873 --> 00:21:49,740 cause something to happen on screen. +真正能让东西显示在屏幕上 508 00:21:49,809 --> 00:21:50,574 But keep in mind that, like, +但记住 509 00:21:50,642 --> 00:21:55,279 a font is basically just a really exquisite path filled, +文字其实就是被填充的复杂线条 510 00:21:55,348 --> 00:21:57,614 okay, or stroked and filled. +或者说不仅填充还描了边 511 00:21:57,683 --> 00:22:00,884 So you can do a lot with stroking and filling. +所以你可以用填充和描边做很多事情 512 00:22:00,953 --> 00:22:03,420 So UIBezierPath kinda encapsulates all of those +所以 UIBezierPath 把 513 00:22:03,489 --> 00:22:05,956 Core Graphics concepts into an object. +Core Graphics 函数封装进对象 514 00:22:06,025 --> 00:22:08,525 And so I have an example here to show you how I would use +我这里有个例子向你们展示 515 00:22:08,594 --> 00:22:12,929 UIBezierPath to draw a triangle on screen. +如何用 UIBezierPath 在屏幕上画一个三角形 516 00:22:12,998 --> 00:22:14,965 First, I'm gonna create the path by just saying, +像刚刚说的,我要先创建一个路径 517 00:22:15,033 --> 00:22:16,099 path = UIBezierPath(). +用的是 let path = UIBezierPath() 518 00:22:16,168 --> 00:22:17,768 There are other initializers for it, +它还有其他构造器 519 00:22:17,837 --> 00:22:18,735 which we'll see in the demo. +这些东西我们将在演示中看到 520 00:22:18,804 --> 00:22:21,371 But this one just creates a blank path to start. +这一个会创建一个空路径 521 00:22:21,440 --> 00:22:23,206 Then, you move around with the path. +然后,你需要移动这个路径 522 00:22:23,275 --> 00:22:25,876 So like I can say, move to, which (80, +像我说的,移动它到(80, 50) 523 00:22:25,945 --> 00:22:29,480 50) is like halfway across this, this little screen. +差不多过这个小屏幕的一半 524 00:22:29,548 --> 00:22:32,949 This is small screen, let's say, 160 points wide. +我们假设这个屏幕 160 点宽 525 00:22:33,018 --> 00:22:34,751 80 and then 50 down, okay? +这个操作会右移 80,下移 50 526 00:22:34,820 --> 00:22:39,556 Then I'm gonna add a line down to 140, 50, see that, okay? +然后我要加一条线到 (140, 50) 527 00:22:39,625 --> 00:22:42,659 Then I'm gonna add another line over to 10, +然后我要再加另一条线 528 00:22:42,728 --> 00:22:45,929 off to the left, I'm still 150 down. +向左移动到 10,纵坐标依然在 150 529 00:22:45,998 --> 00:22:48,832 Then I'm gonna close the path, okay, using close, and +然后我要使用 close() 闭合路径 530 00:22:48,901 --> 00:22:51,101 that just closes it back to the start. +让它与起始点闭合 531 00:22:51,170 --> 00:22:53,436 So look, I made a triangle, okay, really easy. +看,我画了个三角形,非常简单 532 00:22:53,505 --> 00:22:56,940 Now, the only thing is, all this code right here would +现在,唯一的一件事是,这些代码 533 00:22:57,009 --> 00:23:00,410 actually draw, instead of that triangle right there, +真的会绘制出三角形吗? 534 00:23:00,479 --> 00:23:03,113 would draw this: nothing. +不会,什么都不会显示出来 535 00:23:03,182 --> 00:23:06,083 You would see no drawing with that code because we haven't +你看不到用代码绘制的三角形因为 536 00:23:06,151 --> 00:23:07,117 stroked or filled it. +还没有填充或描边 537 00:23:07,186 --> 00:23:09,386 The stroking and filling is what draws. +填充和描边才会绘制 538 00:23:09,455 --> 00:23:10,754 So how do we do the stroking and fill? +那么我们如何填充和描边呢? 539 00:23:10,823 --> 00:23:13,157 Well, we need to set the colors that we wanna fill and +首先,需要设置填充和描边的颜色 540 00:23:13,226 --> 00:23:15,792 -stroke with. +stroke with. So we're gonna talk about UIColor in a minute, +UIColor 是什么等会儿讲 541 00:23:15,861 --> 00:23:17,261 But here, I'm taking green and +在这里,我将使用绿色 542 00:23:17,330 --> 00:23:18,829 sending it the message setFill. +调用它的 setFill 方法 543 00:23:18,897 --> 00:23:21,865 So you actually set your color to fill with +所以在设定你的填充颜色时 544 00:23:21,934 --> 00:23:24,601 by sending a message to a color. +是通过发送一个消息给颜色 545 00:23:24,670 --> 00:23:25,969 You get a color, and you send it a message, +你选择一个颜色,然后向其发送一条消息 546 00:23:26,038 --> 00:23:27,237 set that as my fill color. +设置那个颜色作为我的填充色, 547 00:23:27,306 --> 00:23:28,104 And the same thing with a stroke, +描边也是同理 548 00:23:28,173 --> 00:23:28,772 set it as a stroke color. +设置其为描边的颜色 549 00:23:28,840 --> 00:23:32,842 So I set my stroke color to red, my fill color to green. +现在描边的颜色为红色,填充色为绿色 550 00:23:32,911 --> 00:23:35,613 But when I'm talking about attributes like line width, +但当设置比如线条宽度等属性 551 00:23:35,681 --> 00:23:38,716 I send that to the path, to the UIBezierPath. +我会发送消息到 UIBezierPath 552 00:23:38,784 --> 00:23:41,318 Set your line width to three, okay, so I do that. +path.lineWidth = 3 设置线宽度为 3 553 00:23:41,387 --> 00:23:45,622 Now, if I say path.fill, now I get a green triangle. +现在 path.fill(),我会得到一个绿色的三角形 554 00:23:45,691 --> 00:23:46,823 Because my fill color was green, +因为我的填充色是绿色 555 00:23:46,892 --> 00:23:48,859 and it takes that path and it fills it in. +它会把路径填充成这个颜色 556 00:23:48,927 --> 00:23:50,594 That's what fill does. +那就是填充所起到的作用 557 00:23:50,663 --> 00:23:53,563 And similarly, if I say path.stroke, +同样的,path.stroke 558 00:23:53,632 --> 00:23:55,332 I get a red line around. +红色的线条会环绕它 559 00:23:55,401 --> 00:23:58,802 Because the path that I took to get around there gets +因为我设置封闭的路径 560 00:23:58,871 --> 00:24:02,206 stroked with a three-point wide red line. +用三个点宽的红色线条勾了线 561 00:24:02,274 --> 00:24:04,841 So that's it, that's quite simple actually. +完成了,其实非常简单 562 00:24:04,910 --> 00:24:05,543 That's how we draw. +这就是我们绘制的过程 563 -00:24:07,579 --> 00:24:08,979 -And, UIBezierPath also knows how to draw a lot of common +00:24:07,579 --> 00:24:08,280 +Okay? +懂了吗? 564 00:24:08,980 --> 00:24:10,380 -Okay? +And, UIBezierPath also knows how to draw a lot of common +同时,UIBezierPath 也知道如何画出很多 565 00:24:10,449 --> 00:24:13,350 shapes, like rounded rectangles, and ovals, and +常见的形状,比如像圆角矩形,椭圆形等 566 00:24:13,419 --> 00:24:16,053 things like that, so you should familiarize yourself +所以你熟练地使用 567 00:24:16,121 --> 00:24:20,256 with UIBezierPath's API, of course. +UIBezierPath 是必须的 568 00:24:20,325 --> 00:24:22,392 Another cool thing you can do with UIBezierPath is you +另一件很酷的事情就是 UIBezierPath 569 00:24:22,461 --> 00:24:24,094 create a path like that triangle, and +比如像刚才那个三角形 570 00:24:24,162 --> 00:24:27,798 you can clip all your drawings to that path. +你可以把那个路径作为遮罩 571 00:24:27,866 --> 00:24:30,367 So you could draw this elaborate picture that only +你可能画一个很复杂的图像 572 00:24:30,436 --> 00:24:33,003 show the part that shows through that triangle, +但只画透过三角形的那部分 573 00:24:33,071 --> 00:24:34,938 if you take that triangle path that we just created and +如果你通过我们刚刚创建的三角形路径 574 00:24:35,007 --> 00:24:37,073 say add clip to it. +调用它的 addClip 方法 575 00:24:37,142 --> 00:24:37,841 Because after that, +在那之后 576 00:24:37,909 --> 00:24:42,012 all drawing is only gonna show up inside that triangle, +绘制的东西只显示在三角形内的部分 577 00:24:42,080 --> 00:24:44,381 -you can make some pretty cool effects by doing it. +which is kinda cool, +真的很酷 578 00:24:44,382 --> 00:24:46,683 -which is kinda cool, +you can make some pretty cool effects by doing it. +你可以通过这个方法来做出一些非常酷的效果 579 00:24:46,752 --> 00:24:48,485 The UIBezierPath also knows how to, +UIBezierPath 也能实现 580 00:24:48,554 --> 00:24:50,521 it has this method contains that will, +通过叫做 contains(_:) 的这个方法 581 00:24:50,589 --> 00:24:53,389 tell you whether a point is inside the path. +告诉你这个点是否在路径里面 582 00:24:53,458 --> 00:24:56,126 So that's good if you want to do some touch thing or people +在处理触控的时候可以使用 583 00:24:56,195 --> 00:24:58,962 are touching on something and you wanna do hit detection, +比如一个人碰到了某个元素 584 00:24:59,031 --> 00:25:00,997 basically, what they're touching on. +你可以检测出究竟按到了什么 585 00:25:01,066 --> 00:25:02,933 All right, and there's tons of other stuff in UIBezierPath, +好了,在 UIBezierPath 中还有大量其它的东西 586 00:25:03,001 --> 00:25:04,567 don't have time to cover it, you should look it up. +但没有时间去顾及了,你应该自己去了解 587 00:25:04,636 --> 00:25:06,369 Okay, UIColor. +好了,下一个 UIColor 588 00:25:06,438 --> 00:25:07,972 So UIColor, really simple. +UIColor 非常简单 589 00:25:08,040 --> 00:25:10,641 Okay, there's some common colors like green, red, +UIColor 中有一些常用的颜色,比如绿色、红色 590 00:25:10,709 --> 00:25:11,808 yellow, purple. +黄色、紫色 591 00:25:11,877 --> 00:25:13,610 Those have type methods on UIColor. +这些颜色都是 UIColor 的类方法(注:属性) 592 00:25:13,679 --> 00:25:15,278 Remember, type methods, static methods? +记住,类方法和静态方法 593 00:25:15,347 --> 00:25:16,046 They're on the type. +都是属于类型的 594 00:25:16,115 --> 00:25:17,247 You don't need an instance of it. +并不需要一个实例 595 00:25:17,316 --> 00:25:19,416 So that's like UIColor.green. +比如 UIColor.green 就是绿色 596 00:25:19,484 --> 00:25:22,686 But there's also initializers that let you create colors +还可以用 UIColor 的构造器创建新的颜色 597 00:25:22,755 --> 00:25:27,057 -from RGB, red, green, blue, or HSB, that's hue, saturation, +from RGB, red, green, blue, or HSB, that's hue, saturation, brightness. +比如 RGB(红、绿、蓝)和 HSB(色调、饱和度、亮度) 598 00:25:27,125 --> 00:25:28,575 -You can even create a color that's made from a pattern. +You can even create a color +你甚至可以把一个图案 599 00:25:28,576 --> 00:25:30,026 -brightness. +that's made from a pattern. +创建成颜色 600 00:25:30,095 --> 00:25:31,794 So that when you draw with that color, +那么在你绘制那个颜色的时候, 601 00:25:31,863 --> 00:25:33,296 it's drawing in a pattern. +实际上绘制的是那个图案 602 00:25:33,365 --> 00:25:34,164 Okay, like a really thick line, +那么,比如说一条很粗的线 603 00:25:34,232 --> 00:25:36,099 we'd actually be showing the details of a pattern, +能绘制出图案的细节 604 00:25:36,168 --> 00:25:38,067 which is kind of fun, using UIImage, +用的是 UIImage,这会很有趣 605 00:25:38,136 --> 00:25:39,303 which I'll talk about in a little bit. +UIImage 之后我再展开讲一点 606 00:25:40,773 --> 00:25:43,640 Of course, all UIViews have a background color. +当然,所有的 UIView 都有一个背景色 607 00:25:43,709 --> 00:25:46,743 We saw this when we did our buttons in the calculator, +我们之前看到过的,以前做的计算器的按键 608 00:25:46,812 --> 00:25:48,211 we made the background color +我们给计算器的按键设置了背景色 609 00:25:48,280 --> 00:25:50,848 of a lot of our buttons be light gray, and I'm sure in +按键的颜色是亮灰,并且我肯定 610 00:25:50,916 --> 00:25:52,649 the homework assignments you made it other colors. +(你们)在课后作业中给它换了其它颜色 611 00:25:52,717 --> 00:25:54,718 Okay, that's just a var on UIView, +那只是 UIView 中的一个变量 612 00:25:54,786 --> 00:25:56,820 that button inherited from UIView. +那个按键从 UIView 中继承 613 00:25:56,888 --> 00:25:59,155 And you can set it to any UIColor you want. +你可以设置为任何你想要的 UIColor 颜色 614 00:25:59,224 --> 00:26:02,359 Now, an interesting thing about colors though is that +现在,有个关于颜色的有趣问题是 615 00:26:02,427 --> 00:26:06,163 they can be transparent, or even semi-transparent, okay? +颜色可以是透明或者是半透明的 616 00:26:06,232 --> 00:26:09,299 And they are done, you specify that with alpha. +你可以通过指定 alpha 来实现 617 00:26:09,368 --> 00:26:10,900 How many people here know what alpha +有多少人知道在图形处理中 618 00:26:10,969 --> 00:26:11,936 is when it comes to graphics? +alpha 代表什么意思? 619 00:26:13,038 --> 00:26:14,137 Okay, so hardly anybody. +好吧,看来几乎没有 620 00:26:14,206 --> 00:26:18,141 So alpha is just a value between 0 and 1, where 0 means +alpha 就是一个 0 到 1 之间的数值 621 00:26:18,210 --> 00:26:21,144 fully transparent and 1 is fully opaque. +0 是全透明,1 意味着不透明 622 00:26:21,213 --> 00:26:23,247 So if you have a color like a triangle and +比如你有一个三角形 623 00:26:23,315 --> 00:26:26,016 you fill it with green, then if it's fully opaque, +你为其填充了绿色,如果它不透明 624 00:26:26,084 --> 00:26:28,551 you can't see anything behind that triangle. +你就不能看到任何在三角形后面的东西 625 00:26:28,620 --> 00:26:30,787 But if it were 50%, 0.5 alpha, +但你设置 50%,0.5 alpha 值 626 00:26:30,856 --> 00:26:33,189 then you'd be able to see the green but +你依然可以看到绿色 627 00:26:33,258 --> 00:26:36,927 you'd also be able to see the things behind it a little bit. +但你还可以看到一点绿色背后的东西 628 00:26:36,995 --> 00:26:38,728 50% kinda, okay? +半透明的样子,懂了吗? 629 00:26:38,797 --> 00:26:40,230 If it was zero, you wouldn't see any +如果是 0,那么你就看不到任何绿色 630 00:26:40,298 --> 00:26:42,165 green because it would be fully transparent. +因为它是全透明 631 00:26:42,234 --> 00:26:43,267 You'd be looking all the way through it, so +你能看到其背后所有的东西 632 00:26:43,335 --> 00:26:45,102 you wouldn't see any green, okay? +你无法看到任何绿色,懂了吗? 633 00:26:45,171 --> 00:26:47,304 diff --git a/subtitles/5. Gestures and Multiple MVCs.srt b/subtitles/5. Gestures and Multiple MVCs.srt old mode 100644 new mode 100755 index b01de44..b65712a --- a/subtitles/5. Gestures and Multiple MVCs.srt +++ b/subtitles/5. Gestures and Multiple MVCs.srt @@ -16,158 +16,197 @@ CS193P 课程,iOS 应用程序开发 4 00:00:16,183 --> 00:00:18,650 This is lecture number five? +这是第五节课? 5 00:00:18,719 --> 00:00:20,251 Is that right? The lecture number five? +对吧?这是第五节课? 6 00:00:20,320 --> 00:00:21,453 Yeah, lecture number five. +嗯看来是的,第五节课 7 00:00:22,790 --> 00:00:25,990 Today we are going to start off with a little demo, +今天我们将从新的小 demo 开始学习 8 00:00:26,059 --> 00:00:29,594 where I'm gonna take the application we worked on last +我将会使用上一次我们开发的程序 9 00:00:29,663 --> 00:00:31,763 time, and add a model to it. +并加入新的模型进去 10 00:00:31,831 --> 00:00:34,999 Cuz we have only worked on the view part of that, +因为之前我们只做了视图部分 11 00:00:35,068 --> 00:00:37,036 building that nice cool FaceView, +做出了那个漂亮的 FaceView(笑脸) 12 00:00:37,104 --> 00:00:40,305 now we are going to add a model to that MVC. +现在我们要加入一个模型到 MVC 中 13 00:00:40,374 --> 00:00:42,841 Then we're going to come back to the slides and +然后我们会回到幻灯片当中 14 00:00:42,910 --> 00:00:45,477 I'm going to do some slides on gestures. +然后会在幻灯片中讲关于手势操作 15 00:00:45,545 --> 00:00:49,013 Obviously, you want to be able to have input to your app, +很显然,你肯定想在你的 app 中有一个输入功能 16 00:00:49,082 --> 00:00:50,915 you need to know how to do multi-touch gestures, +那么你需要知道如何使用多点触控手势功能 17 00:00:50,984 --> 00:00:52,518 we'll talk all about that, and +我们将会讨论这个 18 00:00:52,586 --> 00:00:55,220 then I will go back to our FaceView application and +然后我会回到我们的 FaceView 程序 19 00:00:55,289 --> 00:00:58,957 we will add some gestures, pinching, panning, tapping. +并在其中加入一些手势功能,比如缩放,拖动等 20 00:00:59,026 --> 00:01:01,894 And finally, I will go back to the slides again and +最后,我会再次回到幻灯片 21 00:01:01,962 --> 00:01:04,062 start talking about multiple MVCs. +开始讲述关于多个 MVC 的知识 22 00:01:04,130 --> 00:01:06,364 How to build bigger applications that are made out +如何通过结合 MVC 来开发出功能更加强大 23 00:01:06,433 --> 00:01:11,837 of combining MVCs, so that's what's on tap for today. +的软件,这是我们今天要讲的内容 24 00:01:11,906 --> 00:01:17,809 So let's jump right back into this FaceIt Demo. +那么让我们回到之前开发的 FaceIt Demo 中 25 00:01:17,878 --> 00:01:21,346 And if you remember where we left off, +如果你还记得上次我们讲到哪了 26 00:01:21,414 --> 00:01:24,048 we had this nice view, it was really cool because, +我们有一个很棒的视图,因为我们可以 27 00:01:24,117 --> 00:01:28,220 in Interface Builder, we could do things like open the eyes. +在 Interface Builder 中进行操控,比如让其睁开眼睛 28 00:01:28,289 --> 00:01:31,189 We could make it really big, +还可以让笑脸变得很大 29 00:01:31,258 --> 00:01:36,261 we could make it really small, or anywhere in between. +或者变得很小,总之大小随你定 30 00:01:36,330 --> 00:01:39,297 And we could change the color, green, +我们还可以改变颜色 31 00:01:39,366 --> 00:01:41,299 something like that, so that's cool. +比如绿色之类的,很酷是吧 32 00:01:41,368 --> 00:01:44,302 And this is a nice reusable thing that's got a little +这是个漂亮的可变样的脸,有着一个小型 33 00:01:44,371 --> 00:01:46,104 public API to it. +公共接口 34 00:01:46,173 --> 00:01:48,240 These inspectable things are all public, +这些可审查(@IBInspectable)元素都是公开的 35 00:01:48,308 --> 00:01:52,110 so, we can set the mouth curvature, we can open and +所以,我们可以设置嘴巴的曲度,我们可以 36 00:01:52,178 --> 00:01:53,878 close the eyes, we can change those things, like scale. +睁开或闭上眼睛,我们可以改变比如比例那些设定 37 00:01:53,947 --> 00:01:56,882 And so, it's nice, it's this nice reusable face. +那么,这是个很棒的东西,一个可变样的脸 38 00:01:56,950 --> 00:02:01,086 And what we're going to do is make our MVC have a model. +那么接下来我们要做的,就是让我们的 MVC 有一个模型 39 00:02:01,155 --> 00:02:03,788 That model is not gonna match up exactly to what our +这个模型不会完全的符合我们 40 00:02:03,857 --> 00:02:06,324 FaceView can do, because that's the way models work. +在 FaceView 上想要的,因为这就是模型的工作方式 41 00:02:06,393 --> 00:02:09,961 Models in the world are often databases or something, their +在现实生活中,模型经常是数据库 42 00:02:10,030 --> 00:02:13,031 schema doesn't quite match what view you have around. +它们工作的方法通常和你的视图是不一致的 43 00:02:13,100 --> 00:02:15,600 @@ -6158,1030 +6197,1287 @@ So this is what that looks like. 1400 01:03:55,332 --> 01:03:57,432 Here I've got split view controller on the left. +我已经在左边有了分屏控制器 1401 01:03:57,501 --> 01:03:59,767 I've got calculator view control on the top and +在顶端有计算器视图控制器 1402 01:03:59,836 --> 01:04:02,236 -I've got a graph and control view on the bottom. +I've got a graphing view controller on the bottom. +我在底部还有绘制图像的控制器 1403 01:04:02,305 --> 01:04:03,370 So I'm just gonna control, +所以我按住 control 键 1404 01:04:03,439 --> 01:04:04,972 drag from the split view controllers, +从分屏控制器中拖拽 1405 01:04:05,041 --> 01:04:06,174 the calculator controller. +到计算器控制器 1406 01:04:06,243 --> 01:04:08,510 This little black window is gonna come up. +这个小的黑色窗口将会显示出来 1407 01:04:08,578 --> 01:04:12,914 I'm gonna choose master view controller from the list and +我将会从列表中选择 master view controller 1408 01:04:12,983 --> 01:04:16,951 that's gonna hook that one up top to my master. +那样会将其作为我的主视图控制器 1409 01:04:17,020 --> 01:04:20,155 Then, I'm gonna Ctrl+drag to the bottom one, the black +然后,我按住 control 并拖拽到底部,那个黑色的 1410 01:04:20,223 --> 01:04:22,924 window comes up I'm gonna choose Detail View Controller +窗口显示出来了,我选择 detail view controller 1411 01:04:22,993 --> 01:04:24,659 then it's gonna make that connection. +然后会让其连接为详细信息视图控制器 1412 01:04:25,829 --> 01:04:27,361 Okay, as simple as that. +完成了,就像之前那么简单 1413 01:04:27,430 --> 01:04:29,363 Now you've got the split view with master that's +现在你已经有了 1414 01:04:29,432 --> 01:04:31,566 calculator of your controller and +计算器控制器和 1415 01:04:31,635 --> 01:04:34,169 detail that is going to be a graphic view controller. +分屏显示的详细信息会是图像控制器 1416 01:04:35,405 --> 01:04:37,205 Now, one interesting thing here though, +这里有个有趣的事情 1417 01:04:37,274 --> 01:04:39,774 is this split view does not work on an iPhone. +这个分屏显示无法在 iPhone 上运行 1418 01:04:39,843 --> 01:04:43,344 Well it works on iPhone plus, iPhone six plus or +但能在 iPhone Plus 上运行,iPhone6 Plus 或 1419 01:04:43,413 --> 01:04:46,013 seven plus, the kind of big ones, but it does not work on +7 Plus,类似这种大屏幕的,但无法运行在 1420 01:04:46,082 --> 01:04:48,783 a normal iPhone, it's just not enough screen real estate to +小尺寸 iPhone 上,因为屏幕不够大 1421 01:04:48,851 --> 01:04:52,053 really do the split view thing, so we can't do it. +所以无法做分屏显示,所以我们没法做 1422 01:04:52,122 --> 01:04:54,989 So, what we really want to do is build a UI though that +那么,我们要做的是开发一个 UI 界面 1423 01:04:55,058 --> 01:04:56,191 works on all the devices. +能在所有尺寸设备上运行的 1424 01:04:56,259 --> 01:04:59,827 So to do that, what we do is we're gonna wrap +那么要想开发出来,我们需要 1425 01:04:59,896 --> 01:05:02,763 the master and the detail if we want. +把主视图和详细视图分别 1426 01:05:02,832 --> 01:05:05,466 We're gonna wrap them in a navigation controller. +嵌套到导航控制器里 1427 01:05:05,535 --> 01:05:06,901 And then when they're on iPhone, +当其运行在 iPhone 上的时候 1428 01:05:06,969 --> 01:05:08,102 they won't use the split view part, +程序无法使用分屏功能 1429 01:05:08,171 --> 01:05:09,838 they'll just use the navigation controller. +那时程序就只会用到导航控制器 1430 01:05:11,041 --> 01:05:13,808 It's really cool, how it figures this out. +这非常棒,我们解决了这个问题 1431 01:05:13,876 --> 01:05:17,178 The way to wrap a view controller that's in there, +嵌入视图控制器的方法在这 1432 01:05:17,246 --> 01:05:19,047 you wanna wrap it in a Navigation Controller, +你需要嵌套到导航控制器里 1433 01:05:19,116 --> 01:05:20,282 you just go to the Editor menu, +你只需要到编辑器菜单(Editor) 1434 01:05:20,350 --> 01:05:22,116 the same place we did embed and stack view, +在之前我们嵌入到堆栈视图的地方 1435 01:05:22,185 --> 01:05:23,151 and some of that. +Embed in,一样一样 1436 01:05:23,220 --> 01:05:26,887 And you select the whole scene of your MVC, and +当你选择了整个 MVC 的场景时 1437 01:05:26,956 --> 01:05:29,623 you go to the Editor Menu and +你去到编辑器菜单 1438 01:05:29,692 --> 01:05:31,993 you say embed in navigation controller. +选择嵌入到导航控制器(Navigation Controller) 1439 01:05:32,062 --> 01:05:34,295 So I've selected that top, calculate and control and +也就是我选中顶端的计算器控制器 1440 01:05:34,363 --> 01:05:35,563 when I do that, +当我这样做时 1441 01:05:35,632 --> 01:05:38,199 it's going to put it inside a navigation controller. +它就会被放到一个导航控制器里 1442 01:05:38,268 --> 01:05:40,067 Did you see that? +你看到了吗? 1443 01:05:40,136 --> 01:05:42,236 -Now, I've got the flip view, it points to a navigation +Now, I've got the split view, it points to a navigation +现在,我有分屏视图了,它指向导航控制器 1444 01:05:42,305 --> 01:05:44,372 -controller, so the master of this flip view is actually +controller, so the master of this split view is actually +所以分屏控制器的主视图实际上 1445 01:05:44,441 --> 01:05:46,808 that navigation controller, and then the navigation +是个导航控制器,然后 1446 01:05:46,876 --> 01:05:50,311 controller root view controller is the calculator. +导航控制器的根视图是计算器 1447 01:05:50,379 --> 01:05:52,146 So, if you're on a device that can do split view, +所以,如果你在用一台能够分屏显示的设备 1448 01:05:52,215 --> 01:05:53,114 like an iPad or a plus, +比如 iPad 或者 iPhone Plus 1449 01:05:53,183 --> 01:05:55,316 you're going to get the whole split view effect. +你会获得完整的分屏显示效果 1450 01:05:55,385 --> 01:05:56,684 But if you're on just an iPhone, +但如果你在(小尺寸)iPhone 上运行 1451 01:05:56,753 --> 01:05:58,486 it's not going to do the split view. +其不能分屏显示 1452 01:05:58,555 --> 01:06:00,721 It's just going to do the navigation controller. +这时候就要用到导航控制器 1453 01:06:00,790 --> 01:06:01,989 So, when you look at the detail, +所以,你要查看详细视图 1454 01:06:02,058 --> 01:06:04,192 it's going to slide it in. +详细视图会滑进来覆盖主视图 1455 01:06:04,261 --> 01:06:06,761 Whereas if you're on a iPad in landscape, +然而当你在 iPad 上时 1456 01:06:06,830 --> 01:06:09,764 you're gonna see Master and Detail at the same time. +你会同时看到主界面和详细信息 1457 01:06:09,833 --> 01:06:13,568 Now, you can also do the same thing- yeah, and so +现在,你也可以做同样的事情了,等等 1458 01:06:13,637 --> 01:06:15,703 the UINavigationController is the Master, +导航控制器是主视图 1459 01:06:15,771 --> 01:06:17,639 as, as I talked about. +像我之前所说的 1460 01:06:17,707 --> 01:06:20,074 So you can do the same thing with the Detail. +你可以在详细信息中做同样的事 1461 01:06:20,143 --> 01:06:22,410 Now why would you ever do that with the Detail? +为什么要这样做呢? 1462 01:06:22,479 --> 01:06:24,111 Because yo've already done it with the master and +因为你已经嵌套了主视图 1463 01:06:24,180 --> 01:06:26,513 so you gotta click in the master to get to the detail, +你只需要点一下主视图来获取详细信息 1464 01:06:26,582 --> 01:06:28,516 so yo're kinda already gonna be in a navigation controller, +其实这就有点像导航控制器 1465 01:06:28,585 --> 01:06:29,584 and tha's true. +大实话 1466 01:06:29,653 --> 01:06:32,186 But wha's kinda nice about putting the detail +但我们可以把它变得更完美 1467 01:06:32,255 --> 01:06:35,223 in a navigation controller is you get that little title bar, +把详细视图嵌入导航控制器后会有标题栏 1468 01:06:35,292 --> 01:06:36,524 you know the little gray title bar? +就是那个灰色的小标题栏 1469 01:06:36,593 --> 01:06:37,391 So now, your master and +所以现在,你的主视图和 1470 01:06:37,460 --> 01:06:39,561 your detail both have a title bar on the top and +详细信息在屏幕顶端都有标题栏 1471 01:06:39,629 --> 01:06:40,961 they match up nicely. +他们看上去更加相匹配了 1472 01:06:41,030 --> 01:06:42,930 So if you wanna title on your detail, +如果你想在你的详细信息上有个标题 1473 01:06:42,999 --> 01:06:43,598 that's a good thing to do. +这是个好方法 1474 01:06:43,666 --> 01:06:45,566 The only thing to be careful there though is +唯一需要注意的事情是 1475 01:06:45,635 --> 01:06:48,269 now your detail in not a graph view controller. +详细信息视图控制器不是图形视图控制器 1476 01:06:48,338 --> 01:06:50,638 Your detail is now a navigation controller. +你的详细信息现在是一个导航控制器 1477 01:06:50,706 --> 01:06:52,540 So if you wanna get the graph view controller and +如果你想访问图形视图控制器 1478 01:06:52,609 --> 01:06:54,342 like talk to it, tell it what to graph or +像之前说的那样,告诉它什么需要绘制之类的 1479 01:06:54,410 --> 01:06:56,911 something like that, you need to get the root view +你需要间接通过 1480 01:06:56,980 --> 01:06:58,580 controller of the navigation controller. +导航控制器中的根视图控制器 1481 01:06:59,982 --> 01:07:01,549 So it's just subtle difference but +这有一点微妙的变化但 1482 01:07:01,617 --> 01:07:03,685 if you wrap your detail in a navigation controller, +如果你用导航控制器嵌套详细信息控制器 1483 01:07:03,753 --> 01:07:05,853 the detail has come become a navigation controller. +那么详细信息就变成了一个导航控制器 1484 01:07:05,922 --> 01:07:07,588 It's easy to get to the graph view controller, +获取图形视图控制器非常简单 1485 01:07:07,657 --> 01:07:09,724 cuz the root view controller of the navigation controller. +因为有了在导航控制器里的根视图控制器 1486 01:07:12,095 --> 01:07:15,096 That's how you wire up the split views so +这就是你如何让分屏视图 1487 01:07:15,165 --> 01:07:17,298 that it works cross platform, all devices. +适应所有操作平台和设备 1488 01:07:18,568 --> 01:07:21,302 The last thing we're gonna talk about is segueing. +今天最后一件我们要讨论的事情是关于转场功能 1489 01:07:21,370 --> 01:07:25,406 So we know how to wire up the split view controller, and +那么我们已经知道如何使用分屏控制器,并且 1490 01:07:25,475 --> 01:07:26,974 we know how to do a navigation control, +我们还知道如何使用导航控制 1491 01:07:27,043 --> 01:07:29,376 we just embed it in the navigation controller. +我们把它嵌入到导航控制器中 1492 01:07:29,445 --> 01:07:31,346 I didn't talk about the tab bar controller by the way, +顺便说一句我之前并没有说过标签栏控制器 1493 01:07:31,414 --> 01:07:32,446 but that's easy. +但那很简单 1494 01:07:32,515 --> 01:07:35,450 You just drag a tab bar controller out and CTRL + drag +只要拖拽出一个标签栏控制器,按住 control 1495 01:07:35,518 --> 01:07:38,152 to all of the MVC's that you want it to show, +然后拖拽到所有你希望显示出的 MVC 中 1496 01:07:38,221 --> 01:07:42,223 and you can actually even drag the little icons around +而且实际上你还可以拖拽一个小图标并 1497 01:07:42,291 --> 01:07:43,724 to put them in order. +使他们有序的排列开来 1498 01:07:43,793 --> 01:07:46,227 You can even set the icons in text in the interface builder +甚至你可以在 Interface Builder 中调整图标和标题 1499 01:07:46,296 --> 01:07:46,961 with an inspector. +通过检查工具 1500 01:07:47,029 --> 01:07:49,797 So, tab bars, so simple I don't even want to waste time +标签栏太简单,我并不想花太多时间 1501 01:07:49,866 --> 01:07:52,633 showing it, but so we know how to kind of hook up and control +我们现在知道如何用 control 拖拽连接 1502 01:07:52,702 --> 01:07:56,971 drags and wire up, or embed to do the navigation controllers. +还知道如何嵌入到导航控制器中 1503 01:07:57,040 --> 01:07:59,540 How do we go from one to the other, like in the navigation +我们如何从一个跳转到另外一个呢,像在导航控制器内 1504 01:07:59,609 --> 01:08:02,109 controller, how do we go from all settings to settings and +我们如何在设置应用中跳转到通用设置 1505 01:08:02,178 --> 01:08:03,244 from settings to accessibility, +从通用设置到辅助功能 1506 01:08:03,312 --> 01:08:07,081 and accessibility to larger text? +然后从辅助功能到更大字体呢? 1507 01:08:07,149 --> 01:08:09,651 How do we set up that transition or how do we make +我们如何设置其转场,或者说我们如何能做到 1508 01:08:09,719 --> 01:08:13,354 it so that we press a button in our calculator split view +当我们在分屏显示的计算器中按下一个按钮 1509 01:08:13,423 --> 01:08:16,557 and it causes that graph to be replaced with a new graph? +会使新画面替换掉旧画面呢? 1510 01:08:16,626 --> 01:08:17,157 How do we do that? +到底如何实现呢? 1511 01:08:17,226 --> 01:08:19,226 We do that with what are called segues. +我们要做的我们称之为 Segue(转场) 1512 01:08:19,295 --> 01:08:20,628 I've alluded to this earlier. +之前我有暗示过 1513 01:08:23,032 --> 01:08:24,832 These are the kinds of segues that exist. +自带的转场有以下几种 1514 01:08:24,900 --> 01:08:26,066 There's a show segue. +最简单的 Show,展示 1515 01:08:26,135 --> 01:08:28,436 That means, if you're in a Navigation Controller, +那意味着,如果你在导航控制器中 1516 01:08:28,504 --> 01:08:29,537 slide a card on. +新页面会滑进来 1517 01:08:31,441 --> 01:08:32,740 There's Show Detail, +有 Show Detail, 显示详细信息 1518 01:08:32,809 --> 01:08:34,208 which if you're a Navigation Controller, +但如果你是一个导航控制器 1519 01:08:34,277 --> 01:08:36,044 still means slide a card on. +依然是滑进来新页面 1520 01:08:36,112 --> 01:08:37,578 But if you're inside a Split View, +但如果你在分屏显示的情况下 1521 01:08:37,647 --> 01:08:40,982 it means put this new MVC where the detail goes. +意味着需要将 MVC 作为详细信息显示 1522 01:08:41,051 --> 01:08:42,683 That's why it's called Show Detail. +这就是为什么叫做显示详情 1523 01:08:42,752 --> 01:08:44,552 So Show Detail behaves differently depending on +那么显示详细信息不同的行为取决于 1524 01:08:44,621 --> 01:08:45,653 whether you're in the Split View or +你是在分屏显示还是 1525 01:08:45,722 --> 01:08:48,122 whether you're in a Navigation Controller. +在导航控制器中 1526 01:08:48,191 --> 01:08:50,591 Modal segue, it's kind of interesting one. +模态框转场,这是个有趣的东西 1527 01:08:50,660 --> 01:08:53,227 It takes over the entire screen and lets +它会占用整个屏幕并让 1528 01:08:53,296 --> 01:08:57,831 the MVC that you're segueing into own the whole screen. +你过渡到的 MVC 占用整个屏幕 1529 01:08:57,900 --> 01:09:00,034 Now, these can be somewhat disturbing to the users cuz, +现在,这些东西会让使用者感到厌烦 1530 01:09:00,103 --> 01:09:01,869 I can't get back to where I was, +“我无法回到我之前所操作的” 1531 01:09:01,938 --> 01:09:03,804 cuz there's no back button or anything. +因为没有返回键或其它的 1532 01:09:03,873 --> 01:09:05,239 That whatever MVC comes up and +那就是为什么出现的 MVC 1533 01:09:05,308 --> 01:09:07,775 takes over the screen has to provide some UI to get out of +要提供某种用户界面来退出全屏 1534 01:09:07,844 --> 01:09:10,945 there like cancel or done, or something. +比如取消或者完成(按钮),或者类似的 1535 01:09:11,013 --> 01:09:13,915 So we try to stay away from Modal if we can. +所以我们尽可能的远离模态框 1536 01:09:13,983 --> 01:09:18,019 So Popover is sort of the same as Modal, but +弹出框和模态框类似 1537 01:09:18,087 --> 01:09:20,621 instead of taking over the whole screen, it just puts up +但不会占用整个屏幕,只让其出现 1538 01:09:20,690 --> 01:09:22,656 a little pop-up window, a little popover window, +一个小弹窗,一个小的弹出框 1539 01:09:22,725 --> 01:09:24,958 you've seen that, on iPad especially. +你已经在 iPad 上见过了 1540 01:09:25,027 --> 01:09:28,229 It's still Modal, because if you click anywhere else, +它仍然是模态框,但如果你点击任何地方 1541 01:09:28,297 --> 01:09:29,797 the popover goes away. +这个弹窗就会消失 1542 01:09:29,866 --> 01:09:32,233 So it's essentially modal. +所以本质是它还是模态框 1543 01:09:32,302 --> 01:09:33,634 It's a little nicer than modal, though, +但它比模态框好一些 1544 01:09:33,703 --> 01:09:35,737 because you can really see the background kinda grayed out. +因为你可以看到背景变成灰色 1545 01:09:35,805 --> 01:09:37,772 And if you don't want what's in the popover, +如果你不需要弹出框内的信息 1546 01:09:37,840 --> 01:09:39,541 just click somewhere else and it goes away. +只需要点击任意其它位置它便会消失 1547 01:09:39,609 --> 01:09:42,076 So yeah, popover's a little nicer than modal. +所以是的,弹出框比模态框好些 1548 01:09:42,145 --> 01:09:44,078 But it only works on fairly large screens, +但其只在足够大的屏幕上工作 1549 01:09:44,147 --> 01:09:46,247 unless you have a really small pop over window. +除非你想有一个非常小的弹出框在屏幕上 1550 01:09:47,183 --> 01:09:51,319 Now, I'm going to emphasize for +现在,我要强调 1551 01:09:51,387 --> 01:09:54,421 the second time what I said before segues always create +第二次强调我之前说的转场总是会创建 1552 01:09:54,490 --> 01:09:56,824 a new instance of the MVC. +一个新的 MVC 实例去取代旧的 1553 01:09:56,893 --> 01:10:00,695 All of the segues, all of them, modal, popover, show, +所有的转场,模态框,弹出框,展示 1554 01:10:00,764 --> 01:10:01,495 -slide in the min, +slide them in, +把视图滑进来 1555 01:10:01,564 --> 01:10:04,265 show detail, even show detail in the split view. +显示详情,包括在分屏中显示详情 1556 01:10:04,334 --> 01:10:07,635 If you have a calculator and you say graph my function and +如果你有一个计算器,让它绘制我的函数 1557 01:10:07,704 --> 01:10:09,470 you segue to a graph view controller, +你要转场到一个图形视图控制器 1558 01:10:09,539 --> 01:10:11,372 it throws away the one that was there and +它会去掉正在显示的 1559 01:10:11,441 --> 01:10:14,908 puts a new one there, always creating new MVCs. +总是会创建新的 MVC 放在那儿 1560 01:10:14,977 --> 01:10:18,379 So think of these MVCs as ephemeral, they come alive, +所以想象这些短暂 MVC,它们被激活 1561 01:10:18,448 --> 01:10:20,280 they do their job and they go away. +它们完成了它们的工作然后就走了 1562 01:10:20,349 --> 01:10:23,784 They don't live you know, long lives. +它们不像你,能活那么久 1563 01:10:23,853 --> 01:10:25,686 Now the master and a split view. +现在主视图和分屏视图 1564 01:10:25,755 --> 01:10:27,121 The root view of a navigational, +导航的根视图 1565 01:10:27,190 --> 01:10:28,823 they tend to live fairly long. +它们能活很久 1566 01:10:28,891 --> 01:10:31,526 But even those, if that split view, if that navigational +但尽管那样,如果那个分屏视图,那个导航器 1567 01:10:31,594 --> 01:10:33,428 were to go off screen, they go away as well. +消失在屏幕上,它们也就走了 1568 01:10:35,698 --> 01:10:37,398 So how do we make these segues happen? +所以我们如何实现这些转场呢? 1569 01:10:37,467 --> 01:10:39,233 Of course, we use control drag. +当然是使用拖拽功能啦 1570 01:10:39,302 --> 01:10:41,569 We love to use control drag, so here for +我们喜欢用拖拽功能,所以这里 1571 01:10:41,637 --> 01:10:43,404 example is the calculator example. +举的例子是计算器的例子 1572 01:10:43,472 --> 01:10:44,672 I've got a split view. +我现在有了一个分屏视图 1573 01:10:44,740 --> 01:10:46,874 And in my calculator there in the upper right +在我的计算器的右上角 1574 01:10:46,943 --> 01:10:49,477 I have a button it's very hard to see but +我有一个非常难看到的按钮 1575 01:10:49,545 --> 01:10:51,111 it's a little picture of a graph. +那是个函数图像的图片 1576 01:10:51,180 --> 01:10:52,813 So that's the button that when I press it, +所以当我按下那个按钮时 1577 01:10:52,882 --> 01:10:55,549 it's gonna take whatever's in my calculator and graph it. +无论计算器是什么内容,图像视图都会绘制出来 1578 01:10:55,618 --> 01:10:59,019 So if I've typed in for example m cosine, +所以如果我输入比如余弦 m 1579 01:10:59,088 --> 01:11:04,258 it's gonna draw a cosine wave, that's what that button does. +它便会画一个余弦波,那就是按钮的功能 1580 01:11:04,327 --> 01:11:07,661 So I just go into interface builder here, control drag +那么我到 Interface Builder 这,按 control 1581 01:11:07,730 --> 01:11:10,564 from that button down to the detail right there. +拖拽按钮到右边详细信息那 1582 01:11:10,633 --> 01:11:11,532 When I let go, +当我放开鼠标 1583 01:11:11,601 --> 01:11:13,634 it's going to put up just a little black window, +会出现一个小的黑色窗口 1584 01:11:13,703 --> 01:11:15,502 which I'll show you a little detail of. +我会展示它具体长什么样 1585 01:11:15,571 --> 01:11:16,003 It looks like that. +就像那样 1586 01:11:16,072 --> 01:11:18,106 And I'm gonna pick the segue I want. +然后我要选择一个我想要的转场 1587 01:11:18,174 --> 01:11:21,675 Well, since this is a Split view, if I can, +那么,既然这是个分屏视图,如果我可以的话 1588 01:11:21,744 --> 01:11:23,177 I'm going to show detail. +我将要其显示详情 1589 01:11:23,245 --> 01:11:25,079 Put it on the right side of the split view. +将其放到分屏视图的右边 1590 01:11:25,148 --> 01:11:27,348 Now, if I were in this same storyboard, but +现在,如果我在这相同的 storyboard 1591 01:11:27,417 --> 01:11:29,583 I was on an iPhone non-plus, +但我当是在小尺寸的 iPhone 上 1592 01:11:29,652 --> 01:11:31,251 then even though I'm picking show detail here, +即使我选择显示详情,其仍然会 1593 01:11:31,320 --> 01:11:33,754 it's still going to do the navigation controller show, +在(小尺寸 iPhone 上)通过导航控制器呈现 1594 01:11:33,823 --> 01:11:36,291 because there is no split view side, when I'm on the iPhone. +因为在小尺寸的 iPhone 上没有办法分屏显示 1595 01:11:37,760 --> 01:11:39,894 So I pick the segue type I want, and +所以我选择一个我想要的转场类型 1596 01:11:39,962 --> 01:11:41,229 it creates the segue. +Xcode 会创建 segue 实现转场效果 1597 01:11:41,297 --> 01:11:43,564 And it appears in your storyboard, +然后它会出现在你的 storyboard 1598 01:11:43,633 --> 01:11:45,232 it can even be clicked on and inspected. +其依然可以被点击并检查 1599 01:11:45,301 --> 01:11:47,467 And in fact you're gonna always want to click on +且事实上你总会想要去点击 1600 01:11:47,536 --> 01:11:49,170 that thing and inspect it. +并检查它 1601 01:11:49,239 --> 01:11:52,173 -Cuz you don't wanna set this thing right here which +Cuz you gonna wanna set this thing right here which +因为你会想要设置这里的 1602 01:11:52,242 --> 01:11:53,841 is the identifier. +identifier,标识符 1603 01:11:53,910 --> 01:11:56,677 Every segue has an identifier, it's just the string and +每一个转场都有一个标识符,这只是一个字符串 1604 01:11:56,745 --> 01:12:00,013 that identifier is what's you're gonna use in your code +这个标识符是你在代码中 1605 01:12:00,082 --> 01:12:02,649 to talk about this segue. +用来与转场进行互动的 1606 01:12:02,718 --> 01:12:04,252 And I'll talk about what you've +接下来我要谈到的是你们之前 1607 01:12:04,320 --> 01:12:07,120 been talk about regarding segues, any moment here. +已经谈论过的 转场,任何时候 1608 01:12:07,189 --> 01:12:08,389 So always set that. +所以总是需要放置它 1609 01:12:08,457 --> 01:12:09,223 And you wanna set it, +且你会想要放置一个 1610 01:12:09,291 --> 01:12:12,059 the identifier to be something that kind of says what is +不言而喻的标识符 1611 01:12:12,128 --> 01:12:12,660 segue does. +说明转场的作用是什么 1612 01:12:12,729 --> 01:12:14,995 So in this case it shows a graph, so +这种情况它是展示了一个图像 1613 01:12:15,064 --> 01:12:16,764 I call this show graph. +那么我称之为 Show Graph 1614 01:12:19,802 --> 01:12:22,236 That's how you set up your segue. +这就是你如何设置转场效果 1615 01:12:22,304 --> 01:12:24,204 And that's true for navigation controller as well. +同样也适用于导航控制器 1616 01:12:24,273 --> 01:12:25,673 If you have a navigation controller and +如果你有一个导航控制器且 1617 01:12:25,742 --> 01:12:28,209 you have a button that causes another card to slide on you +你有一个按钮让另一个页面滑进来 1618 01:12:28,278 --> 01:12:30,445 just control drag from that button to the other MVC. +只需按住 control 后从按钮拖拽到其它 MVC 1619 01:12:30,513 --> 01:12:33,915 And then you use a show segue, and it'll just work. +接着选择用 Show 转场展示,这样就完成了 1620 01:12:33,983 --> 01:12:35,049 Has to be all inside, +不过必须要在导航控制器里面 1621 01:12:35,117 --> 01:12:37,751 embedded in navigation controller, of course. +当然嵌套到导航控制器才行 1622 01:12:37,820 --> 01:12:39,720 So what can you do with these identifiers? +所以你可以用这些标识符来做什么呢? 1623 01:12:39,789 --> 01:12:42,457 It is actually possible to cause a segue to happen from +其实代码能用这个标识符实现转场 1624 01:12:42,525 --> 01:12:45,425 code, with performSegue withIdentifier, but +使用的是 performSegue(withIdentifier:) 方法 1625 01:12:45,494 --> 01:12:47,961 I'm not gonna talk about that, cuz we're never gonna do that. +我并不打算讨论那些,因为我们永远也不会用到 1626 01:12:48,030 --> 01:12:49,329 We always gonna have buttons, +我们总是会通过按钮实现 1627 01:12:49,398 --> 01:12:50,764 well I'm not gonna say we're never gonna do that, +好吧我不应该说我们永远也不会用到 1628 01:12:50,833 --> 01:12:52,767 but we won't be doing that in your assignment three, +但我们在作业三中还暂时不会用到 1629 01:12:52,835 --> 01:12:53,267 that's for sure. +这是肯定的 1630 01:12:53,336 --> 01:12:54,301 It's pretty rare. +很少会这样做 1631 01:12:54,370 --> 01:12:56,303 But you can do it with performSegue. +但你可以通过 performSegue 实现 1632 01:12:56,372 --> 01:12:59,006 But the more important use of the identifier is not causing +标识符最重要的用法不是实现转场 1633 01:12:59,075 --> 01:13:00,774 segues to happen cuz segues kinda happen +因为转场效果的实现是 1634 01:13:00,843 --> 01:13:02,643 automatically when the buttons are pressed. +当按下按钮时自动实现的 1635 01:13:02,712 --> 01:13:04,645 It's to prepare for a segue. +它的目的是为转场做准备 1636 01:13:04,714 --> 01:13:08,148 This is the most important method in all of +prepare(for segue:) 是所有方法中 1637 01:13:08,217 --> 01:13:11,552 multiple MVC programming is this preparing for segue +实现多个 MVC 编程的最重要的方法 1638 01:13:11,620 --> 01:13:15,489 method which I'm gonna show you in a moment here, okay. +之后我将要在这向你们展示下 1639 01:13:15,558 --> 01:13:18,058 And remember, we're all segueing to a new MVC +别忘了,我们总是转场到新的 MVC 1640 01:13:18,127 --> 01:13:20,227 freshly created, so it's always raw. +全新的,未加处理的 1641 01:13:20,296 --> 01:13:22,830 So we have to prepare it to do what it's going to do. +所以我们需要让其准备好我们要做的 1642 01:13:24,734 --> 01:13:25,466 Here is the method. +方法这样写 1643 01:13:25,534 --> 01:13:27,334 It's called prepare for segue, and +prepare(for segue:), 准备转场 1644 01:13:27,403 --> 01:13:30,972 it also has a sender argument right there. +同时还有 sender 参数,表示发起转场的实例 1645 01:13:31,040 --> 01:13:34,375 The segue that's passed along that first argument +作为第一个参数的转场 segue 1646 01:13:34,444 --> 01:13:37,611 is just a little container that contains interesting +只是一个容器,其中包含了 1647 01:13:37,680 --> 01:13:39,613 information about the segue. +关于转场的信息 1648 01:13:39,682 --> 01:13:42,049 For example, the identifier, Show Graph. +例如标识符(这里是 "Show Graph") 1649 01:13:43,585 --> 01:13:47,187 And very importantly, the controller that you're seguing +然后很重要的,转场到的目标控制器 1650 01:13:47,256 --> 01:13:48,455 too, because the whole point is here, +你为这个方法的作用 1651 01:13:48,524 --> 01:13:51,292 you're suppose to be preparing this MVC that's going to +就是让目标 MVC 准备好 1652 01:13:51,360 --> 01:13:52,593 come on screen. +出现在屏幕上 1653 01:13:52,661 --> 01:13:53,794 To do its job so +完成它的工作 1654 01:13:53,862 --> 01:13:57,431 you get that thing from this little segue object. +所以我们要从 segue 中得到目标控制器 1655 01:13:57,499 --> 01:14:00,301 The sender is kinda like buttons, +sender 就是像按钮一类的 1656 01:14:00,370 --> 01:14:02,636 the button sender when we had the action there. +我们按下去来转场的按钮 1657 01:14:02,705 --> 01:14:05,505