>  기사  >  백엔드 개발  >  iOS 5 스토리보드 시작하기 (3)

iOS 5 스토리보드 시작하기 (3)

黄舟
黄舟원래의
2017-01-20 10:21:291193검색

Segues 소개

이제 스토리보드에 ViewController를 더 추가할 시간입니다. 우리는 사용자가 프로그램에 새로운 플레이어를 추가할 수 있는 시나리오를 만들 것입니다.

BarButtonItem을 Players 장면의 탐색 모음 오른쪽 끝으로 드래그합니다. 표준 + 버튼이 되도록 속성 패널을 통해 식별자를 추가로 변경합니다. 이 버튼을 클릭하면 새 플레이어의 정보를 입력할 수 있는 새 모달 창이 팝업됩니다.

TableViewController를 캔버스로 드래그하여 Players 장면의 오른쪽에 배치합니다. 작업 공간을 더 확보하기 위해 두 번 클릭하여 캔버스를 축소할 수 있습니다.

이 TableViewController를 선택하고 ("EditorEmbedInNavigation Controller" 메뉴를 통해) NavigationController에 포함시킵니다.

다음 참고: + 버튼을 선택하고 Ctrl 키를 누른 채 새로 추가된 NavigationController 쪽으로 드래그하세요.

iOS 5 스토리보드 시작하기 (3)

마우스를 놓고 팝업 메뉴에서 Modal을 선택하세요. Players 장면과 NavigationController 사이에는 추가 화살표가 있습니다.

iOS 5 스토리보드 시작하기 (3)

이 연결을 segue(seg-way로 발음)라고 하며, 이는 하나의 ViewController에서 다른 ViewController로 점프하는 것을 의미합니다. . 이는 하나의 ViewController에 다른 ViewController가 포함되어 있음을 나타내는 데 사용되는 관계와는 다릅니다. 즉, segue는 화면의 모든 것을 변경합니다. TableViewCell(및 이와 유사한 것)의 버튼, 터치 또는 제스처가 발생하면 시작됩니다.

segue의 좋은 점은 새 창을 렌더링하기 위해 코드를 작성할 필요가 없다는 것입니다. 버튼을 IBAction에 연결할 필요가 없습니다. 방금 했던 것처럼 barButtonItem을 연결하는 선을 다음 장면으로 드래그하는 것으로 충분합니다. (컨트롤에 이미 IBAction 연결이 있는 경우 segue가 이를 덮어씁니다.)

프로그램을 실행하고 + 버튼을 눌러주세요. 새로운 TableView가 나타납니다!

iOS 5 스토리보드 시작하기 (3)

이것은 "모달" 세구에입니다. 새 창은 전면 창을 완전히 덮습니다. 팝업 창이 닫히지 않으면 사용자는 이전 창과 상호 작용할 수 없습니다. 그런 다음 새 창을 탐색 컨트롤러 스택에 푸시하는 "푸시" segue를 보여 드리겠습니다.

이 새로운 ViewController는 그다지 유용하지 않습니다. 심지어 닫고 기본 창으로 돌아갈 수도 없습니다!

Segue는 플레이어 창에서 새 창으로 단방향으로만 가능합니다. 반환하려면 대리자 패턴을 사용해야 합니다. 먼저 새 장면에 대한 클래스를 만들어야 합니다. UITableViewController 하위 클래스를 프로젝트에 추가하고 이름을 PlayerDetailsViewController로 지정합니다.

스토리보드 편집기로 돌아가서 새 TableViewController를 선택하고 ID 패널에서 클래스를 PlayerDetailsViewController로 변경합니다. 나는 종종 이 단계를 잊어버리기 때문에 여러분도 나와 같은 일을 하지 않도록 상기시켜 드립니다.

제목을 "플레이어 추가"로 변경합니다(탐색 모음을 두 번 클릭). 또한 두 개의 BarButton 항목을 탐색 모음에 추가합니다. 속성 패널에서 왼쪽 버튼의 식별자를 취소로 설정하고 오른쪽 버튼의 식별자를 완료로 설정합니다.


iOS 5 스토리보드 시작하기 (3)

그런 다음 PlayerDetailsViewController.h를 수정하세요.

@class PlayerDetailsViewController;  
@protocol PlayerDetailsViewControllerDelegate <NSObject>
- ( void ) playerDetailsViewControllerDidCancel :    ( PlayerDetailsViewController *) controller;
- ( void ) playerDetailsViewControllerDidSave :    ( PlayerDetailsViewController *) controller;
@end  
 
@interface PlayerDetailsViewController : UITableViewController  
@property ( nonatomic, weak ) id <PlayerDetailsViewControllerDelegate> delegate;  
- ( IBAction ) cancel :( id ) sender;
- ( IBAction ) done :( id ) sender;  
@end

us 사용자가 취소 또는 완료를 클릭하면 AddPlayer 창에서 플레이어 창으로 돌아갈 수 있도록 대리자 프로토콜이 정의됩니다.

스토리보드 편집기로 돌아가 취소 버튼과 완료 버튼을 해당 작업 메서드에 연결합니다. 첫 번째 방법은 Ctrl 키를 누른 채 BarButtonItem에서 ViewController로 드래그한 다음 팝업 메뉴에서 적절한 작업 방법을 선택하는 것입니다.

iOS 5 스토리보드 시작하기 (3)

PlayerDetailsViewController.m , 다음 두 메서드를 추가하세요.

- ( IBAction ) cancel :( id ) sender {
        [ self.delegate playerDetailsViewControllerDidCancel : self ] ;
} - ( IBAction ) done :( id ) sender {
        [ self.delegate playerDetailsViewControllerDidSave : self ] ;
}

이 두 메서드는 각각 두 개의 BarButton에 해당합니다. 이러한 메서드는 어떤 이벤트가 트리거되었는지를 대리자 개체에 알립니다. 궁극적으로 대리자 개체에 창을 닫도록 요청해야 합니다(필수는 아니지만 마음에 듭니다. 물론 대리자 개체에 알리기 전이나 후에 AddPlayer가 자동으로 닫히도록 할 수도 있습니다).

대리자 메서드는 일반적으로 호출자에 대한 참조를 메서드의 첫 번째 매개변수(또는 유일한 매개변수)로 배치합니다. 이것은 PlayerDetailsViewController 매개변수입니다. 이를 통해 위임 개체는 어떤 개체가 자신에게 메시지를 보냈는지 알 수 있습니다.

대리자 속성을 합성하는 것을 잊지 마세요:

@synthesize Delegate;

우리는 이미 PlayerDetailsViewController를 가지고 있습니다. 위임 프로토콜이 정의되어 있으며 이를 어딘가에 구현해야 합니다. 분명히 이 장소는 PlayersViewController여야 합니다. AddPlayer 창 렌더링을 담당하기 때문입니다. PlayerViewController.h에 다음 코드를 추가합니다.

#import "PlayerDetailsViewController.h"  
@interface PlayersViewController : UITableViewController <PlayerDetailsViewControllerDelegate>

PlayersViewController.m 메서드 끝에 다음 코드를 추가합니다.

#pragma mark - PlayerDetailsViewControllerDelegate  
- ( void ) playerDetailsViewControllerDidCancel :    ( PlayerDetailsViewController *) controller {
        [ self dismissViewControllerAnimated : YES completion : nil ] ;
}  
- ( void ) playerDetailsViewControllerDidSave :    ( PlayerDetailsViewController *) controller {
        [ self dismissViewControllerAnimated : YES completion : nil ] ;
}

   

这里只是简单地关闭 AddPlayer 窗口。稍后我们会做一些有趣的事情。

iOS5 中出现了新的dismissViewControllerAnimated:completion: 方法。你也可以用之前的老  dismissModalViewControllerAnimated: 方法。但新方法将更加优雅地关闭ViewController(它能给你一个机会在窗口被关闭后能执行额外的代码)。

剩下只有一件事情: Players 窗口需要告诉 PlayerDetailsViewController它将成为它的委托。你可能想,用故事版编辑器在二者间拖一条线不就完了吗?很不幸,这不行。在 segue 中,为了传递数据到下一个 ViewController ,我们仍然必须编写代码。

在PlayersViewController 中添加如下方法:

- ( void ) prepareForSegue :( UIStoryboardSegue *) segue sender :( id ) sender {
        if ([ segue.identifier isEqualToString : @ "AddPlayer" ]) {
               UINavigationController * navigationController =             segue.destinationViewController;
               PlayerDetailsViewController * playerDetailsViewController = [[ navigationController viewControllers ] objectAtIndex : 0 ] ;
               playerDetailsViewController.delegate = self;
        }
}

   

prepareForSegue 方法在即将发生 segue 之时触发。新的 ViewController 已经同故事版一起加载了,但它是不可见的,我们必须利用这个方法传递参数给它。(永远不要自己调用prepareForSegue 方法,它由 UIKit 调用以通知你正在触发一个 segue。)

注意 segue 的目标将是 NavigationController,它与我们的BarButtonItem 是关联的。为了得到 PlayerDetailsViewController实例,我们必须从 NavigationController 的 viewControllers 属性中将它找出来。

运行程序,按下 + 号按钮,尝试关闭 AddPlayer 窗口。居然没有效果!

那是因为我们并没有指定 segue 的 identifier 。而在prepareForSegue  方法中我们检查了 identifier 是否为 AddPlayer。在同一个 ViewController 中存在多个 segue 的情况下,建议你通过 identifier 来区分不同的 segue。

在故事版编辑器中,选择该 segue,注意 BarButtonItem 会被加亮显示以便你能清楚地知道是哪个控件触发这个segue。

在属性面板中,将 identifier 设为 AddPlayer。

iOS 5 스토리보드 시작하기 (3)

再次运行程序,触摸 Cancel 或 Done 按钮,现在都能关闭窗口并返回玩家列表了。

 

注意:也可以从模式窗口中调用 dismissViewControllerAnimated:completion:方法。不一定非要让代理对象来关闭。但如果你这样做,要留意一件事情:你原来使用的[self.parentViewController dismissModalViewControllerAnimated:YES] 不再有效。可以用 self.presentingViewController 替换 self.parentViewController,但这是在 iOS5 之后出现的新属性。

另外,在 segue 的属性面板中,有一个 Transition 字段,在此你可以选择不同的过渡动画。

你净可以尝试你最喜欢的设置。但不要改变 Style 属性。对于这个窗口,它只能是Modal——任何其他选项都会导致程序崩溃!

在本教程中,我们多次使用委托模式。在此我们列出了在两个场景中建立连接的步骤:

从源场景的按钮或其他控件创建 segue 到另一个场景。(如果你想呈现一个模式窗口,通常目标对象应该是一个 NavigationController)。

指定 segue 的 identifier。(对于同一源场景,identifier必须是唯一的;不同的源场景则可以有重复)。

为目标场景创建委托协议。

从 Cancel 按钮和 Done 按钮中调用委托方法,对于目标场景想回到源场景的任何地方,你都要这样做。

在源场景中实现委托协议。当 Cancel 按钮或 Done 按钮被触摸时,委托对象应当负责关闭目标 ViewController。

 在源 ViewController 中实现 prepareForSegue 方法,并让目标场景的 delegate=self;

委托模式是必然的,因为没有“反向 segue”这样的东西。当 segue 被触发,它创建的都是新的目标ViewController 实例。你当然可以创建一个 segue 用于从目标返回到源场景,但这太想当然了。

打比方,你可以从 Cancel 按钮创建一个 segue 返回Players 窗口,但却无法关闭 Add Player 窗口回到 Players。除非你创建一个新的 Players 对象。这样你就创建了一个无尽循环直到耗净所有内存。

记住:Segue 只有一个方向,只能用于打开新窗口。要关闭它返回(或者将他从NavigationController 栈中弹出),通常使用委托模式。segue 只适用于源场景,目标 ViewController 根本不知道 segue是什么玩意。

 

静态Cell

最终的 Add Player 窗口如下图所示:

iOS 5 스토리보드 시작하기 (3)

这是一个分组表视图,但这次我们不需要为它创建一个数据源。我们可以直接在故事版编辑器中设计它,不需要写cellForRowAtIndexPath 方法。这种新特性叫做静态cell。

在 Add Players 场景中选择 tableView,在属性面板修改Content 为 Static Cells。Style 则选择 Grouped,Sections 设置为 2。

iOS 5 스토리보드 시작하기 (3)

Sections 属性一旦改变,编辑器将克隆已有的 section。(你也可以从左边的文档树中选择某个 section 然后复制它)。

对于每个 section,我们只有一行。选择多余的行并删除。选择最上面的section ,通过属性面板,在 Header 字段中输入 Player Name。

拖一个新的 TextField 到这个 section 的仅有的 cell中。移除它的边框,这样你就看不到 textfield 的头和尾。设置字体为 System 17 ,反选Adjust to Fit。

我们将使用 Assistan Editor 创建 textField 的IBOutlet。打开 Assistant Editor,它将自动打开 PlayerDetailsViewController.h。选中 TextField 然后按住 ctrl 拖到 .h 文件中:

iOS 5 스토리보드 시작하기 (3)

放开鼠标键,将弹出窗口:


iOS 5 스토리보드 시작하기 (3)

Name 设置为 nameTextField。点击 Connect,Xcode 将在PlayerDetailsViewController.h 中添加如下属性:

@property ( strong, nonatomic ) IBOutlet UITextField * nameTextField;

   

同时它也自动合成了属性,并在 viewDidUnload 方法中加入语句。

我说过这种方法不能在模板cell 上使用,但在静态 cell 中是可以的。每个静态cell 只有一个实例(与模板 cell 不同,它们不会被复制),因此将它们的 subview 与 ViewController的出口连接是完全可行的。

设置第二个section 的静态 cell 的 Style 为 RightDetail。这是一种标准的 cell 样式。将左边的 Label 文本设置为 Game,accessory 设置为 disclosure indicator。为右边的Label 创建一个出口,命名为 detailLabel。这两个 Label 都是通常的 UILabel 对象。

设计后的 Add Player  窗口最终如下图所示:

iOS 5 스토리보드 시작하기 (3)

使用静态 cell 时,TableViewController 不用数据源。因为PlayerDetailsViewController  类是 Xcode 模板创建的,代码中会存在数据源的模板代码,我们需要删除它。删除在:

#pragma mark - Table view data source

   

和:

#pragma mark - Table view delegate

   

之间的所有行。这将消除 Xcode 在添加这个类时的一些警告。运行程序,查看静态cell 的效果。我们没有写一行代码——实际上反倒删除了一大堆的代码。

但我们免不了还是要写一些代码。在你想第一个单元格加入 textField 时,你可能会注意到它稍有些不妥,在它的周围会有一些多余的空间。用户看不见textField 的头和尾,因此当他们触摸到这些空处的时候,键盘不会弹出。这个很容易解决,覆盖tableView:didSelectRowAtIndexPath 方法代码如下所示:

- ( void ) tableView :( UITableView *) tableView    didSelectRowAtIndexPath :( NSIndexPath *) indexPath {
        if ( indexPath.section == 0 )
               [ self.nameTextField becomeFirstResponder ] ;
}

   

即用户触摸到第一个单元格时,我们激活 textField 焦点(在这个section 中只有一个 cell,因此我们只需要检查 section 的索引即可)。这将自动弹出软键盘。这只是微不足道的工作,但能降低用户的不满。

你还应该在属性面板中将 cell 的 selection style 设置为None,否则用户触摸在文本框附近时,整个行将变成蓝色。

好了,这就是 AddPlayer 窗口的设计了。现在我们要让它真正发挥作用。

以上就是iOS 5 故事板入门(3)的内容,更多相关内容请关注PHP中文网(www.php.cn)!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.