9

As Eureka is used for creating a new record, which includes different datatypes, one being MediaPicker, I'm wondering how to present its viewController.

Which row would do the job? PushRow or ButtonRow

Here is my class where I try to create this.

import UIKit
import MediaPlayer

import Eureka

public final class MusicRow<T: Equatable> : SelectorRow<T, PushSelectorCell<T>, SelectorViewController<T>>, RowType {

    public required init(tag: String?) {
        super.init(tag: tag)
        presentationMode = .Show(controllerProvider: ControllerProvider.Callback {
            return AddMusicViewController(){ _ in }
            }, completionCallback: { vc in
                vc.navigationController?.popViewControllerAnimated(true)
        })
    }
}

public class AddMusicViewController: MPMediaPickerController, MPMediaPickerControllerDelegate {

    var musicPicker: MPMediaPickerController!

    public var row: RowOf<MPMediaItemCollection>!

    public var completionCallback : ((UIViewController) -> ())?

    public override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        // Setup sections/rows for tableView
        addMusic()
    }

    // Initialize musicPicker and customize it
    func addMusic() {
        musicPicker = MPMediaPickerController.self(mediaTypes:.Music)
        musicPicker.delegate = self
        musicPicker.allowsPickingMultipleItems = true
        view.addSubview(musicPicker.view)
    }

    // After selection, store the data into an array
    public func mediaPicker(mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
        musicTemp = nil
        musicTemp = mediaItemCollection
        if musicTemp == nil {
            noMusic = true
        } else {
            noMusic = false
        }
        completionCallback?(self)
    }

    // Cancel mediaPickerController
    public func mediaPickerDidCancel(mediaPicker: MPMediaPickerController){
        // Dismiss the picker if the user canceled
        noMusic = true
        completionCallback?(self)
    }
}

Below is the error that I face.

Error

Shyam
  • 561
  • 5
  • 22
  • @EricAya Well, actually not. I'm completely new to iOS development. And, Eureka seems to be a very good framework when it comes to forms. So, I use it my app. But, when there is a custom implementation, I'm not able to relate it correctly. What would you suggest in this case? Thanks.. – Shyam Sep 12 '16 at 15:51
  • I did that as well. The error I receive is, Cannot invoke initializer for type 'AddMusicViewController' with an argument list of type '((_) -> _)' – Shyam Sep 12 '16 at 15:57
  • Hi Shyam, I want to present the GooglePlaces autocomplete ViewController on selection of a row (https://developers.google.com/places/ios-api/autocomplete) is it possible using your code? – Anjan Biswas Jul 07 '17 at 02:34

1 Answers1

7

Although, this was a generic question, my requirement was to use a MPMediaPickerController.

Below is my setup.

import UIKit
import MediaPlayer

import Eureka

// MusicRow
public final class MusicRow : SelectorRow<MPMediaItemCollection, PushSelectorCell<MPMediaItemCollection>, AddMusicViewController>, RowType {
    public required init(tag: String?) {
        super.init(tag: tag)
        presentationMode = .Show(controllerProvider: ControllerProvider.Callback { return AddMusicViewController(){ _ in } }, completionCallback: { vc in vc.navigationController?.popViewControllerAnimated(true) })
displayValueFor = {
        guard var musicTitle = $0 else { return "" }
        musicTitle = musicTemp!
        let representativeItem = musicTitle.representativeItem
        print("representativeItem = \(representativeItem)")
        let representativeItemTitle = representativeItem?.title
        return  "\(representativeItemTitle)"
        }
    }
}

// MusicViewController
public class AddMusicViewController : UIViewController, TypedRowControllerType, MPMediaPickerControllerDelegate {

    public var row: RowOf<MPMediaItemCollection>!
    public var completionCallback : ((UIViewController) -> ())?

    lazy var musicPicker : MPMediaPickerController = { [unowned self] in
        let mediaPicker = MPMediaPickerController.self(mediaTypes:.Music)
        return mediaPicker
    }()

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nil, bundle: nil)
    }

    convenience public init(_ callback: (UIViewController) -> ()){
        self.init(nibName: nil, bundle: nil)
        completionCallback = callback
    }

    public override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(musicPicker.view)

        musicPicker.delegate = self
        musicPicker.allowsPickingMultipleItems = true

        self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
    }

    // After selection, store the data into a temporary variable
    public func mediaPicker(mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
        musicTemp = nil
        musicTemp = mediaItemCollection
        if musicTemp == nil {
            noMusic = true
        } else {
            noMusic = false
            row.value? = musicTemp!
        }
        completionCallback?(self)
    }

    // Cancel mediaPickerController
    public func mediaPickerDidCancel(mediaPicker: MPMediaPickerController){
        // Dismiss the picker if the user canceled
        noMusic = true
        completionCallback?(self)
    }
}

I believe, it isn't hard to tweak it to anyone's personal requirements!

Shyam
  • 561
  • 5
  • 22
  • Although, I managed to present the viewcontroller, I'm still not able to pick up a value to be displayed when I segue back to the row!! Anyone has any suggestions? – Shyam Sep 27 '16 at 10:11
  • 1
    Well, actually I was able to with the help of the creators of Eureka. row.value = musicTemp! (Removing the question mark, did the trick) :) – Shyam Oct 05 '16 at 00:21
  • This does answer "show" but doing a "show" from a "form view controller" often times means you really want to "push" into the navigation stack, in which case you would need to override "show(...)" method on your FormViewController subclass and say like self.navigationController?.push(...) – snakeoil Oct 19 '17 at 16:31