从父 iOS 访问容器视图控制器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13279105/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Access Container View Controller from Parent iOS
提问by Adam Waite
in iOS6 I noticed the new Container View but am not quite sure how to access it's controller from the containing view.
在 iOS6 中,我注意到了新的容器视图,但不太确定如何从包含视图访问它的控制器。
Scenario:
设想:
I want to access the labels in Alert view controller from the view controller that houses the container view.
我想从包含容器视图的视图控制器访问警报视图控制器中的标签。
There's a segue between them, can I use that?
他们之间有一个segue,我可以使用它吗?
回答by Peter E
Yes, you can use the segue to get access the child view controller (and its view and subviews). Give the segue an identifier (such as alertview_embed
), using the Attributes inspector in Storyboard. Then have the parent view controller (the one housing the container view) implement a method like this:
是的,您可以使用 segue 访问子视图控制器(及其视图和子视图)。alertview_embed
使用 Storyboard 中的属性检查器为 segue 提供一个标识符(例如)。然后让父视图控制器(容纳容器视图的那个)实现一个这样的方法:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSString * segueName = segue.identifier;
if ([segueName isEqualToString: @"alertview_embed"]) {
AlertViewController * childViewController = (AlertViewController *) [segue destinationViewController];
AlertView * alertView = childViewController.view;
// do something with the AlertView's subviews here...
}
}
回答by rdelmar
You can do that simply with self.childViewControllers.lastObject
(assuming you only have one child, otherwise use objectAtIndex:
).
您可以简单地使用self.childViewControllers.lastObject
(假设您只有一个孩子,否则使用objectAtIndex:
)。
回答by Sruit A.Suk
for Swift Programming
用于 Swift 编程
you can write like this
你可以这样写
var containerViewController: ExampleViewController?
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// you can set this name in 'segue.embed' in storyboard
if segue.identifier == "checkinPopupIdentifierInStoryBoard" {
let connectContainerViewController = segue.destinationViewController as ExampleViewController
containerViewController = connectContainerViewController
}
}
回答by SimplGy
The prepareForSegue
approach works, but it relies on the segue identifier magic string. Maybe there's a better way.
该prepareForSegue
方法有效,但它依赖于 segue 标识符魔术字符串。也许有更好的方法。
If you know the class of the VC you're after, you can do this very neatly with a computed property:
如果你知道你所追求的 VC 的类,你可以使用计算属性非常巧妙地做到这一点:
var camperVan: CamperVanViewController? {
return childViewControllers.flatMap({ var jobSummaryViewController: JobSummaryViewController {
get {
let ctrl = childViewControllers.first(where: { override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
switch segue.destination
{
case let aViewController as AViewController:
self.aViewController = aViewController
case let bViewController as BViewController:
self.bViewController = bViewController
default:
return
}
}
is JobSummaryViewController })
return ctrl as! JobSummaryViewController
}
}
as? CamperVanViewController }).first
// This works because `flatMap` removes nils
}
This relies on childViewControllers
. While I agree it could be fragile to rely on the first one, naming the class you seek makes this seem quite solid.
这依赖于childViewControllers
. 虽然我同意依赖第一个可能很脆弱,但命名您要寻找的类会使这看起来非常可靠。
回答by Robin Daugherty
An updated answer for Swift 3, using a computed property:
Swift 3 的更新答案,使用计算属性:
extension Array {
func firstMatchingType<Type>() -> Type? {
return first(where: { var viewControllerInContainer: YourViewControllerClass? {
return childViewControllers.firstMatchingType()!
}
is Type }) as? Type
}
}
This only iterates the list of children until it reaches the first match.
这只会迭代子项列表,直到到达第一个匹配项。
回答by Gautam Jain
self.childViewControllers
is more relevant when you need control from the parent. For instance, if the child controller is a table view and you want to reload it forcefully or change a property via a button tap or any other event on Parent View Controller, you can do it by accessing ChildViewController's instance and not via prepareForSegue. Both have their applications in different ways.
self.childViewControllers
当您需要来自父级的控制时更相关。例如,如果子控制器是一个表视图,并且您想强制重新加载它或通过点击按钮或父视图控制器上的任何其他事件来更改属性,则可以通过访问 ChildViewController 的实例而不是通过 prepareForSegue 来完成。两者都有不同的应用方式。
回答by Joanna Carter
There is another way using Swift's switch statement on the type of the view controller :
在视图控制器的类型上使用 Swift 的 switch 语句还有另一种方法:
let viewController1 : OneViewController!
let viewController2 : TwoViewController!
// Safety handling of optional String
if let identifier: String = segue.identifier {
switch identifier {
case "segueName1":
viewController1 = segue.destination as! OneViewController
break
case "segueName2":
viewController2 = segue.destination as! TwoViewController
break
// ... More cases can be inserted here ...
default:
// A new segue is added in the storyboard but not yet including in this switch
print("A case missing for segue identifier: \(identifier)")
break
}
} else {
// Either the segue or the identifier is inaccessible
print("WARNING: identifier in segue is not accessible")
}
回答by Sunkas
With generic you can do some sweet things. Here is an extension to Array:
使用泛型你可以做一些甜蜜的事情。这是对 Array 的扩展:
- (IBAction)showCartItems:(id)sender{
ListOfCartItemsViewController *listOfItemsVC=[self.storyboard instantiateViewControllerWithIdentifier:@"ListOfCartItemsViewController"];
[self addChildViewController:listOfItemsVC];
}
You can then do this in your viewController:
然后你可以在你的 viewController 中做到这一点:
##代码##回答by Marco Leong
In case someone is looking for Swift 3.0,
如果有人正在寻找Swift 3.0,
viewController1, viewController2and so on will then be accessible.
viewController1,viewController2等将可以访问。
##代码##回答by Mannam Brahmam
I use Code like:
我使用代码如下:
##代码##