Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/118.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何使此弹出扩展更通用,以应用于任何视图?_Ios_Swift - Fatal编程技术网

Ios 如何使此弹出扩展更通用,以应用于任何视图?

Ios 如何使此弹出扩展更通用,以应用于任何视图?,ios,swift,Ios,Swift,我已将在github上找到的弹出式扩展编辑为以下内容 import UIKit class Home: UIViewController { override func viewDidLoad() { self.PopUpInit() super.viewDidLoad() } var overlayView: UIView! var alertView: UIView! var animator: UIDyna

我已将在github上找到的弹出式扩展编辑为以下内容

import UIKit

class Home: UIViewController
{
    override func viewDidLoad()
    {
        self.PopUpInit()
        super.viewDidLoad()
    }

    var overlayView: UIView!
    var alertView: UIView!
    var animator: UIDynamicAnimator!

}
PopUpExtension.swift:

import UIKit
extension (Home)
{
//Call this method in view did load
func PopUpInit()
{
    createOverlay()
    createAlert()
}


func createOverlay()
{
    let p = CGRectMake(self.view!.frame.origin.x, self.view!.frame.origin.y, self.view!.bounds.size.width, self.view!.bounds.size.height)
    overlayView = UIView(frame: p)
    overlayView.backgroundColor = UIColor.grayColor()
    overlayView.alpha = 0.0
    self.view!.addSubview(overlayView)
}

func createAlert()
{
    let alertWidth: CGFloat = UIScreen.mainScreen().bounds.width
    let alertHeight: CGFloat = UIScreen.mainScreen().bounds.height
    let alertViewFrame: CGRect = CGRectMake(0,0, alertWidth, alertHeight)

    alertView = UIView(frame: alertViewFrame)
    alertView.center = self.view.center
    alertView.backgroundColor = UIColor.clearColor()
    alertView.alpha = 0.0

    let button = UIButton(type: UIButtonType.System)
    button.setTitle("Cancel", forState: UIControlState.Normal)
    button.setTitleColor(UIColor.redColor(), forState: UIControlState.Normal)
    button.backgroundColor = UIColor.clearColor()
    button.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
    button.addTarget(self, action: "dismissAlert", forControlEvents: UIControlEvents.TouchUpInside)
    button.center.x = alertView.center.x

    let button1 = UIButton(type: UIButtonType.RoundedRect)
    button1.setTitle("Send", forState: UIControlState.Normal)
    button1.backgroundColor = UIColor.greenColor()
    button1.frame = CGRectMake(100, 100, 80.0, 80.0)
    button1.addTarget(self, action: "Button1", forControlEvents: UIControlEvents.TouchUpInside)
    button1.center.x = alertView.center.x

    let button2 = UIButton(type: UIButtonType.RoundedRect)
    button2.setTitle("Send", forState: UIControlState.Normal)
    button2.backgroundColor = UIColor.greenColor()
    button2.frame = CGRectMake(100, 200, 80.0, 80.0)
    button2.addTarget(self, action: "Button2", forControlEvents: UIControlEvents.TouchUpInside)
    button2.center.x = alertView.center.x

    let button3 = UIButton(type: UIButtonType.RoundedRect)
    button3.setTitle("Send", forState: UIControlState.Normal)
    button3.backgroundColor = UIColor.greenColor()
    button3.frame = CGRectMake(100, 300, 80.0, 80.0)
    button3.addTarget(self, action: "Button3", forControlEvents: UIControlEvents.TouchUpInside)
    button3.center.x = alertView.center.x

    alertView.addSubview(button)
    alertView.addSubview(button1)
    alertView.addSubview(button2)
    alertView.addSubview(button3)
    self.view!.addSubview(alertView)

}

func showAlert()
{
    if (alertView == nil)
    {
        createAlert()
    }
    UIView.animateWithDuration(0.3)
        {
            self.overlayView.alpha = 0.5
            self.alertView.alpha = 1.0
    }
}

func dismissAlert()
{
    UIView.animateWithDuration(0.15, animations:
        {
            self.overlayView.alpha = 0.0
            self.alertView.alpha = 0.0
        }, completion:
        {
            (value: Bool) in
            self.alertView.removeFromSuperview()
            self.alertView = nil
    })
}

func Button1()
{
    print("button1")
}

func Button2()
{
    print("button2")
}

func Button3()
{
    print("button3")
}

}
现在在Home.swift视图控制器中,我只需执行以下操作

import UIKit

class Home: UIViewController
{
    override func viewDidLoad()
    {
        self.PopUpInit()
        super.viewDidLoad()
    }

    var overlayView: UIView!
    var alertView: UIView!
    var animator: UIDynamicAnimator!

}
问题是:

如何将这个扩展转换成一个可以在任何需要的地方使用的类,不仅仅是Home.swift,我还希望避免将这些定义为使用这个弹出窗口的所有类

var overlayView: UIView!
var alertView: UIView!
var animator: UIDynamicAnimator!
你能告诉我做这件事的最佳方法吗


谢谢。

让它更通用的诀窍是让它更面向协议。使用
协议
您可以利用
默认实现
来定义
一致性类型
需要什么样,并使用
扩展
来实现方法


素材:

import UIKit
import XCPlayground

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
弹出列表:

import UIKit
import XCPlayground

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
let vc = UIViewController()

let window = UIWindow(frame: UIScreen.mainScreen().bounds)
window.makeKeyAndVisible()
window.rootViewController = vc

vc.view.backgroundColor = UIColor.greenColor()

XCPlaygroundPage.currentPage.liveView = vc.view

let pop = PopUp()
pop.showAlert(animated: true)
这将是您的主要
协议
。任何具有
视图
变量的内容都可以设置为
可弹出

@objc protocol PopUpAble : class {

    var view : UIView! { get set }

    func button1()
    func button2()
    func button3()

    func alertWillDismiss() -> Bool
    func alertDidDismiss()

    func dismissAlert()

}

标识类型:

import UIKit
import XCPlayground

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
let vc = UIViewController()

let window = UIWindow(frame: UIScreen.mainScreen().bounds)
window.makeKeyAndVisible()
window.rootViewController = vc

vc.view.backgroundColor = UIColor.greenColor()

XCPlaygroundPage.currentPage.liveView = vc.view

let pop = PopUp()
pop.showAlert(animated: true)
这些是
协议
一致性类
,能够区分
警报视图
覆盖视图
,而无需将它们分配给
属性
。更少的样板代码->更好

protocol AlertType : class {}

protocol OverlayType : class {}

class AlertView : UIView, AlertType {}

class OverlayView : UIView, OverlayType {}

实现:

import UIKit
import XCPlayground

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
let vc = UIViewController()

let window = UIWindow(frame: UIScreen.mainScreen().bounds)
window.makeKeyAndVisible()
window.rootViewController = vc

vc.view.backgroundColor = UIColor.greenColor()

XCPlaygroundPage.currentPage.liveView = vc.view

let pop = PopUp()
pop.showAlert(animated: true)
这是与您之前相同的
函数集合
,只是修改为使用
弹出表
协议
中提供的功能

  • create…
    函数现在搜索现有的匹配类型或创建
  • 没有更多的设置功能,不需要
  • 可选动画
  • 设置显示/隐藏之前/之后的视图顺序
这一切使得它更加通用,并且不需要在VC中实现

extension PopUpAble {

    func createOverlay() -> UIView {

        if let overlay = (view.subviews.filter { $0 is OverlayType }).first {
            return overlay
        }

        let p = CGRectMake(self.view!.frame.origin.x, self.view!.frame.origin.y, self.view!.bounds.size.width, self.view!.bounds.size.height)
        let overlayView = OverlayView(frame: p)
        overlayView.backgroundColor = UIColor.grayColor()
        overlayView.alpha = 0.0
        view!.insertSubview(overlayView, atIndex: 0)

        return overlayView
    }

    func createAlert() -> UIView {

        if let alert = (view.subviews.filter { $0 is AlertType }).first {
            return alert
        }

        let alertWidth: CGFloat = UIScreen.mainScreen().bounds.width
        let alertHeight: CGFloat = UIScreen.mainScreen().bounds.height
        let alertViewFrame: CGRect = CGRectMake(0,0, alertWidth, alertHeight)

        let alertView = AlertView(frame: alertViewFrame)
        alertView.center = self.view.center
        alertView.backgroundColor = UIColor.clearColor()
        alertView.alpha = 0.0

        let button = UIButton(type: UIButtonType.System)
        button.setTitle("Cancel", forState: UIControlState.Normal)
        button.setTitleColor(UIColor.redColor(), forState: UIControlState.Normal)
        button.backgroundColor = UIColor.clearColor()
        button.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
        button.addTarget(self, action: #selector(Self.dismissAlert), forControlEvents: UIControlEvents.TouchUpInside)
        button.center.x = alertView.center.x

        let button1 = UIButton(type: UIButtonType.RoundedRect)
        button1.setTitle("Send", forState: UIControlState.Normal)
        button1.backgroundColor = UIColor.greenColor()
        button1.frame = CGRectMake(100, 100, 80.0, 80.0)
        button1.addTarget(self, action: #selector(Self.button1), forControlEvents: UIControlEvents.TouchUpInside)
        button1.center.x = alertView.center.x

        let button2 = UIButton(type: UIButtonType.RoundedRect)
        button2.setTitle("Send", forState: UIControlState.Normal)
        button2.backgroundColor = UIColor.greenColor()
        button2.frame = CGRectMake(100, 200, 80.0, 80.0)
        button2.addTarget(self, action: #selector(Self.button2), forControlEvents: UIControlEvents.TouchUpInside)
        button2.center.x = alertView.center.x

        let button3 = UIButton(type: UIButtonType.RoundedRect)
        button3.setTitle("Send", forState: UIControlState.Normal)
        button3.backgroundColor = UIColor.greenColor()
        button3.frame = CGRectMake(100, 300, 80.0, 80.0)
        button3.addTarget(self, action: #selector(Self.button3), forControlEvents: UIControlEvents.TouchUpInside)
        button3.center.x = alertView.center.x

        alertView.addSubview(button)
        alertView.addSubview(button1)
        alertView.addSubview(button2)
        alertView.addSubview(button3)
        view!.insertSubview(alertView, atIndex: 1)

        return alertView

    }

    func showAlert(animated animated:Bool = true) {

        func show(alert:UIView,overlay:UIView) {
            if animated {
                UIView.animateWithDuration(0.3) {
                    overlay.alpha = 0.5
                    alert.alpha = 1.0
                }
            } else {
                overlay.alpha = 0.5
                alert.alpha = 1.0
            }
        }

        let overlay = createOverlay()
        let alert = createAlert()

        view.bringSubviewToFront(overlay)
        view.bringSubviewToFront(alert)

        show(alert, overlay: overlay)

    }

    func hideAlert(animated animated:Bool = true) {

        guard alertWillDismiss() else {
            return
        }

        func hide(alert:UIView,overlay:UIView) {
            if animated {
                UIView.animateWithDuration(0.15, animations: {
                    overlay.alpha = 0.0
                    alert.alpha = 0.0
                    }) {
                    if $0 {
                        self.view.sendSubviewToBack(alert)
                        self.view.sendSubviewToBack(overlay)
                        self.alertDidDismiss()
                    }
                }
            } else {
                overlay.alpha = 0.0
                alert.alpha = 0.0
                view.sendSubviewToBack(alert)
                view.sendSubviewToBack(overlay)
                alertDidDismiss()
            }
        }

        let overlay = createOverlay()
        let alert = createAlert()

        hide(alert, overlay: overlay)
    }
}

作品:

import UIKit
import XCPlayground

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
let vc = UIViewController()

let window = UIWindow(frame: UIScreen.mainScreen().bounds)
window.makeKeyAndVisible()
window.rootViewController = vc

vc.view.backgroundColor = UIColor.greenColor()

XCPlaygroundPage.currentPage.liveView = vc.view

let pop = PopUp()
pop.showAlert(animated: true)
alertwilldisease
alertdidisease
是不需要的,但是它们很好地遵循了标准的UIKit流程,并为您提供了更多的控制

class VC : UIViewController, PopUpAble {

    func button1() {
        print("button1")
    }

    func button2() {
        print("button2")
    }

    func button3() {
        print("button3")
    }

    func alertWillDismiss() -> Bool {
        return true
    }

    func alertDidDismiss() {
        print("dismissed")
    }

    func dismissAlert() { // this bridges between objc en swift
        self.hideAlert() 
    }

}


let vc = VC()
vc.view.backgroundColor = UIColor.greenColor()

vc.showAlert(animated: true)

XCPlaygroundPage.currentPage.liveView = vc.view

另一种方法是获取当前可见的viewcontroller并在其上显示警报。它们不是在
UIViewController
子类中定义动作,而是在
PopUp
对象中实现。需要时,将从任何位置创建一个
弹出窗口
,它将显示在当前VC上


素材:

import UIKit
import XCPlayground

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
let vc = UIViewController()

let window = UIWindow(frame: UIScreen.mainScreen().bounds)
window.makeKeyAndVisible()
window.rootViewController = vc

vc.view.backgroundColor = UIColor.greenColor()

XCPlaygroundPage.currentPage.liveView = vc.view

let pop = PopUp()
pop.showAlert(animated: true)

当前视图控制器:

import UIKit
import XCPlayground

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
let vc = UIViewController()

let window = UIWindow(frame: UIScreen.mainScreen().bounds)
window.makeKeyAndVisible()
window.rootViewController = vc

vc.view.backgroundColor = UIColor.greenColor()

XCPlaygroundPage.currentPage.liveView = vc.view

let pop = PopUp()
pop.showAlert(animated: true)
不能把这个代码归功于你,是从某处来的。(如果某人有链接?)


与另一个答案相同:

protocol AlertType : class {}

protocol OverlayType : class {}

class AlertView : UIView, AlertType {}

class OverlayView : UIView, OverlayType {}

弹出对象:

import UIKit
import XCPlayground

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
let vc = UIViewController()

let window = UIWindow(frame: UIScreen.mainScreen().bounds)
window.makeKeyAndVisible()
window.rootViewController = vc

vc.view.backgroundColor = UIColor.greenColor()

XCPlaygroundPage.currentPage.liveView = vc.view

let pop = PopUp()
pop.showAlert(animated: true)
子类化可用于重写操作

class PopUp : NSObject {

    func button1Tapped() {
        print("button1")
    }

    func button2Tapped() {
        print("button2")
    }

    func button3Tapped() {
        print("button3")
    }

   func alertWillDismiss() -> Bool {
        return true
    }

    func alertDidDismiss() {
        print("dismissed")
    }

这现在在弹出的
中实现
抓取当前VC的
视图
,用于显示警报

    func createOverlay() -> UIView? {

        guard let window = UIApplication.sharedApplication().windows.first, view = window.visibleViewController?.view else {
            return nil
        }

        if let overlay = (view.subviews.filter { $0 is OverlayType }).first {
            return overlay
        }

        let p = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.bounds.size.width, view.bounds.size.height)
        let overlayView = OverlayView(frame: p)
        overlayView.backgroundColor = UIColor.grayColor()
        overlayView.alpha = 0.0
        view.insertSubview(overlayView, atIndex: 0)

        return overlayView
    }

    func createAlert() -> UIView? {

        guard let window = UIApplication.sharedApplication().windows.first, view = window.visibleViewController?.view else {
            return nil
        }

        if let alert = (view.subviews.filter { $0 is AlertType }).first {
            return alert
        }

        let alertWidth: CGFloat = UIScreen.mainScreen().bounds.width
        let alertHeight: CGFloat = UIScreen.mainScreen().bounds.height
        let alertViewFrame: CGRect = CGRectMake(0,0, alertWidth, alertHeight)

        let alertView = AlertView(frame: alertViewFrame)
        alertView.center = view.center
        alertView.backgroundColor = UIColor.clearColor()
        alertView.alpha = 0.0

        let button = UIButton(type: UIButtonType.System)
        button.setTitle("Cancel", forState: UIControlState.Normal)
        button.setTitleColor(UIColor.redColor(), forState: UIControlState.Normal)
        button.backgroundColor = UIColor.clearColor()
        button.frame = CGRectMake(0, 0, view.frame.width, view.frame.height)
        button.addTarget(self, action: #selector(dismissAlert), forControlEvents: UIControlEvents.TouchUpInside)
        button.center.x = alertView.center.x

        let button1 = UIButton(type: UIButtonType.RoundedRect)
        button1.setTitle("Send", forState: UIControlState.Normal)
        button1.backgroundColor = UIColor.greenColor()
        button1.frame = CGRectMake(100, 100, 80.0, 80.0)
        button1.addTarget(self, action: #selector(button1Tapped), forControlEvents: UIControlEvents.TouchUpInside)
        button1.center.x = alertView.center.x

        let button2 = UIButton(type: UIButtonType.RoundedRect)
        button2.setTitle("Send", forState: UIControlState.Normal)
        button2.backgroundColor = UIColor.greenColor()
        button2.frame = CGRectMake(100, 200, 80.0, 80.0)
        button2.addTarget(self, action: #selector(button2Tapped), forControlEvents: UIControlEvents.TouchUpInside)
        button2.center.x = alertView.center.x

        let button3 = UIButton(type: UIButtonType.RoundedRect)
        button3.setTitle("Send", forState: UIControlState.Normal)
        button3.backgroundColor = UIColor.greenColor()
        button3.frame = CGRectMake(100, 300, 80.0, 80.0)
        button3.addTarget(self, action: #selector(button3Tapped), forControlEvents: UIControlEvents.TouchUpInside)
        button3.center.x = alertView.center.x

        alertView.addSubview(button)
        alertView.addSubview(button1)
        alertView.addSubview(button2)
        alertView.addSubview(button3)
        view.insertSubview(alertView, atIndex: 1)

        return alertView

    }

    func showAlert(animated animated:Bool = true) {

        guard let window = UIApplication.sharedApplication().windows.first, view = window.visibleViewController?.view else {
            return
        }

        guard let overlay = createOverlay(), alert = createAlert() else {
            return
        }

        func show(alert:UIView,overlay:UIView) {
            if animated {
                UIView.animateWithDuration(0.3) {
                    overlay.alpha = 0.5
                    alert.alpha = 1.0
                }
            } else {
                overlay.alpha = 0.5
                alert.alpha = 1.0
            }
        }


        view.bringSubviewToFront(overlay)
        view.bringSubviewToFront(alert)

        show(alert, overlay: overlay)

    }

    func dismissAlert(animated animated:Bool = true) {

        guard let window = UIApplication.sharedApplication().windows.first, view = window.visibleViewController?.view else {
            return
        }

        guard let overlay = createOverlay(), alert = createAlert() else {
            return
        }

        func hide(alert:UIView,overlay:UIView) {
            if animated {
                UIView.animateWithDuration(0.15, animations: {
                    overlay.alpha = 0.0
                    alert.alpha = 0.0
                    }) {
                    if $0 {
                        view.sendSubviewToBack(alert)
                        view.sendSubviewToBack(overlay)
                        self.alertDidDismiss()
                    }
                }
            } else {
                overlay.alpha = 0.0
                alert.alpha = 0.0
                view.sendSubviewToBack(alert)
                view.sendSubviewToBack(overlay)
                alertDidDismiss()
            }
        }

        hide(alert, overlay: overlay)
    }
}

作品:

import UIKit
import XCPlayground

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
let vc = UIViewController()

let window = UIWindow(frame: UIScreen.mainScreen().bounds)
window.makeKeyAndVisible()
window.rootViewController = vc

vc.view.backgroundColor = UIColor.greenColor()

XCPlaygroundPage.currentPage.liveView = vc.view

let pop = PopUp()
pop.showAlert(animated: true)

注意:

import UIKit
import XCPlayground

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
let vc = UIViewController()

let window = UIWindow(frame: UIScreen.mainScreen().bounds)
window.makeKeyAndVisible()
window.rootViewController = vc

vc.view.backgroundColor = UIColor.greenColor()

XCPlaygroundPage.currentPage.liveView = vc.view

let pop = PopUp()
pop.showAlert(animated: true)
隐藏后,我将从
视图中删除警报和覆盖。没有必要把它们留在身边