在iOS6中,我注意到了新的容器视图,但不太确定如何从包含视图访问它的控制器。
场景: 我希望能够从承载容器视图的视图控制器中访问警报视图控制器中的标签。 它们之间有一个segue,我能用它吗?
场景: 我希望能够从承载容器视图的视图控制器中访问警报视图控制器中的标签。 它们之间有一个segue,我能用它吗?
是的,您可以使用segue来访问子视图控制器(以及其视图和子视图)。 在Storyboard中使用属性检查器为segue命名一个标识符(例如alertview_embed
)。 然后,让包含容器视图的父视图控制器实现像这样的方法:
- (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...
}
}
如果您只有一个子视图控制器,您可以简单地使用 self.childViewControllers.lastObject
(否则请使用 objectAtIndex:
)。
childViewControllers
,所以现在它会崩溃。 - Mazyod用于Swift编程
你可以像这样编写代码
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
}
}
prepareForSegue
方法可行,但它依赖于转场标识符的神奇字符串。也许有更好的办法。
如果您知道要使用的VC类,可以使用计算属性很好地实现此目的:
var camperVan: CamperVanViewController? {
return childViewControllers.flatMap({ $0 as? CamperVanViewController }).first
// This works because `flatMap` removes nils
}
这依赖于 childViewControllers
。虽然我同意依赖第一个子控制器可能会很容易出错,但是命名你要找的类会让这个看起来更加可靠。
return childViewControllers.filter { $0 is CamperVanViewController }.first
- Adam WaitechildViewControllers.flatMap({ $0 as? CamperVanViewController }).first
,我认为这样更好一些,因为它进行了强制转换并且去除了任何 nil 值。 - SimplGyfirst(where:)
函数。示例:childViewControllers.first(where: { $0 is CamperVanViewController })
- Alexandervar jobSummaryViewController: JobSummaryViewController {
get {
let ctrl = childViewControllers.first(where: { $0 is JobSummaryViewController })
return ctrl as! JobSummaryViewController
}
}
self.childViewControllers
在需要从父视图控制器中进行控制时更为相关。例如,如果子控制器是一个表视图,并且您想通过访问ChildViewController的实例来强制重新加载它或通过按钮点击或任何其他事件在父视图控制器上更改属性,您可以这样做,而不是通过prepareForSegue。两者在不同方面都有其应用。
还有另一种使用Swift中switch语句的方法来判断视图控制器的类型:
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
}
}
使用泛型,你可以做一些很棒的事情。这里是一个针对数组的扩展:
extension Array {
func firstMatchingType<Type>() -> Type? {
return first(where: { $0 is Type }) as? Type
}
}
var viewControllerInContainer: YourViewControllerClass? {
return childViewControllers.firstMatchingType()!
}
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")
}
- (IBAction)showCartItems:(id)sender{
ListOfCartItemsViewController *listOfItemsVC=[self.storyboard instantiateViewControllerWithIdentifier:@"ListOfCartItemsViewController"];
[self addChildViewController:listOfItemsVC];
}