如何在Objective中添加具有自己的UIViewController的子视图
我正在努力与自己的UIViewControllers
子视图。 我有一个UIViewController
与toolbar
上的视图(浅粉色)和两个按钮。 我想要在按下第一个按钮时显示蓝色视图,并按下第二个按钮时显示的黄色视图。 如果我只想显示一个视图,应该很容易。 但蓝色视图将包含一个表,所以它需要它自己的控制器。 那是我的第一课。 我从这个问题开始,在那里我学会了我需要一个控制器。
所以,我要回去在这里采取一些小步骤。 下面是我的Utility ViewController
(主视图控制器)和其他两个控制器(蓝色和黄色)的简单起点的图片。 想象一下,当首次显示Utility ViewController
(主视图)时,蓝色(默认)视图将显示在粉红色视图所在的位置。 用户将能够点击两个按钮前后来回,粉红色的视图将永远不会显示。 我只想让蓝色视图去粉色视图所在的位置,黄色视图去粉色视图所在的位置。 我希望这是有道理的。
我试图使用addChildViewController
。 从我所看到的,有两种方法可以做到这一点:在storyboard
的容器视图或编程的addChildViewController
。 我想以编程方式进行。 我不想使用NavigationController
或Tab栏。 我只想添加控制器,并在按下相关按钮时将正确的视图推入粉色视图。
以下是我到目前为止的代码。 我想要做的就是显示粉红色视图所在的蓝色视图。 从我所看到的,我应该能够公正addChildViewController
和addSubView。 这段代码不适合我。 我的困惑越来越好。 有人能帮助我在粉红色视图显示的地方显示蓝色视图吗?
除了在viewDidLoad中显示蓝色视图之外,此代码不用于执行任何操作。
IDUtilityViewController.h
#import <UIKit/UIKit.h>
@interface IDUtilityViewController : UIViewController
@property (strong, nonatomic) IBOutlet UIView *utilityView;
@end
IDUtilityViewController.m
#import "IDUtilityViewController.h"
#import "IDAboutViewController.h"
@interface IDUtilityViewController ()
@property (nonatomic, strong) IDAboutViewController *aboutVC;
@end
@implementation IDUtilityViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.aboutVC = [[IDAboutViewController alloc]initWithNibName:@"AboutVC" bundle:nil];
[self addChildViewController:self.aboutVC];
[self.aboutVC didMoveToParentViewController:self];
[self.utilityView addSubview:self.aboutVC.aboutView];
}
@end
- - - - - - - - - - - - - 编辑 - - - - - - - - - - - - -------
self.aboutVC.aboutView是零。 但是我把它连接在storyboard
。 我还需要实例化吗?
这篇文章通常有最新的语法,比如Swift 4。
在今天的iOS中, “一切都是容器视图” 。 这是您今天制作应用的基本方式。
一个应用可能非常简单,只有一个视图。 但即使在这种情况下,屏幕上的每个“东西”都是一个容器视图。
这很简单...
(A)将容器视图拖入场景中...
将容器视图拖到场景视图中。 (就像你会拖入一个UIButton一样。)
容器视图是这张图片中的棕色东西。 它实际上是在你的场景视图中。
将容器视图拖到场景视图中时,Xcode会自动给你两件事 :
您可以在场景视图中获取容器视图,
你会得到一个全新的UIViewController
,它只是坐在你的故事板上白色的某个地方 。
这两个与“共济会的符号”的东西连接 -下面解释!
(B)点击那个新的视图控制器(Xcode为你在白色区域的某个地方制作的新东西,而不是你场景中的东西)......并且改变这个类!
这真的很简单。
你完成了。
这是视觉上解释的同样的事情。
(A)
注意容器视图 。
(B)
注意到控制器 。
点击B.(这是B - 不是A!)
去右上角的检查员。 注意它说“UIViewController”
[ ] [3]
将其更改为您自己的自定义类,这是一个UIViewController。
所以,我有一个Swift类Snap
,它是一个UIViewController
。
所以在Inspector中,我在“Snap”中输入“UIViewController”。
(和往常一样,当您开始输入“Snap ...”时,Xcode会自动完成“Snap”)。)
这就是它的全部 - 你完成了。
如何改变容器视图 - 比如说一个表格视图。
所以当你点击添加容器视图时,Apple会自动为你提供一个链接的视图控制器,坐在故事板上。
恰巧(2017):默认情况下它使它成为UIViewController
。
这很愚蠢:它应该问你需要哪种类型。 例如,你经常需要一个表格视图。 以下是如何将其改为不同的方式:
在写这篇文章时,Xcode默认给你一个UIViewController
。 假设你想要一个UICollectionViewController
来代替:
(i)将容器视图拖入场景中。 看看Xcode默认给你的故事板上的UIViewController。
(ii)将新的UICollectionViewController
到故事UICollectionViewController
白色区域的任何位置。
(iii)点击场景中的容器视图。 点击连接检查器。 注意有一个“触发神论”。 将鼠标悬停在“触发的Segue”上,并注意到Xcode 突出显示了所有不需要的UIViewController。
(iv)点击“x”实际删除触发的塞恩。
(v) 从触发的塞格拖动 (viewDidLoad是唯一的选择)。 将故事板拖到新的UICollectionViewController。 出现并弹出一个窗口。 您必须选择嵌入 。
(vi)简单地删除所有不需要的UIViewController。 你完成了。
短版本:删除不需要的UIViewController。 在故事板上放置一个新的UICollectionViewController
。 控制 - 从容器视图的连接 - 触发Segue - viewDidLoad拖动到您的新控制器。 一定要在弹出窗口中选择“嵌入”。
输入文本标识符...
你将有一个“方形方形”共鸣符号的东西:它在连接你的容器视图和视图控制器的“弯曲线”上。
“共济会的象征”是赛格。
通过点击 “共济会的符号”的东西选择SEGUE。
看你的权利。
你必须输入一个segue的文本标识符 。
你决定这个名字。 它可以是任何文本字符串。 明智的选择通常是“segueClassName”。
如果你遵循这个模式,你所有的segues将被称为segueClockView,seguePersonSelector,segueSnap,segueCards等等。
接下来,你在哪里使用该文本标识符?
如何连接'到'子控制器...
然后,在代码中,在整个场景的ViewController中执行以下操作。
假设您在场景中有三个容器视图。 每个容器视图都包含一个不同的控制器,例如“Snap”,“Clock”和“Other”。
最新的Swift3语法(2017)
var snap:Snap?
var clock:Clock?
var other:Other?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "segueSnap")
{ snap = (segue.destination as! Snap) }
if (segue.identifier == "segueClock")
{ clock = (segue.destination as! Clock) }
if (segue.identifier == "segueOther")
{ other = (segue.destination as! Other) }
}
就这么简单。 您使用prepareForSegue
调用来连接变量以引用控制器。
如何在'其他方向'连接到父母......
假设你已经在容器视图中放置了控制器(示例中为“Snap”)。
上面的“boss”视图控制器可能会让你感到困惑(例子中的“Dash”)。 幸运的是,这很简单:
// Dash is the overall scene.
// Here we are in Snap. Snap is one of the container views inside Dash.
class Snap {
var myBoss:Dash?
override func viewDidAppear(_ animated: Bool) { // MUST be viewDidAppear
super.viewDidAppear(animated)
myBoss = self.parent as? Dash
}
严重:只能从viewDidAppear
或更高版本运行。 在viewDidLoad
不起作用。
你完成了。
重要提示:只适用于容器视图。
重要的高级技巧:不要忘记,只适用于容器视图。
现在有了故事板标识符,在屏幕上弹出新视图(而不是在Android开发中)是司空见惯的事情。 所以,假设用户想编辑一些东西......
// let's just pop a view on the screen.
// this has nothing to do with container views
//
let e = ...instantiateViewController(withIdentifier: "Edit") as! Edit
e.modalPresentationStyle = .overCurrentContext
self.present(e, animated: false, completion: nil)
在使用容器视图时, 保证 Dash将是Snap的父视图控制器。
但是,当使用instantiateViewController时,这不是必需的 。
非常容易混淆的是,在iOS中,父视图控制器与实例化它的类无关 。 (它可能是相同的,但通常不一样。) self.parent
模式仅适用于容器视图。
(对于instantiateViewController模式中的类似结果,您必须使用一个协议和一个委托,记住委托将是一个薄弱环节。)
prepareForSegue命名不佳...
值得注意的是,“准备赛报”是一个非常糟糕的名字!
“prepareForSegue”用于两个目的:加载容器视图,以及在场景之间延续。
但在实践中,你很少在场景之间流连忘返! 几乎所有的应用程序都有许多容器视图。
如果“prepareForSegue”被称为“loadingContainerView”,那将会更有意义。
超过一个...
常见的情况是:屏幕上有一个小区域,您想在其中显示多个不同视图控制器中的一个。 例如,四个小部件之一。
最简单的方法:只有四个不同的容器视图都坐在同一个区域 。 在你的代码中,只需隐藏所有四个并打开你想看到的那个。
在故事板上,有一个空的“持有人”UIView,它只保存四个容器视图。 然后,您可以通过调整或移动“支架”来一次调整或移动所有四个尺寸。 在你的代码中,只需要有四个UIView
插座,每个容器视图都有一个插座。 复制并粘贴上面的代码,“如何连接到子控制器”,以连接四个包含的视图控制器。
注意 - Storyboard参考文件到达!
正如SimplGy在下面指出的那样:“iOS 9的Storyboard引用使得容器视图更加可怕,您可以在任何地方定义可重用视图(控制器),并在多个模块化故事板中的任何容器视图中引用它。
还要注意 - 相当容易混淆 - 通常今天你只是不打扰容器视图!
在许多情况下,您只需instantiateViewController#withIdentifier
。
但请注意上面解释的关于.parent
的“gotchya”。 容器视图的全部内容是您可以即时且简单地确定父链。
如果你使用instantiateViewController#withIdentifier
使用storyboard引用,你必须instantiateViewController#withIdentifier
协议和委托(记住委托将是一个薄弱的环节)。 但是,你可以随时随地灵活使用它。
相比之下,使用“固定”,可以说,容器视图非常简单,您可以立即在父母和孩子之间进行连接,如上所述。
我看到两个问题。 首先,因为你正在做的故事板的控制器,你应该和他们实例instantiateViewControllerWithIdentifier:
不initWithNibName:bundle:
。 其次,将视图添加为子视图时,应该给它一个框架。 所以,
- (void)viewDidLoad
{
[super viewDidLoad];
self.aboutVC = [self.storyboard instantiateViewControllerWithIdentifier:@"aboutVC"]; // make sure you give the controller this same identifier in the storyboard
[self addChildViewController:self.aboutVC];
[self.aboutVC didMoveToParentViewController:self];
self.aboutVC.view.frame = self.utilityView.bounds;
[self.utilityView addSubview:self.aboutVC.aboutView];
}
链接地址: http://www.djcxy.com/p/2519.html
上一篇: How to add a subview that has its own UIViewController in Objective