Create an array of objects that implement a specific protocol

TL DR

I am looking for an array type ( var array = [TheTypeImLookingFor]()), for example, "all objects that subclass UIViewController and implement the protocol MyProtocol.

Explanation

I create a master view with a container view and built-in child views (controller). No problem, this will work for so long since I only have one type of child view controller type base.

Due to the contents of the screens, I now have a bunch of view controllers of the type MyTableViewControllerthat is a subclass UITableViewControllerand other view controllers that have the usual UIViewControllersbase.

All view controllers have one thing in common. The default data property myData: MyObject.

I created a protocol MyProtocolthat contains this property.

Now I have to combine all these view controllers into one array in order to use it as the steps of the wizard. So far I only need to access the methods of the view controller (array elements are a type UIViewController), I can use var viewControllers = [UIViewController](), or if I only want to access the property myData, I change the type of the array element to MyObject.

But the problem is that I need to access the methods from UIViewControllerand from the protocol.

That's why I'm looking for an array type of type "all objects that subclass UIViewController and implement the protocol MyProtocol.

I tried:

  • var viewControllers = [UIViewController: MyProtocol]()// is a dict
  • `var viewControllers = UIViewController, where MyProtocol
  • `var viewControllers = UIViewController.conforms (to: MyProtocol)
  • ...

, .

+4
5

, -, , .

, MyProtocol.

struct MyProtocolViewController {

    let base: UIViewController

    init<T : UIViewController>(_ base: T) where T : MyProtocol {
        self.base = base
    }

    func asMyProtocol() -> MyProtocol {
        return base as! MyProtocol
    }
}

[MyProtocolViewController] UIViewController, MyProtocol.

// given that ViewController and AnotherViewController conform to MyProtocol.
let viewControllers = [MyProtocolViewController(ViewController()),
                       MyProtocolViewController(AnotherViewController())]

for viewController in viewControllers {
    print(viewController.asMyProtocol().myData)
    print(viewController.base.prefersStatusBarHidden)
}
+2

- :

protocol UIViewControllerClass {}
extension UIViewController: UIViewControllerClass {}

protocol MyProtocol:class {}

class MySpecialVC:UIViewController,MyProtocol {}    

var viewControllers = [UIViewControllerClass & MyProtocol]()

viewControllers.append( MySpecialVC() )   

, UIViewController . , ( )

extension MyProtocol where Self: UIViewControllerClass
{
   var vc:UIViewController { return self as! UIViewController }
}

// accessing the view controller methods would then only require insertion of a property name.
viewControllers.first!.vc.view

UIViewController, -, , .

+1

:

:

class ObservingViewController : UIViewController, MyProtocol {


}

var viewControllers : [ObservingViewController] = []
0

protocol, UIViewController, . , , .

protocol UIViewControllerInteractions {
    //copy the signature from the methods you want to interact with here, e.g.
    var title: String? { get set }
}

.

protocol MyProtocol: UIViewControllerInteractions { }

, UIViewControllerInteractions MyProtocol.

protocol MyProtocolViewController: UIViewControllerInteractions, MyProtocol { }

, SubclassUIViewController, myData, UIViewControllerInteractions UIViewController ( )

class SubclassUIViewController: MyProtocol {
    var myData ...
}

array MyProtocol MyProtocolViewController, , UIViewControllerInteractions, UIViewController.

var viewController: [MyProtocol] = [...]
viewController.forEach { (vc) in
    print(vc.myData)
    print(vc.title)
}
0

. :

var viewControllers: [MapViewController]

UIViewController :

protocol MapViewControllerDelegate {
    func zoomToUser()
}

:

class MapViewController: UIViewController {
    var delegate: MapViewControllerDelegate?
}

: , , . - UIViewController, :

class GoogleMapsViewController: MapViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        delegate = self
    }
}

extension GoogleMapsViewController: MapViewControllerDelegate {
    func zoomToUser() {
        // Place custom google maps code here
    }
}

viewDidLoad. .

:

let googleMapsViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "GoogleMapsViewController") as! GoogleMapsViewController
let mapboxMapsViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "MapboxMapsViewController") as! MapboxMapsViewController
let mapViewControllers: [MapViewController] = [googleMapsViewController, mapboxViewController]
for mapVC in mapViewControllers {
    mapVC.delegate?.zoomToUser()
}

:

  • MapViewController , MapViewControllerDelegate, GoogleMapsViewController MapboxMapsViewController.
  • , .
  • Other answers do not require any type selection. Everyone UIViewControllerstill is UIViewControllerand provides all of his methods.
0
source

Source: https://habr.com/ru/post/1669034/


All Articles