Swift 1.2 在 iOS 8 上的全局弹出框功能

Global Popover Function in Swift 1.2 on iOS 8

我在我的应用程序中使用了这个函数,创建一个全局函数会很好:

class CustomReportVC: UIViewController, UIAdaptivePresentationControllerDelegate, UIPopoverPresentationControllerDelegate {

  func showPicker(pickerValues:[String], field:UITextField) -> AnyPickerVC{
    //Set up modal
    let storyboard = UIStoryboard(name: "Popovers", bundle: nil)
    let modal = storyboard.instantiateViewControllerWithIdentifier("AnyPickerModal") as! AnyPickerVC
    modal.modalPresentationStyle = UIModalPresentationStyle.Popover
    let pc = modal.popoverPresentationController
    pc?.permittedArrowDirections = .Down
    pc?.sourceView = field
    pc?.sourceRect = field.bounds
    modal.preferredContentSize = CGSizeMake(300,180)
    pc?.delegate = self

    //Pass in data
    modal.data = pickerValues

    //Set the value from within the picker controller
    modal.passDataToParent = { (value) in
      field.text = value
    }

    return modal
  }

  //Required for the popover
  func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
    return .None
  }

}

我 运行 遇到的问题是 pc?.delegate = self。由于 CustomReportVC 符合 UIPopoverPresentationControllerDelegate,因此可以正常工作。

但是一旦我尝试将其创建为符合此协议的 class 之外的全局函数,我就会收到错误消息:

func globalShowPicker(pickerValues:[String], field:UITextField, controller:UIViewController) -> AnyPickerVC{
  //...
  pc?.delegate = controller //<-- ( ! ) Type UIViewController does not conform to UIPopoverPresentationControllerDelegate  
}

不管我把controller做成UIViewController还是AnyObject,都不符合。有没有办法以某种方式将协议符合性传递给全局函数?

知道如何解决这个问题吗?谢谢。 :)

尝试添加一个继承自它们的新 class。像这样。

class PopoverController: UIViewController, UIPopoverPresentationControllerDelegate {

}

然后,将函数切换成这样。

func globalShowPicker(pickerValues:[String], field:UITextField, controller: PopoverController) -> AnyPickerVC{
  //...
  pc?.delegate = controller  
}

使您的全局函数通用以指定它仅适用于某些 类型的 UIViewController。在此示例中,T 可以采用任何 UIViewController 类型的值,该类型也符合列出的其他协议。

func globalShowPicker< T: UIViewController where
    T: UIPopoverPresentationControllerDelegate,
    T: UIAdaptivePresentationControllerDelegate > 
    (pickerValues:[String], field:UITextField, controller: T) -> AnyPickerVC
{
   //...
   pc?.delegate = controller 

   return blah
}

确实有点长,而且我还没有找到缩进所有约束的最佳方法。但它有效。

是这样的吗?

self.presentViewController(pc, animated: true, completion: nil)

顺便说一句,如果你正在做通用,你不能像 iPhone 那样呈现 iPad UIActivityViewController。您需要按照 Apple 建议的设计指南将其呈现在弹出窗口中。

或者举个例子

@IBAction func shareButtonClicked(sender: UIButton)
{
let textToShare = "Text"

if let myWebsite = NSURL(string: "http://www.example.com/")
{
    let objectsToShare = [textToShare, myWebsite]
    let activityVC = UIActivityViewController(activityItems:  objectsToShare, applicationActivities: nil)

    var nav = UINavigationController(rootViewController: activityVC)
    nav.modalPresentationStyle = UIModalPresentationStyle.Popover
    var popover = nav.popoverPresentationController as UIPopoverPresentationController!
    activityVC.preferredContentSize = CGSizeMake(500,600)
    popover.sourceView = self.view
    popover.sourceRect = CGRectMake(100,100,0,0)

    self.presentViewController(nav, animated: true, completion: nil)

}
}


class MyViewController : UIViewController,   UIPopoverPresentationControllerDelegate {
//code here
}

您可以像这样在函数中将委托作为参数传递:

class CustomReportVC: UIViewController, UIAdaptivePresentationControllerDelegate, UIPopoverPresentationControllerDelegate {

    class func showPicker(pickerValues:[String], field:UITextField, delegate: UIPopoverPresentationControllerDelegate) -> UIViewController {
        //Set up modal
        let storyboard = UIStoryboard(name: "Popovers", bundle: nil)
        let modal = storyboard.instantiateViewControllerWithIdentifier("AnyPickerModal") as! UIViewController
        modal.modalPresentationStyle = UIModalPresentationStyle.Popover
        let pc = modal.popoverPresentationController
        pc?.permittedArrowDirections = .Down
        pc?.sourceView = field
        pc?.sourceRect = field.bounds
        modal.preferredContentSize = CGSizeMake(300,180)
        pc?.delegate = delegate

        //Pass in data
        modal.data = pickerValues

        //Set the value from within the picker controller
        modal.passDataToParent = { (value) in
            field.text = value
        }

        return modal
    }

    //Required for the popover
    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
        return .None
    }

}

最后你必须有一个符合协议的视图控制器实例,但这样你就可以拥有全局函数,就像你想要的一样,并在符合协议的视图控制器中传递自指针协议 "UIPopoverPresentationControllerDelegate":

CustomReportVC.showPicker(pickerValues:....., delegate: self)