mirror of https://github.com/xaoxuu/ProHUD
update
This commit is contained in:
parent
ca6c36650b
commit
9431c715f5
|
@ -8,8 +8,11 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
33E2B6CF0D9BD11D8C027DE6 /* Pods_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB925B38880FB296AF5D219F /* Pods_Example.framework */; };
|
||||
CD10F0DA211582580077CAFF /* header.gif in Resources */ = {isa = PBXBuildFile; fileRef = CD10F0D9211582580077CAFF /* header.gif */; };
|
||||
CD95D26F22E732CE007559A3 /* TestA.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD95D26E22E732CE007559A3 /* TestA.swift */; };
|
||||
CD8BFF1823014850001E08DD /* TestToastVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD8BFF1723014850001E08DD /* TestToastVC.swift */; };
|
||||
CD8BFF1A2301485E001E08DD /* TestAlertVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD8BFF192301485E001E08DD /* TestAlertVC.swift */; };
|
||||
CD8BFF1C23014867001E08DD /* TestGuardVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD8BFF1B23014867001E08DD /* TestGuardVC.swift */; };
|
||||
CD8BFF1E230148DD001E08DD /* BaseListVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD8BFF1D230148DD001E08DD /* BaseListVC.swift */; };
|
||||
CD8BFF2023014CB5001E08DD /* EmptyVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD8BFF1F23014CB5001E08DD /* EmptyVC.swift */; };
|
||||
CDA4E03C20D3935B00CD2A0C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDA4E03B20D3935B00CD2A0C /* AppDelegate.swift */; };
|
||||
CDA4E03E20D3935B00CD2A0C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDA4E03D20D3935B00CD2A0C /* ViewController.swift */; };
|
||||
CDA4E04120D3935B00CD2A0C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CDA4E03F20D3935B00CD2A0C /* Main.storyboard */; };
|
||||
|
@ -21,9 +24,12 @@
|
|||
AB925B38880FB296AF5D219F /* Pods_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
BA1A6035F1B9A658B3BB225C /* Pods-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.release.xcconfig"; sourceTree = "<group>"; };
|
||||
CA1298266BE89D7950DE99F2 /* Pods-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
CD10F0D9211582580077CAFF /* header.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = header.gif; sourceTree = "<group>"; };
|
||||
CD59584620E36DA8000F6427 /* Example-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Example-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
CD95D26E22E732CE007559A3 /* TestA.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestA.swift; sourceTree = "<group>"; };
|
||||
CD8BFF1723014850001E08DD /* TestToastVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestToastVC.swift; sourceTree = "<group>"; };
|
||||
CD8BFF192301485E001E08DD /* TestAlertVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestAlertVC.swift; sourceTree = "<group>"; };
|
||||
CD8BFF1B23014867001E08DD /* TestGuardVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestGuardVC.swift; sourceTree = "<group>"; };
|
||||
CD8BFF1D230148DD001E08DD /* BaseListVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseListVC.swift; sourceTree = "<group>"; };
|
||||
CD8BFF1F23014CB5001E08DD /* EmptyVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyVC.swift; sourceTree = "<group>"; };
|
||||
CDA4E03820D3935B00CD2A0C /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
CDA4E03B20D3935B00CD2A0C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
CDA4E03D20D3935B00CD2A0C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
|
@ -84,11 +90,14 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
CDA4E03B20D3935B00CD2A0C /* AppDelegate.swift */,
|
||||
CD8BFF1D230148DD001E08DD /* BaseListVC.swift */,
|
||||
CD8BFF1F23014CB5001E08DD /* EmptyVC.swift */,
|
||||
CDA4E03D20D3935B00CD2A0C /* ViewController.swift */,
|
||||
CD95D26E22E732CE007559A3 /* TestA.swift */,
|
||||
CD8BFF1723014850001E08DD /* TestToastVC.swift */,
|
||||
CD8BFF192301485E001E08DD /* TestAlertVC.swift */,
|
||||
CD8BFF1B23014867001E08DD /* TestGuardVC.swift */,
|
||||
CDA4E03F20D3935B00CD2A0C /* Main.storyboard */,
|
||||
CDA4E04220D3935C00CD2A0C /* Assets.xcassets */,
|
||||
CD10F0D9211582580077CAFF /* header.gif */,
|
||||
CDA4E04420D3935C00CD2A0C /* LaunchScreen.storyboard */,
|
||||
CDA4E04720D3935C00CD2A0C /* Info.plist */,
|
||||
CD59584620E36DA8000F6427 /* Example-Bridging-Header.h */,
|
||||
|
@ -161,7 +170,6 @@
|
|||
CDA4E04620D3935C00CD2A0C /* LaunchScreen.storyboard in Resources */,
|
||||
CDA4E04320D3935C00CD2A0C /* Assets.xcassets in Resources */,
|
||||
CDA4E04120D3935B00CD2A0C /* Main.storyboard in Resources */,
|
||||
CD10F0DA211582580077CAFF /* header.gif in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -230,9 +238,13 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CD8BFF1823014850001E08DD /* TestToastVC.swift in Sources */,
|
||||
CDA4E03E20D3935B00CD2A0C /* ViewController.swift in Sources */,
|
||||
CD8BFF2023014CB5001E08DD /* EmptyVC.swift in Sources */,
|
||||
CD8BFF1A2301485E001E08DD /* TestAlertVC.swift in Sources */,
|
||||
CDA4E03C20D3935B00CD2A0C /* AppDelegate.swift in Sources */,
|
||||
CD95D26F22E732CE007559A3 /* TestA.swift in Sources */,
|
||||
CD8BFF1C23014867001E08DD /* TestGuardVC.swift in Sources */,
|
||||
CD8BFF1E230148DD001E08DD /* BaseListVC.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "alert-circle.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "alert-circle (1).png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 961 B |
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "header_center@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "header_center@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 28 KiB |
Binary file not shown.
Before Width: | Height: | Size: 44 KiB |
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14835.7" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14835.7" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ttk-4w-IeX">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
|
@ -8,42 +8,39 @@
|
|||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<!--ProHUD-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" image="bg" translatesAutoresizingMaskIntoConstraints="NO" id="0oA-CL-uZS">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
</imageView>
|
||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="PcH-Px-Vql">
|
||||
<rect key="frame" x="51" y="120" width="46" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="Button"/>
|
||||
<connections>
|
||||
<action selector="test:" destination="BYZ-38-t0r" eventType="touchUpInside" id="mff-h5-exz"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="0oA-CL-uZS" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="5mO-PC-le4"/>
|
||||
<constraint firstItem="0oA-CL-uZS" firstAttribute="top" secondItem="8bC-Xf-vdC" secondAttribute="top" id="Fay-dw-LvJ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="0oA-CL-uZS" secondAttribute="bottom" id="TC7-O2-j1c"/>
|
||||
<constraint firstAttribute="trailing" secondItem="0oA-CL-uZS" secondAttribute="trailing" id="U3A-8b-rnZ"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" title="ProHUD" id="Yzl-Q6-9v7"/>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="142" y="134"/>
|
||||
<point key="canvasLocation" x="1050.7246376811595" y="133.92857142857142"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="HjC-hd-4PZ">
|
||||
<objects>
|
||||
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="ttk-4w-IeX" sceneMemberID="viewController">
|
||||
<toolbarItems/>
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="juX-kz-8Ti">
|
||||
<rect key="frame" x="0.0" y="44" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<nil name="viewControllers"/>
|
||||
<connections>
|
||||
<segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="gyV-fc-5FK"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Lg9-xW-IRh" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="140.57971014492756" y="133.92857142857142"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="bg" width="414" height="896"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// BaseListVC.swift
|
||||
// Example
|
||||
//
|
||||
// Created by xaoxuu on 2019/8/12.
|
||||
// Copyright © 2019 Titan Studio. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class BaseListVC: UIViewController {
|
||||
|
||||
lazy var tableView: UITableView = {
|
||||
let tv = UITableView()
|
||||
|
||||
return tv
|
||||
}()
|
||||
|
||||
var titles: [String] {
|
||||
return ["Toast", "Alert", "Guard"]
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
|
||||
view.addSubview(tableView)
|
||||
tableView.dataSource = self
|
||||
tableView.delegate = self
|
||||
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
|
||||
tableView.snp.makeConstraints { (mk) in
|
||||
mk.edges.equalToSuperview()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension BaseListVC: UITableViewDataSource, UITableViewDelegate {
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return titles.count
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
|
||||
cell.textLabel?.text = titles[indexPath.row]
|
||||
return cell
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// EmptyVC.swift
|
||||
// Example
|
||||
//
|
||||
// Created by xaoxuu on 2019/8/12.
|
||||
// Copyright © 2019 Titan Studio. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
import Inspire
|
||||
|
||||
class EmptyVC: UIViewController {
|
||||
|
||||
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
view.backgroundColor = UIColor(white: 0.95, alpha: 1)
|
||||
// Do any additional setup after loading the view.
|
||||
|
||||
let lb = UILabel()
|
||||
lb.numberOfLines = 0
|
||||
lb.text = title
|
||||
lb.font = .regular(40)
|
||||
view.addSubview(lb)
|
||||
lb.snp.makeConstraints { (mk) in
|
||||
mk.center.equalToSuperview()
|
||||
mk.leading.greaterThanOrEqualToSuperview().offset(16)
|
||||
mk.trailing.lessThanOrEqualToSuperview().offset(-16)
|
||||
}
|
||||
|
||||
let btn = UIButton(type: .system)
|
||||
btn.titleLabel?.font = .bold(20)
|
||||
btn.setTitle("Dismiss", for: .normal)
|
||||
btn.addTarget(self, action: #selector(didTappedDismiss(_:)), for: .touchUpInside)
|
||||
view.addSubview(btn)
|
||||
btn.snp.makeConstraints { (mk) in
|
||||
mk.top.equalToSuperview().offset(Inspire.current.layout.safeAreaInsets(for: self).top)
|
||||
mk.trailing.equalToSuperview().offset(-16)
|
||||
mk.height.equalTo(44)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func didTappedDismiss(_ sender: UIButton) {
|
||||
dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension UIViewController {
|
||||
func presentEmptyVC(title: String?) {
|
||||
let vc = EmptyVC()
|
||||
vc.title = title
|
||||
present(vc, animated: true, completion: nil)
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
//
|
||||
// TestA.swift
|
||||
// ProHUDExample
|
||||
//
|
||||
// Created by xaoxuu on 2019/7/23.
|
||||
// Copyright © 2019 Titan Studio. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
public class TestA: NSObject {
|
||||
|
||||
class func test1() {
|
||||
print(self, "test1")
|
||||
}
|
||||
class func test2() {
|
||||
print(self, "test2")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
open class TestB: NSObject {
|
||||
|
||||
|
||||
class func test1() {
|
||||
print(self, "test1")
|
||||
}
|
||||
open class func test2() {
|
||||
print(self, "test2")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class TestAA: TestA {
|
||||
|
||||
override class func test2() {
|
||||
print(self, "test2", "override")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestBB: TestB {
|
||||
|
||||
override class func test2() {
|
||||
print(self, "test2", "override")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
//
|
||||
// TestAlertVC.swift
|
||||
// Example
|
||||
//
|
||||
// Created by xaoxuu on 2019/8/12.
|
||||
// Copyright © 2019 Titan Studio. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import ProHUD
|
||||
|
||||
class TestAlertVC: BaseListVC {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
override var titles: [String] {
|
||||
return ["场景:正在同步(超时)", "场景:同步成功", "场景:同步失败和重试"]
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
let row = indexPath.row
|
||||
if row == 0 {
|
||||
func f() {
|
||||
let a = Alert.push(scene: .loading, title: "正在同步", message: "请稍等片刻") { (vm) in
|
||||
vm.identifier = "loading"
|
||||
}
|
||||
a.animate(rotate: true)
|
||||
a.didForceQuit { [weak self] in
|
||||
let t = Toast.push(scene: .loading, title: "正在同步", message: "请稍等片刻(点击展开为Alert)") { (vm) in
|
||||
vm.identifier = "loading"
|
||||
}
|
||||
t.animate(rotate: true)
|
||||
t.didTapped { [weak t] in
|
||||
t?.pop()
|
||||
f()
|
||||
}
|
||||
self?.simulateSync()
|
||||
}
|
||||
simulateSync()
|
||||
}
|
||||
f()
|
||||
} else if row == 1 {
|
||||
Alert.push(scene: .loading, title: "正在同步", message: "请稍等片刻") { (vm) in
|
||||
vm.identifier = "loading"
|
||||
}.animate(rotate: true)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now()+2) {
|
||||
if let a = Alert.get("loading").last {
|
||||
a.update { (vm) in
|
||||
vm.scene = .success
|
||||
vm.title = "同步成功"
|
||||
vm.message = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if row == 2 {
|
||||
Alert.push() { (vm) in
|
||||
vm.identifier = "loading"
|
||||
}
|
||||
func loading() {
|
||||
if let a = Alert.get("loading").last {
|
||||
a.update { (vm) in
|
||||
vm.scene = .loading
|
||||
vm.title = "正在同步"
|
||||
vm.message = "请稍等片刻"
|
||||
vm.remove(action: 0, 1)
|
||||
}
|
||||
a.animate(rotate: true)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now()+2) {
|
||||
a.update { (vm) in
|
||||
vm.scene = .error
|
||||
vm.title = "同步失败"
|
||||
vm.message = "请检查网络是否通畅"
|
||||
vm.add(action: .default, title: "重试") {
|
||||
loading()
|
||||
}
|
||||
vm.add(action: .cancel, title: "取消", handler: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
loading()
|
||||
}
|
||||
}
|
||||
|
||||
func simulateSync() {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 15) {
|
||||
if let t = Alert.get("loading").last {
|
||||
t.update { (vm) in
|
||||
vm.scene = .success
|
||||
vm.title = "同步成功"
|
||||
vm.message = "啊哈哈哈哈哈哈哈哈"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
//
|
||||
// TestGuardVC.swift
|
||||
// Example
|
||||
//
|
||||
// Created by xaoxuu on 2019/8/12.
|
||||
// Copyright © 2019 Titan Studio. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import ProHUD
|
||||
import Inspire
|
||||
|
||||
class TestGuardVC: BaseListVC {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
override var titles: [String] {
|
||||
return ["场景:删除菜单", "场景:升级至专业版", "场景:隐私协议页面"]
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
let row = indexPath.row
|
||||
if row == 0 {
|
||||
Guard.push(to: self.navigationController) { (vm) in
|
||||
let vc = vm.vc
|
||||
vm.add(action: .destructive, title: "删除") {
|
||||
Alert.push(scene: .delete, title: "确认删除", message: "此操作不可撤销") { (vm) in
|
||||
let vc = vm.vc
|
||||
vm.add(action: .destructive, title: "删除") {
|
||||
vc?.pop()
|
||||
}
|
||||
vm.add(action: .cancel, title: "取消", handler: nil)
|
||||
}
|
||||
vc?.pop()
|
||||
}
|
||||
vm.add(action: .cancel, title: "取消", handler: nil)
|
||||
}
|
||||
} else if row == 1 {
|
||||
// 可以通过id来避免重复
|
||||
if Guard.get("pro", from: self.navigationController).count == 0 {
|
||||
Guard.push(to: self.navigationController) { (vm) in
|
||||
let vc = vm.vc
|
||||
vm.identifier = "pro"
|
||||
vm.add(title: "升级至专业版")
|
||||
vm.add(subTitle: "解锁功能")
|
||||
vm.add(message: "功能1功能2...")
|
||||
vm.add(subTitle: "价格")
|
||||
vm.add(message: "只需一次性付费$2999即可永久享用。")
|
||||
vm.add(action: .destructive, title: "购买") { [weak vc] in
|
||||
Alert.push(scene: .confirm, title: "确认购买", message: "一旦购买拒不退款") { (vm) in
|
||||
let vc = vm.vc
|
||||
vm.add(action: .destructive, title: "购买") { [weak vc] in
|
||||
vc?.update({ (vm) in
|
||||
vm.scene = .success
|
||||
vm.title = "购买成功"
|
||||
vm.message = "感谢您的支持"
|
||||
vm.remove(action: 1)
|
||||
vm.update(action: 0, style: .default, title: "我知道了") {
|
||||
vc?.pop()
|
||||
}
|
||||
})
|
||||
}
|
||||
vm.add(action: .cancel, title: "取消", handler: nil)
|
||||
}
|
||||
vc?.pop()
|
||||
}
|
||||
vm.add(action: .cancel, title: "取消", handler: nil)
|
||||
}
|
||||
}
|
||||
|
||||
} else if row == 2 {
|
||||
let g = Guard.push(to: self.navigationController) { (vm) in
|
||||
let vc = vm.vc
|
||||
vc?.isFullScreen = true
|
||||
let titleLabel = vm.add(title: "隐私协议")
|
||||
titleLabel.snp.makeConstraints { (mk) in
|
||||
mk.height.equalTo(44)
|
||||
}
|
||||
let tv = UITextView()
|
||||
tv.backgroundColor = .white
|
||||
vc?.textStack.addArrangedSubview(tv)
|
||||
tv.text = "这里可以插入一个webView"
|
||||
vm.add(message: "请认真阅读以上内容,当您阅读完毕并同意协议内容时点击接受按钮。")
|
||||
|
||||
vm.add(action: .default, title: "接受") { [weak vc] in
|
||||
vc?.pop()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
//
|
||||
// TestToastVC.swift
|
||||
// Example
|
||||
//
|
||||
// Created by xaoxuu on 2019/8/12.
|
||||
// Copyright © 2019 Titan Studio. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import ProHUD
|
||||
|
||||
class TestToastVC: BaseListVC {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
override var titles: [String] {
|
||||
return ["场景:正在同步",
|
||||
"场景:同步成功",
|
||||
"场景:同步失败",
|
||||
"场景:设备电量过低",
|
||||
"传入指定图标",
|
||||
"禁止手势移除",
|
||||
"组合使用示例"]
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
let row = indexPath.row
|
||||
if row == 0 {
|
||||
Toast.push(scene: .loading, title: "正在同步", message: "请稍等片刻") { (vm) in
|
||||
vm.identifier = "loading"
|
||||
}.animate(rotate: true)
|
||||
simulateSync()
|
||||
} else if row == 1 {
|
||||
let t = Toast.push(scene: .success, title: "同步成功", message: "点击查看详情")
|
||||
t.didTapped { [weak self, weak t] in
|
||||
self?.presentEmptyVC(title: "详情")
|
||||
t?.pop()
|
||||
}
|
||||
} else if row == 2 {
|
||||
let t = Toast.push(scene: .error, title: "同步失败", message: "请稍后重试。点击查看详情") { (vm) in
|
||||
vm.duration = 0
|
||||
}
|
||||
t.didTapped { [weak self, weak t] in
|
||||
self?.presentEmptyVC(title: "这是错误详情")
|
||||
t?.pop()
|
||||
}
|
||||
|
||||
} else if row == 3 {
|
||||
Toast.push(scene: .warning, title: "设备电量过低", message: "请及时对设备进行充电,以免影响使用。")
|
||||
|
||||
} else if row == 4 {
|
||||
Toast.push(scene: .default, title: "传入指定图标测试", message: "这是消息内容") { (vm) in
|
||||
vm.icon = UIImage(named: "icon_download")
|
||||
}
|
||||
} else if row == 5 {
|
||||
Toast.push(scene: .default, title: "禁止手势移除", message: "这条消息无法通过向上滑动移出屏幕。5秒后自动消失,每次拖拽都会刷新倒计时。") { (vm) in
|
||||
vm.removable = false
|
||||
vm.duration = 5
|
||||
}
|
||||
} else if row == 6 {
|
||||
let t = Toast.push(scene: .default, title: "好友邀请", message: "你收到一条好友邀请,点击查看详情。", duration: 10)
|
||||
|
||||
t.didTapped { [weak t] in
|
||||
t?.pop()
|
||||
Alert.push(scene: .confirm, title: "好友邀请", message: "用户xxx想要添加你为好友,是否同意?") { (vm) in
|
||||
let vc = vm.vc
|
||||
vm.add(action: .default, title: "接受") {
|
||||
vc?.pop()
|
||||
Toast.push(scene: .success, title: "好友添加成功", message: "这是消息内容")
|
||||
}
|
||||
vm.add(action: .cancel, title: "拒绝") {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func simulateSync() {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
|
||||
if let t = Toast.get("loading").last {
|
||||
t.update { (vm) in
|
||||
vm.scene = .success
|
||||
vm.title = "同步成功"
|
||||
vm.message = "啊哈哈哈哈哈哈哈哈"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -8,8 +8,10 @@
|
|||
|
||||
import UIKit
|
||||
import ProHUD
|
||||
import SnapKit
|
||||
|
||||
class ViewController: BaseListVC {
|
||||
|
||||
class ViewController: UIViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
@ -20,14 +22,17 @@ class ViewController: UIViewController {
|
|||
cfg.rootViewController = self
|
||||
|
||||
cfg.alert { (a) in
|
||||
a.duration = 1
|
||||
|
||||
// a.durationForScene { (s) -> TimeInterval? in
|
||||
// return 1
|
||||
// }
|
||||
a.forceQuitTimer = 3
|
||||
// a.iconSize = .init(width: 20, height: 80)
|
||||
// a.reloadData
|
||||
// a.iconSize = .init(width: 20, height: 80)
|
||||
a.iconForScene { (s) -> UIImage? in
|
||||
return UIImage(named: "icon_download")
|
||||
}
|
||||
// a.iconForScene { (s) -> UIImage? in
|
||||
// return UIImage(named: "icon_download")
|
||||
// }
|
||||
|
||||
}
|
||||
cfg.toast { (t) in
|
||||
|
@ -39,15 +44,21 @@ class ViewController: UIViewController {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
override var titles: [String] {
|
||||
return ["Toast", "Alert", "Guard"]
|
||||
}
|
||||
|
||||
@IBAction func test(_ sender: UIButton) {
|
||||
// testAlert()
|
||||
testToast()
|
||||
// testUpdateAction()
|
||||
// testGuard()
|
||||
// fastGuard()
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
if indexPath.row == 0 {
|
||||
navigationController?.pushViewController(TestToastVC(), animated: true)
|
||||
} else if indexPath.row == 1 {
|
||||
navigationController?.pushViewController(TestAlertVC(), animated: true)
|
||||
} else {
|
||||
navigationController?.pushViewController(TestGuardVC(), animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
func testAlert() {
|
||||
|
@ -59,53 +70,6 @@ class ViewController: UIViewController {
|
|||
vm.add(action: .default, title: "OK", handler: nil)
|
||||
|
||||
}
|
||||
// a.update()
|
||||
// Alert.push(scene: .loading, title: "Loading") { (a) in
|
||||
// a.animate(rotate: true)
|
||||
// DispatchQueue.main.asyncAfter(deadline: .now()+1) {
|
||||
// a.update { (vm) in
|
||||
// vm.message = "请稍后片刻"
|
||||
// }
|
||||
// a.animate(rotate: true)
|
||||
// }
|
||||
// DispatchQueue.main.asyncAfter(deadline: .now()+2) {
|
||||
// a.update { (vm) in
|
||||
// vm.message = "请稍后片刻请稍后片刻"
|
||||
// }
|
||||
// a.animate(rotate: true)
|
||||
// }
|
||||
// DispatchQueue.main.asyncAfter(deadline: .now()+3) {
|
||||
// a.update { (vm) in
|
||||
// vm.scene = .success
|
||||
// vm.add(action: .default, title: "OK") { [weak a] in
|
||||
// a?.pop()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// DispatchQueue.main.asyncAfter(deadline: .now()+4) {
|
||||
// a.update { (vm) in
|
||||
// vm.update(action: 0, style: .cancel, title: "Cancel", handler: nil)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Alert.push(scene: .delete, title: "确认删除", message: "此操作不可撤销!此操作不可撤销!此操作不可撤销!") { (a) in
|
||||
// a.identifier = ""
|
||||
// DispatchQueue.main.asyncAfter(deadline: .now()+1) {
|
||||
// a.update { (vm) in
|
||||
// vm.add(action: .destructive, title: "确认") { [weak a] in
|
||||
// a?.update({ (vm) in
|
||||
// vm.message = "但是饭撒 打算放过"
|
||||
// vm.remove(action: 1)
|
||||
// vm.update(action: 0, style: .destructive, title: "确认", handler: {
|
||||
// a?.pop()
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
// vm.add(action: .cancel, title: "取消", handler: nil)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
func testDelete() {
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 493 KiB |
|
@ -11,7 +11,7 @@ import SnapKit
|
|||
import Inspire
|
||||
|
||||
public extension ProHUD.Configuration {
|
||||
class Alert {
|
||||
struct Alert {
|
||||
// MARK: 卡片样式
|
||||
/// 最大宽度(用于优化横屏或者iPad显示)
|
||||
public var maxWidth = CGFloat(400)
|
||||
|
@ -59,8 +59,10 @@ public extension ProHUD.Configuration {
|
|||
privReloadData = callback
|
||||
}
|
||||
|
||||
/// 非Loading弹窗的默认持续时间
|
||||
public var duration = TimeInterval(2)
|
||||
/// 默认持续时间(当viewmodel的duration为nil时,会从这里获取)
|
||||
public func durationForScene(_ callback: @escaping (ProHUD.Alert.Scene) -> TimeInterval?) {
|
||||
privDurationForScene = callback
|
||||
}
|
||||
|
||||
/// 多少秒后显示强制退出的按钮(只有无按钮的弹窗才会出现)
|
||||
public var forceQuitTimer = TimeInterval(30)
|
||||
|
@ -81,9 +83,15 @@ public extension ProHUD.Configuration {
|
|||
|
||||
// MARK: - 内部调用
|
||||
internal extension ProHUD.Configuration.Alert {
|
||||
|
||||
var reloadData: (ProHUD.Alert) -> Void {
|
||||
return privReloadData
|
||||
}
|
||||
|
||||
var durationForScene: (ProHUD.Alert.Scene) -> TimeInterval? {
|
||||
return privDurationForScene
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -233,11 +241,11 @@ fileprivate var privUpdateTextStack: (ProHUD.Alert) -> Void = {
|
|||
fileprivate var privUpdateActionStack: (ProHUD.Alert) -> Void = {
|
||||
return { (vc) in
|
||||
let config = cfg.alert
|
||||
if vc.buttonEvents.count > 0 {
|
||||
if vc.actionStack.arrangedSubviews.count > 0 {
|
||||
// 有按钮
|
||||
vc.contentStack.addArrangedSubview(vc.actionStack)
|
||||
// 适配横竖屏和iPad
|
||||
if isPortrait == false && vc.buttonEvents.count < 4 {
|
||||
if isPortrait == false && vc.actionStack.arrangedSubviews.count < 4 {
|
||||
vc.actionStack.axis = .horizontal
|
||||
vc.actionStack.alignment = .fill
|
||||
vc.actionStack.distribution = .fillEqually
|
||||
|
@ -332,14 +340,8 @@ fileprivate var privReloadData: (ProHUD.Alert) -> Void = {
|
|||
}
|
||||
}
|
||||
|
||||
// 设置默认持续时间
|
||||
if vc.vm.duration == nil {
|
||||
if vc.vm.scene == .loading {
|
||||
vc.vm.duration = 0
|
||||
} else {
|
||||
vc.vm.duration = config.duration
|
||||
}
|
||||
}
|
||||
// 设置持续时间
|
||||
vc.vm.updateDuration()
|
||||
|
||||
// 强制退出按钮
|
||||
vc.vm.forceQuitTimerBlock?.cancel()
|
||||
|
@ -358,3 +360,15 @@ fileprivate var privReloadData: (ProHUD.Alert) -> Void = {
|
|||
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
fileprivate var privDurationForScene: (ProHUD.Alert.Scene) -> TimeInterval? = {
|
||||
return { (scene) in
|
||||
switch scene {
|
||||
case .loading:
|
||||
return nil
|
||||
default:
|
||||
return 2
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
|
|
@ -125,7 +125,9 @@ public extension Alert {
|
|||
UIView.animateForAlertBuildOut(animations: {
|
||||
window.backgroundColor = window.backgroundColor?.withAlphaComponent(0)
|
||||
}) { (done) in
|
||||
Alert.alertWindow = nil
|
||||
if Alert.alerts.count == 0 {
|
||||
Alert.alertWindow = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -178,13 +180,13 @@ public extension Alert {
|
|||
/// - Parameter title: 标题
|
||||
/// - Parameter message: 正文
|
||||
/// - Parameter actions: 更多操作
|
||||
@discardableResult class func push(scene: Alert.Scene = .default, title: String? = nil, message: String? = nil, actions: ((inout ViewModel) -> Void)? = nil) -> Alert {
|
||||
@discardableResult class func push(scene: Alert.Scene = .default, title: String? = nil, message: String? = nil, _ actions: ((inout ViewModel) -> Void)? = nil) -> Alert {
|
||||
return Alert(scene: scene, title: title, message: message, actions: actions).push()
|
||||
}
|
||||
|
||||
/// 获取指定的实例
|
||||
/// - Parameter identifier: 指定实例的标识
|
||||
class func alerts(_ identifier: String?) -> [Alert] {
|
||||
class func get(_ identifier: String?) -> [Alert] {
|
||||
var aa = [Alert]()
|
||||
for a in Alert.alerts {
|
||||
if a.vm.identifier == identifier {
|
||||
|
@ -203,7 +205,7 @@ public extension Alert {
|
|||
/// 弹出屏幕
|
||||
/// - Parameter identifier: 指定实例的标识
|
||||
class func pop(_ identifier: String?) {
|
||||
for a in alerts(identifier) {
|
||||
for a in get(identifier) {
|
||||
a.pop()
|
||||
}
|
||||
}
|
||||
|
@ -271,10 +273,16 @@ internal extension Alert {
|
|||
for view in self.actionStack.arrangedSubviews {
|
||||
if let btn = view as? UIButton {
|
||||
btn.removeFromSuperview()
|
||||
if let _ = buttonEvents[btn] {
|
||||
buttonEvents.removeValue(forKey: btn)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if index < self.actionStack.arrangedSubviews.count, let btn = self.actionStack.arrangedSubviews[index] as? UIButton {
|
||||
btn.removeFromSuperview()
|
||||
if let _ = buttonEvents[btn] {
|
||||
buttonEvents.removeValue(forKey: btn)
|
||||
}
|
||||
}
|
||||
if self.actionStack.arrangedSubviews.count == 0 {
|
||||
self.actionStack.removeFromSuperview()
|
||||
|
|
|
@ -65,15 +65,7 @@ public extension Alert {
|
|||
/// 持续时间(为空代表根据场景不同的默认配置,为0代表无穷大)
|
||||
public var duration: TimeInterval? {
|
||||
didSet {
|
||||
durationBlock?.cancel()
|
||||
if let t = duration, t > 0 {
|
||||
durationBlock = DispatchWorkItem(block: { [weak self] in
|
||||
self?.vc?.pop()
|
||||
})
|
||||
DispatchQueue.main.asyncAfter(deadline: .now()+t, execute: durationBlock!)
|
||||
} else {
|
||||
durationBlock = nil
|
||||
}
|
||||
updateDuration()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,6 +82,18 @@ public extension Alert {
|
|||
/// 强制退出代码
|
||||
internal var forceQuitCallback: (() -> Void)?
|
||||
|
||||
internal func updateDuration() {
|
||||
durationBlock?.cancel()
|
||||
if let t = duration ?? cfg.alert.durationForScene(scene), t > 0 {
|
||||
durationBlock = DispatchWorkItem(block: { [weak self] in
|
||||
self?.vc?.pop()
|
||||
})
|
||||
DispatchQueue.main.asyncAfter(deadline: .now()+t, execute: durationBlock!)
|
||||
} else {
|
||||
durationBlock = nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -97,6 +97,9 @@ fileprivate var privReloadData: (ProHUD.Guard) -> Void = {
|
|||
vc.contentView.layer.shadowOpacity = 0.12
|
||||
}
|
||||
vc.contentView.snp.makeConstraints { (mk) in
|
||||
if isPortrait && vc.isFullScreen {
|
||||
mk.top.equalToSuperview()
|
||||
}
|
||||
mk.centerX.equalToSuperview()
|
||||
if UIDevice.current.userInterfaceIdiom == .phone {
|
||||
if width < config.cardMaxWidth {
|
||||
|
@ -111,7 +114,11 @@ fileprivate var privReloadData: (ProHUD.Guard) -> Void = {
|
|||
}
|
||||
// stack
|
||||
vc.contentStack.snp.makeConstraints { (mk) in
|
||||
mk.top.equalToSuperview().offset(config.padding)
|
||||
if isPortrait && vc.isFullScreen {
|
||||
mk.top.equalToSuperview().offset(Inspire.shared.screen.safeAreaInsets.top)
|
||||
} else {
|
||||
mk.top.equalToSuperview().offset(config.padding)
|
||||
}
|
||||
mk.centerX.equalToSuperview()
|
||||
if width < config.cardMaxWidth {
|
||||
let bottom = Inspire.shared.screen.safeAreaInsets.bottom
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//
|
||||
|
||||
import SnapKit
|
||||
import Inspire
|
||||
|
||||
public typealias Guard = ProHUD.Guard
|
||||
|
||||
|
@ -44,11 +45,14 @@ public extension ProHUD {
|
|||
/// 是否是强制性的(点击空白处是否可以消失)
|
||||
public var force = false
|
||||
|
||||
/// 是否是全屏的(仅手机竖屏有效)
|
||||
public var isFullScreen = false
|
||||
|
||||
/// 是否正在显示
|
||||
private var displaying = false
|
||||
|
||||
/// 背景颜色
|
||||
public var backgroundColor: UIColor? = UIColor(white: 0, alpha: 0.5)
|
||||
public var backgroundColor: UIColor? = UIColor(white: 0, alpha: 0.4)
|
||||
|
||||
public var vm = ViewModel()
|
||||
|
||||
|
@ -142,7 +146,9 @@ public extension Guard {
|
|||
cfg.guard.reloadData(self)
|
||||
}
|
||||
|
||||
|
||||
func willAppear(_ callback: (() -> Void)?) {
|
||||
willAppearCallback = callback
|
||||
}
|
||||
/// 消失事件
|
||||
/// - Parameter callback: 事件回调
|
||||
func didDisappear(_ callback: (() -> Void)?) {
|
||||
|
@ -159,13 +165,13 @@ public extension Guard {
|
|||
/// - Parameter title: 标题
|
||||
/// - Parameter message: 正文
|
||||
/// - Parameter icon: 图标
|
||||
@discardableResult class func push(to viewController: UIViewController? = nil, actions: ((inout ViewModel) -> Void)? = nil) -> Guard {
|
||||
@discardableResult class func push(to viewController: UIViewController? = nil, _ actions: ((inout ViewModel) -> Void)? = nil) -> Guard {
|
||||
return Guard(actions: actions).push(to: viewController)
|
||||
}
|
||||
|
||||
/// 获取指定的实例
|
||||
/// - Parameter identifier: 指定实例的标识
|
||||
class func guards(_ identifier: String? = nil, from viewController: UIViewController? = nil) -> [Guard] {
|
||||
class func get(_ identifier: String? = nil, from viewController: UIViewController? = nil) -> [Guard] {
|
||||
var gg = [Guard]()
|
||||
if let vc = viewController ?? cfg.rootViewController {
|
||||
for child in vc.children {
|
||||
|
@ -194,7 +200,7 @@ public extension Guard {
|
|||
/// 弹出所有实例
|
||||
/// - Parameter identifier: 指定实例的标识
|
||||
class func pop(from viewController: UIViewController?) {
|
||||
for g in guards(from: viewController) {
|
||||
for g in get(from: viewController) {
|
||||
g.pop()
|
||||
}
|
||||
}
|
||||
|
@ -304,10 +310,16 @@ internal extension Guard {
|
|||
for view in self.actionStack.arrangedSubviews {
|
||||
if let btn = view as? UIButton {
|
||||
btn.removeFromSuperview()
|
||||
if let _ = buttonEvents[btn] {
|
||||
buttonEvents.removeValue(forKey: btn)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if index < self.actionStack.arrangedSubviews.count, let btn = self.actionStack.arrangedSubviews[index] as? UIButton {
|
||||
btn.removeFromSuperview()
|
||||
if let _ = buttonEvents[btn] {
|
||||
buttonEvents.removeValue(forKey: btn)
|
||||
}
|
||||
}
|
||||
cfg.guard.reloadStack(self)
|
||||
UIView.animateForAlert {
|
||||
|
|
|
@ -13,6 +13,8 @@ public class HUDController: UIViewController {
|
|||
/// 消失回调
|
||||
internal var disappearCallback: (() -> Void)?
|
||||
|
||||
internal var willAppearCallback: (() -> Void)?
|
||||
|
||||
/// 按钮事件
|
||||
internal var buttonEvents = [UIButton:() -> Void]()
|
||||
|
||||
|
@ -36,6 +38,11 @@ public class HUDController: UIViewController {
|
|||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
public override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
willAppearCallback?()
|
||||
}
|
||||
|
||||
public override func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
disappearCallback?()
|
||||
|
|
|
@ -46,8 +46,10 @@ public extension ProHUD.Configuration {
|
|||
privReloadData = callback
|
||||
}
|
||||
|
||||
/// 非Loading弹窗的默认持续时间
|
||||
public var duration = TimeInterval(3)
|
||||
/// 默认持续时间(当viewmodel的duration为nil时,会从这里获取)
|
||||
public mutating func durationForScene(_ callback: @escaping (ProHUD.Toast.Scene) -> TimeInterval?) {
|
||||
privDurationForScene = callback
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +62,10 @@ internal extension ProHUD.Configuration.Toast {
|
|||
return privReloadData
|
||||
}
|
||||
|
||||
var durationForScene: (ProHUD.Toast.Scene) -> TimeInterval? {
|
||||
return privDurationForScene
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - 默认实现
|
||||
|
@ -79,6 +85,7 @@ fileprivate var privReloadData: (ProHUD.Toast) -> Void = {
|
|||
}
|
||||
// 设置数据
|
||||
vc.imageView.image = vc.vm.icon ?? privIconForScene(vc.vm.scene)
|
||||
vc.imageView.layer.removeAllAnimations()
|
||||
vc.titleLabel.textColor = cfg.primaryLabelColor
|
||||
vc.titleLabel.text = vc.vm.title
|
||||
vc.bodyLabel.textColor = cfg.secondaryLabelColor
|
||||
|
@ -104,14 +111,10 @@ fileprivate var privReloadData: (ProHUD.Toast) -> Void = {
|
|||
}
|
||||
|
||||
vc.view.layoutIfNeeded()
|
||||
// 设置默认持续时间
|
||||
if vc.vm.duration == nil {
|
||||
if vc.vm.scene == .loading {
|
||||
vc.vm.duration = 0
|
||||
} else {
|
||||
vc.vm.duration = config.duration
|
||||
}
|
||||
}
|
||||
|
||||
// 设置持续时间
|
||||
vc.vm.updateDuration()
|
||||
|
||||
}
|
||||
|
||||
}()
|
||||
|
@ -136,3 +139,17 @@ fileprivate var privIconForScene: (ProHUD.Toast.Scene) -> UIImage? = {
|
|||
return ProHUD.image(named: imgStr)
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
fileprivate var privDurationForScene: (ProHUD.Toast.Scene) -> TimeInterval? = {
|
||||
return { (scene) in
|
||||
switch scene {
|
||||
case .loading:
|
||||
return nil
|
||||
case .error, .warning:
|
||||
return 5
|
||||
default:
|
||||
return 3
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
|
|
@ -65,7 +65,7 @@ public extension ProHUD {
|
|||
/// - Parameter title: 标题
|
||||
/// - Parameter message: 内容
|
||||
/// - Parameter icon: 图标
|
||||
public convenience init(scene: Scene = .default, title: String? = nil, message: String? = nil, icon: UIImage? = nil, actions: ((inout ViewModel) -> Void)? = nil) {
|
||||
public convenience init(scene: Scene = .default, title: String? = nil, message: String? = nil, icon: UIImage? = nil, duration: TimeInterval? = nil, actions: ((inout ViewModel) -> Void)? = nil) {
|
||||
self.init()
|
||||
vm.vc = self
|
||||
|
||||
|
@ -73,6 +73,7 @@ public extension ProHUD {
|
|||
vm.title = title
|
||||
vm.message = message
|
||||
vm.icon = icon
|
||||
vm.duration = duration
|
||||
actions?(&vm)
|
||||
|
||||
// 点击
|
||||
|
@ -180,6 +181,20 @@ public extension Toast {
|
|||
return self
|
||||
}
|
||||
|
||||
func animate(rotate: Bool) {
|
||||
if rotate {
|
||||
DispatchQueue.main.async {
|
||||
let ani = CABasicAnimation(keyPath: "transform.rotation.z")
|
||||
ani.toValue = Double.pi * 2.0
|
||||
ani.duration = 3
|
||||
ani.repeatCount = 10000
|
||||
self.imageView.layer.add(ani, forKey: "rotationAnimation")
|
||||
}
|
||||
} else {
|
||||
imageView.layer.removeAllAnimations()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -191,13 +206,13 @@ public extension Toast {
|
|||
/// - Parameter title: 标题
|
||||
/// - Parameter message: 内容
|
||||
/// - Parameter actions: 更多操作
|
||||
@discardableResult class func push(scene: Toast.Scene = .default, title: String? = nil, message: String? = nil, actions: ((inout ViewModel) -> Void)? = nil) -> Toast {
|
||||
return Toast(scene: scene, title: title, message: message, actions: actions).push()
|
||||
@discardableResult class func push(scene: Toast.Scene = .default, title: String? = nil, message: String? = nil, duration: TimeInterval? = nil, _ actions: ((inout ViewModel) -> Void)? = nil) -> Toast {
|
||||
return Toast(scene: scene, title: title, message: message, duration: duration, actions: actions).push()
|
||||
}
|
||||
|
||||
/// 获取指定的toast
|
||||
/// - Parameter identifier: 标识
|
||||
class func toasts(_ identifier: String?) -> [Toast] {
|
||||
class func get(_ identifier: String?) -> [Toast] {
|
||||
var tt = [Toast]()
|
||||
for t in toasts {
|
||||
if t.vm.identifier == identifier {
|
||||
|
@ -234,7 +249,7 @@ public extension Toast {
|
|||
/// 弹出屏幕
|
||||
/// - Parameter identifier: 指定实例的标识
|
||||
class func pop(_ identifier: String?) {
|
||||
for t in toasts(identifier) {
|
||||
for t in get(identifier) {
|
||||
t.pop()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,15 +59,7 @@ public extension Toast {
|
|||
/// 持续时间
|
||||
public var duration: TimeInterval? {
|
||||
didSet {
|
||||
durationBlock?.cancel()
|
||||
if let t = duration, t > 0 {
|
||||
durationBlock = DispatchWorkItem(block: { [weak self] in
|
||||
self?.vc?.pop()
|
||||
})
|
||||
DispatchQueue.main.asyncAfter(deadline: .now()+t, execute: durationBlock!)
|
||||
} else {
|
||||
durationBlock = nil
|
||||
}
|
||||
updateDuration()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,6 +77,17 @@ public extension Toast {
|
|||
/// 点击事件回调
|
||||
internal var tapCallback: (() -> Void)?
|
||||
|
||||
internal func updateDuration() {
|
||||
durationBlock?.cancel()
|
||||
if let t = duration ?? cfg.toast.durationForScene(scene), t > 0 {
|
||||
durationBlock = DispatchWorkItem(block: { [weak self] in
|
||||
self?.vc?.pop()
|
||||
})
|
||||
DispatchQueue.main.asyncAfter(deadline: .now()+t, execute: durationBlock!)
|
||||
} else {
|
||||
durationBlock = nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue