16835


swiftプログラムを作成しております。  
[![画像の説明をここに入力](https://i.stack.imgur.com/p809H.png)](https://i.stack.imgur.com/p809H.png)

このような画面になりますが、「Button」を押すと、「Label」が"変更しました"に変更したいと思っています。しかし、「Button」を押しても変化しません。

PageMenuライブラリ([https://github.com/uacaps/PageMenu)を使っています](https://github.com/uacaps/PageMenu\)%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99)。CAPSPageMenu.swiftをインポートしています。

ViewController.swift

[code]

    import UIKit
    
    class ViewController: UIViewController {
    
        @IBOutlet weak var ParentLabel: UILabel!
        var pageMenu : CAPSPageMenu?
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
        }
    
        override func viewDidAppear(animated: Bool) {
            super.viewDidAppear(animated)
    
            var controllerArray : [UIViewController] = []
    
            let controller1 : SecondView = SecondView(nibName: "SecondView", bundle: nil)
            controller1.title = "2nd View"
            controllerArray.append(controller1)
            let parameters: [CAPSPageMenuOption] = [
                .ScrollMenuBackgroundColor(UIColor(red: 30.0/255.0, green: 30.0/255.0, blue: 30.0/255.0, alpha: 1.0)),
                .ViewBackgroundColor(UIColor(red: 20.0/255.0, green: 20.0/255.0, blue: 20.0/255.0, alpha: 1.0)),
                .SelectionIndicatorColor(UIColor.orangeColor()),
                .BottomMenuHairlineColor(UIColor(red: 70.0/255.0, green: 70.0/255.0, blue: 80.0/255.0, alpha: 1.0)),
                .MenuItemFont(UIFont(name: "HelveticaNeue", size: 13.0)!),
                .MenuHeight(40.0),
                .MenuItemWidth(90.0),
                .CenterMenuItems(true)
            ]
            pageMenu = CAPSPageMenu(viewControllers: controllerArray, frame: CGRectMake(0.0, 50, self.view.frame.width, 100), pageMenuOptions: parameters)
            self.addChildViewController(pageMenu!)
            self.view.addSubview(pageMenu!.view)
            pageMenu!.didMoveToParentViewController(self)
    
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    }
    
[/code]

SecondView.swift

[code]

    import UIKit
    
    class SecondView: UIViewController {
    
        override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
            super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        }
    
        required init(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)!
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    
        @IBAction func changeLabel(sender: AnyObject) {
            if let vc :ViewController = self.parentViewController as? ViewController {
                vc.ParentLabel.text = "変更しました"
            }
        }
    
[/code]

上記のコードの通りです。  
どうやら

[code]

    if let vc :ViewController = self.parentViewController as? ViewController {
    
[/code]

で型キャストに失敗しているようです。

[code]

    if let vc :ViewController = self.presentedViewController as? ViewController {
    
[/code]

に変えてもダメでした。

追加元のLabelを変更するにはどうしたらいいのでしょう？ご存知の方、ご教示お願いします。


CC BY-SA 3.0
2015-09-21T14:28:42.427
16824
2015-09-22T04:33:21.633
2015-09-21T23:15:02.560
5337
8593
question
swift uikit
addChildViewControllerで追加した画面のボタンで、追加元のLabelを変更する方法


PageMenuのソースコードリーディングをしましょう。

[code]

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
    
        // Initialize view controllers to display and place in array
        var controllerArray : [UIViewController] = [vc1, vc2, vc3]
    
        // Initialize scroll menu
        pageMenu = CAPSPageMenu(viewControllers: controllerArray, frame: CGRectMake(0.0, 50.0, self.view.frame.width, self.view.frame.height - 50), pageMenuOptions: parameters)
    
        self.addChildViewController(pageMenu!)
        self.view.addSubview(pageMenu!.view)
    
        pageMenu!.didMoveToParentViewController(self)
    }
    
[/code]

`ViewController.swift`では複数のビューコントローラから`CAPSPageMenu`を生成しています。ここで重要なのは、`ViewController`の直接の子となっているのは、
**`CAPSPageMenu`であって、個々の子`ViewController`ではない** ということです。

これがなぜかというと、省メモリ化のためです。実際に`view`を生成する必要があるのは、現在表示しているページとその前後分、せいぜい3ページ分の`ViewController`だけです。最初から10や100ページ分の`ViewController`の`view`をインスタンス化してしまうと非常に重くなるので、`view`の生成および破棄を適時行う必要があります。その面倒を見てくれるのが、PageMenuライブラリなのです。

つまり、

  * RootViewController 
    * CAPSPageMenu 
      * ChildViewController

の階層構造となっており、このためルートの`ViewController`に対して何らかの処理をするのであれば、以下のコードのように「親の親」を取得する必要があります。

[code]

    @IBAction func click(sender: UIButton) {
        if let vc = self.parentViewController?.parentViewController as? ViewController {
            vc.label.text = "changed"
        }
    }
    
[/code]

これはあまり良い方法とは言えないので、`CAPSPageMenuDelegate`を利用して、現在表示しているページに`delegate`を持たせたり、ちょっと大げさになりますが`UINotificationCenter`を利用するといった方法が好ましいかもしれません。


CC BY-SA 3.0
2015-09-21T23:32:27.740
16835
2015-09-22T04:33:21.633
2015-09-22T04:33:21.633
5337
5337
16824
answer