簡體   English   中英

從父 iOS 訪問容器視圖控制器

[英]Access Container View Controller from Parent iOS

在 iOS6 中,我注意到了新的容器視圖,但不太確定如何從包含視圖訪問它的控制器。

設想:

例子

我想從包含容器視圖的視圖控制器訪問 Alert 視圖控制器中的標簽。

它們之間有一個 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: )。

用於 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方法有效,但它依賴於 segue 標識符魔術字符串。 也許有更好的方法。

如果你知道你想要的 VC 的類,你可以使用計算屬性非常巧妙地做到這一點:

var camperVan: CamperVanViewController? {
  return childViewControllers.flatMap({ $0 as? CamperVanViewController }).first
  // This works because `flatMap` removes nils
}

這依賴於childViewControllers 雖然我同意依賴第一個可能很脆弱,但命名您要查找的類會使它看起來非常可靠。

Swift 3 的更新答案,使用計算屬性:

var 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
  }
}

我使用這樣的代碼:

- (IBAction)showCartItems:(id)sender{ 
  ListOfCartItemsViewController *listOfItemsVC=[self.storyboard instantiateViewControllerWithIdentifier:@"ListOfCartItemsViewController"];
  [self addChildViewController:listOfItemsVC];
 }

如果有人正在尋找Swift 3.0

然后可以訪問viewController1viewController2等等。

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")
}

使用 generic 你可以做一些甜蜜的事情。 這是數組的擴展:

extension Array {
    func firstMatchingType<Type>() -> Type? {
        return first(where: { $0 is Type }) as? Type
    }
}

然后,您可以在 viewController 中執行此操作:

var viewControllerInContainer: YourViewControllerClass? {
    return childViewControllers.firstMatchingType()!
}

你可以這樣寫

- (IBAction)showDetail:(UIButton *)sender {  
            DetailViewController *detailVc = [self.childViewControllers firstObject];  
        detailVc.lable.text = sender.titleLabel.text;  
    }  
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM