2017-04-13 3 views
0

Ich habe zwei ViewControllers - Slider & Foo. Ich füge Slider als Foosubview und es ist Rahmen in Foo VC Einstellung, aber Slider ‚s Rahmen nicht ändert -> Ich kann sehen, dass nur x & y angewendet werden. Wie sollte ich meinen Code ändern, um Slider mit Slider(initWithFrame: CGFrame) initialisieren zu können? Oder was ist eine bevorzugte Möglichkeit, um die Größe Slider von der Foo VC zu setzen?Swift: Programmgesteuert VC-Frame von einem anderen VC

// slider.swift

import UIKit 

class Slider: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { 
    var collectionView: UICollectionView? 


    override func viewDidLoad() { 
     super.viewDidLoad() 

     let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout() 
     layout.minimumLineSpacing = 0 
     layout.sectionInset = UIEdgeInsets.zero 
     layout.itemSize = self.view.frame.size 
     layout.scrollDirection = UICollectionViewScrollDirection.horizontal 

     collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout) 
     collectionView?.dataSource = self 
     collectionView?.delegate = self 
     collectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell") 
     collectionView?.backgroundColor = UIColor.white 
     collectionView?.isPagingEnabled = true 

     self.view.addSubview(collectionView!) 
    } 

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
     return 14 
    } 

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) 
     cell.backgroundColor = UIColor.red 
     return cell 
    } 
} 

// foo.swift

import UIKit 

class Foo: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     slider = Slider(); 
     slider!.view.frame = CGRect(x: 50, y: 50, width: 20, height: 20) 
     self.view.addSubview(slider!.view) 
     self.addChildViewController(slider!) 
    } 

} 
+0

Eine Sache, die mich herausspringt ist die * Größe * Ihrer * Slider * - hoffentlich ist es viel größer in der Realität. 20x20 ist wahrscheinlich viel zu klein für eine UICollectionView (und aus dem Namen ein UISlider). Das heißt, Sie können ein * init (frame:) * für 'Slider' kodieren - eines, das Swift ** immer benutzt hat, nicht * init (withFrame:) * - aber Sie wollen sich wahrscheinlich mit' Slider' beschäftigen Subview-Layout in seiner * viewDidLoadSubviews * überschreiben. – dfd

Antwort

0

Es sieht aus wie Sie ein paar Probleme mit der Umsetzung haben. Obwohl es so aussieht, als ob sich der Rahmen nicht ändert, ist er tatsächlich, aber Ihre Ansicht schneidet nicht in Grenzen ab, so dass der Rahmen scheinbar gleich bleibt.

Ein paar Dinge zu beachten.

Erstens, wenn Sie einrichten und Layout in Code, müssen Sie Ihre Frames/Platzierung in der Funktion 'viewDidLayoutSubviews' aktualisieren. (sieht aus wie dfd das auch in einem Kommentar erwähnt)

Stellen Sie außerdem sicher, dass Sie View Controller Containment korrekt implementieren. Immer wenn Sie versuchen, die Ansicht eines Ansichtscontrollers der Ansicht eines anderen Ansichtscontrollers hinzuzufügen, sollten Sie die Ansichtscontrolling-Einschränkung verwenden. Hier ist ein Link auf die Dokumentation für das: View Controller Containment Docs Here

Laut Apple das Minimum Sie für Rückhaltung implementieren sollte, ist die folgende: (Sie haben es meistens richtig, aber Ihre Anrufe sind in der falschen Reihenfolge)

func displayContentController(content: UIViewController) { 
    addChildViewController(content) 
    content.view.frame = frameForContentController() 
    view.addSubview(content.view) 
    content.didMoveToParentViewController(self) 
} 

I habe im Beispiel unten ein UIViewController-Extension-Beispiel eingefügt.

Versuchen Sie den folgenden Code, es in einem Testprojekt für mich funktioniert:

import UIKit 


class Slider: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { 

var collectionView: UICollectionView? 
var layout : UICollectionViewFlowLayout? 

override func viewDidLoad() { 
    super.viewDidLoad() 

    layout = UICollectionViewFlowLayout() 
    layout?.minimumLineSpacing = 0 
    layout?.sectionInset = UIEdgeInsets.zero 
    layout?.itemSize = view.bounds.size 
    layout?.scrollDirection = UICollectionViewScrollDirection.horizontal 

    collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout!) 
    collectionView?.dataSource = self 
    collectionView?.delegate = self 
    collectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell") 
    collectionView?.backgroundColor = UIColor.blue 
    collectionView?.isPagingEnabled = true 

    self.view.addSubview(collectionView!) 
} 

override func viewDidLayoutSubviews() { 

    // update layout item size here to your new view size 
    layout?.itemSize = view.bounds.size 
    // update collection view frame to new view size here 
    collectionView?.frame = view.bounds 

    super.viewDidLayoutSubviews() 
} 

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
    return 14 
} 

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) 
    cell.backgroundColor = UIColor.red 
    return cell 
} 
} 


class ViewController: UIViewController { 

override func viewDidLoad() { 
    super.viewDidLoad() 

    let slider = Slider() 

    // note clips to bounds here, avoids confusion as to where the frame is 
    slider.view.clipsToBounds = true 
    addChild(child: slider, frame: CGRect(x: 50, y: 50, width: 30, height: 30)) 
} 


} 


extension UIViewController { 

// MARK: View Controller Containment convenience functions 

func addChild(child:UIViewController, frame:CGRect) { 
    // notify child of containment 
    child.willMove(toParentViewController: self) 

    // add content as child 
    self.addChildViewController(child) 

    // set frame of child content 
    child.view.frame = frame 

    // add childs view to hierarchy 
    self.view.addSubview(child.view) 

    // call containment delegate 
    child.didMove(toParentViewController: self) 
} 

/* 
* Call this function on a child view controller to remove it from it's parent controller and dismiss it. 
*/ 
func remove(fromParentWithAnimationDuration animationDuration:TimeInterval) 
{ 
    // notify child it's being removed 
    self.willMove(toParentViewController: nil) 

    // remove the view 
    self.view.removeFromSuperview() 

    // remove child controller from container 
    self.removeFromParentViewController() 
} 

} 
+0

Danke! Ich habe mehrere Probleme bei der Erstellung anderer 'VC's festgestellt. Das Problem lag darin. Danke, dass du auf meine Fehler hingewiesen hast. Dennoch habe ich einige Fragen bezüglich deiner Antwort: 1) Ist es eine schlechte Übung, das Selbst auszulassen? Wie du es hier getan hast -> 'view.bounds' 2) Warum hast du' bounds' anstelle von 'frame' benutzt? 3) Warum platzierst du 'super.viewDidLayoutSubviews()' am Ende von 'func viewDidLayoutSubviews'? – Doe

+0

Die Verwendung von selbst ist nicht erforderlich, außer in Verschlüssen. Es ist mehr eine persönliche Vorliebe, ich denke, es ist sauberer ohne all die zusätzlichen "Selbst". 2) Es hängt davon ab, was Sie anstreben. Ein Views-Frame ist seine Platzierung innerhalb seiner Superview und die Grenzen sind seine Platzierung in seinem eigenen Koordinatensystem. Durch Verwendung von Grenzen wird der Rahmen der Unteransicht jedesmal 0,0, Breite, Höhe sein. 3) Da ich Ansichten verlege, rufe ich super an, wenn meine Layoutänderungen abgeschlossen sind. Ich könnte mich irren, aber da es ViewDIDLayoutSubviews ist, scheint es, dass alle Ansichten angezeigt werden sollten, wenn Super aufgerufen wird. – digitalHound

Verwandte Themen