├── .swift-version
├── gifs
├── mmsharesheet_1.gif
├── mmsharesheet_2.gif
├── mmsharesheet_3.gif
└── mmsharesheet_4.gif
├── swiftui
├── Assets.xcassets
│ ├── Contents.json
│ ├── qq.imageset
│ │ ├── qq.png
│ │ └── Contents.json
│ ├── icon.imageset
│ │ ├── icon.png
│ │ └── Contents.json
│ ├── sina.imageset
│ │ ├── sina.png
│ │ └── Contents.json
│ ├── jubao.imageset
│ │ ├── jubao.png
│ │ └── Contents.json
│ ├── airpay.imageset
│ │ ├── airpay.png
│ │ └── Contents.json
│ ├── moment.imageset
│ │ ├── moment.png
│ │ └── Contents.json
│ ├── safari.imageset
│ │ ├── safari.png
│ │ └── Contents.json
│ ├── wechat.imageset
│ │ ├── wechat.png
│ │ └── Contents.json
│ ├── copy_link.imageset
│ │ ├── copy_link.png
│ │ └── Contents.json
│ ├── collection.imageset
│ │ ├── collection.png
│ │ └── Contents.json
│ ├── refresh_icon.imageset
│ │ ├── refresh_icon.png
│ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Info.plist
├── AppDelegate.swift
└── Base.lproj
│ └── LaunchScreen.storyboard
├── swiftui.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── project.pbxproj
├── .gitignore
├── MMShareSheet.podspec
├── LICENSE
├── Components
├── MMCardItem.swift
└── MMShareSheet.swift
├── README.md
├── Example
├── ExampleShareSheetVC.swift
└── Example.storyboard
└── Tools
└── SwiftNotice.swift
/.swift-version:
--------------------------------------------------------------------------------
1 | 3.0
2 |
--------------------------------------------------------------------------------
/gifs/mmsharesheet_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MinMao-Hub/MMShareSheet/HEAD/gifs/mmsharesheet_1.gif
--------------------------------------------------------------------------------
/gifs/mmsharesheet_2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MinMao-Hub/MMShareSheet/HEAD/gifs/mmsharesheet_2.gif
--------------------------------------------------------------------------------
/gifs/mmsharesheet_3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MinMao-Hub/MMShareSheet/HEAD/gifs/mmsharesheet_3.gif
--------------------------------------------------------------------------------
/gifs/mmsharesheet_4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MinMao-Hub/MMShareSheet/HEAD/gifs/mmsharesheet_4.gif
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/qq.imageset/qq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MinMao-Hub/MMShareSheet/HEAD/swiftui/Assets.xcassets/qq.imageset/qq.png
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/icon.imageset/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MinMao-Hub/MMShareSheet/HEAD/swiftui/Assets.xcassets/icon.imageset/icon.png
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/sina.imageset/sina.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MinMao-Hub/MMShareSheet/HEAD/swiftui/Assets.xcassets/sina.imageset/sina.png
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/jubao.imageset/jubao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MinMao-Hub/MMShareSheet/HEAD/swiftui/Assets.xcassets/jubao.imageset/jubao.png
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/airpay.imageset/airpay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MinMao-Hub/MMShareSheet/HEAD/swiftui/Assets.xcassets/airpay.imageset/airpay.png
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/moment.imageset/moment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MinMao-Hub/MMShareSheet/HEAD/swiftui/Assets.xcassets/moment.imageset/moment.png
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/safari.imageset/safari.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MinMao-Hub/MMShareSheet/HEAD/swiftui/Assets.xcassets/safari.imageset/safari.png
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/wechat.imageset/wechat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MinMao-Hub/MMShareSheet/HEAD/swiftui/Assets.xcassets/wechat.imageset/wechat.png
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/copy_link.imageset/copy_link.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MinMao-Hub/MMShareSheet/HEAD/swiftui/Assets.xcassets/copy_link.imageset/copy_link.png
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/collection.imageset/collection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MinMao-Hub/MMShareSheet/HEAD/swiftui/Assets.xcassets/collection.imageset/collection.png
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/refresh_icon.imageset/refresh_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MinMao-Hub/MMShareSheet/HEAD/swiftui/Assets.xcassets/refresh_icon.imageset/refresh_icon.png
--------------------------------------------------------------------------------
/swiftui.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | swiftui.xcodeproj/project.xcworkspace/xcuserdata
3 | swiftui.xcodeproj/project.xcworkspace/xcshareddata
4 | swiftui.xcworkspace/xcuserdata/
5 | swiftui.xcworkspace/xcshareddata/
6 | swiftui.xcodeproj/xcshareddata/
7 | swiftui.xcodeproj/xcuserdata/
8 |
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "icon.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/qq.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "qq.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/sina.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "sina.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/airpay.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "airpay.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/jubao.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "jubao.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/moment.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "moment.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/safari.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "safari.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/wechat.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "wechat.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/copy_link.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "copy_link.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/collection.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "collection.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/refresh_icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "refresh_icon.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/MMShareSheet.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 |
3 | s.name = "MMShareSheet"
4 | s.version = "0.0.3"
5 | s.summary = "MMShareSheet is an simple pop-up selection box(ShareSheet) written in pure Swift"
6 | s.homepage = "https://github.com/MinMao-Hub"
7 | s.license = "MIT"
8 | s.author = { "gyh" => "m12860gyh@gmail.com" }
9 | s.platform = :ios, "8.0"
10 | s.source = { :git => "https://github.com/MinMao-Hub/MMShareSheet.git", :tag => "#{s.version}" }
11 | s.source_files = "Components"
12 | end
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 小冒
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/swiftui/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Example
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 | NSAppTransportSecurity
45 |
46 | NSAllowsArbitraryLoads
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/swiftui/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/swiftui/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // swiftui
4 | //
5 | // Created by 郭永红 on 2017/10/12.
6 | // Copyright © 2017年 keeponrunning. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/Components/MMCardItem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MMCardItem.swift
3 | // swiftui
4 | //
5 | // Created by 郭永红 on 2017/10/12.
6 | // Copyright © 2017年 keeponrunning. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | let mm_itemWidth:CGFloat = 60.0 * ss_mmscreenWidth / 375 /* item的宽高 */
12 | let mm_itemPadding:CGFloat = 8.0 * ss_mmscreenWidth / 375 /* item距离顶部的距离 */
13 | let mm_titlePadding:CGFloat = 5.0 * ss_mmscreenWidth / 375 /* item距离顶部的距离 */
14 | public class MMCardItem: UIView {
15 |
16 | var icon: String?
17 | var title: String?
18 | var handler: String?
19 | var callBack:ItemClickBlock?
20 |
21 | public override init(frame: CGRect) {
22 | super.init(frame: frame)
23 | }
24 |
25 | required public init?(coder aDecoder: NSCoder) {
26 | fatalError("init(coder:) has not been implemented")
27 | }
28 |
29 | convenience public init(frame: CGRect,props: Dictionary?, callback: @escaping ItemClickBlock) {
30 | self.init(frame: frame)
31 | self.title = props?["title"] ?? ""
32 | self.icon = props?["icon"] ?? ""
33 | self.handler = props?["handler"] ?? ""
34 | self.callBack = callback
35 | initUI()
36 |
37 | }
38 |
39 | func initUI() {
40 |
41 | let button = UIButton.init(type: .custom)
42 | button.frame = CGRect.init(x: (self.bounds.size.width - mm_itemWidth) / 2, y: mm_itemPadding, width: mm_itemWidth, height: mm_itemWidth)
43 |
44 | var imageNormal:UIImage? = nil
45 |
46 | DispatchQueue.global().async {
47 | if self.icon != "" {
48 | if (self.icon?.hasPrefix("http"))! {
49 | do {
50 | let imgData = try Data.init(contentsOf: URL.init(string: self.icon!)!)
51 | imageNormal = UIImage.init(data: imgData, scale: UIScreen.main.scale)
52 | } catch {
53 | //Handle exception
54 | }
55 | } else {
56 | imageNormal = UIImage.init(named: self.icon!)
57 | }
58 | }
59 |
60 | DispatchQueue.main.async {
61 | button.setBackgroundImage(imageNormal, for: .normal)
62 | }
63 | }
64 |
65 | button.addTarget(self, action: #selector(self.itemClick), for: .touchUpInside)
66 |
67 | self.addSubview(button)
68 |
69 | if (self.title != nil && self.title != "") {
70 | let titlelabel = UILabel.init(frame: CGRect.init(x: 0, y: mm_itemWidth + mm_itemPadding + mm_titlePadding, width: self.bounds.size.width, height: 20))
71 | titlelabel.text = self.title
72 | titlelabel.textAlignment = .center
73 | titlelabel.textColor = UIColor(red: 0.365, green: 0.361, blue: 0.357, alpha: 1.00)
74 | titlelabel.font = UIFont.systemFont(ofSize: 12)
75 | titlelabel.backgroundColor = UIColor(red: 0.937, green: 0.937, blue: 0.941, alpha: 0.00)
76 | titlelabel.adjustsFontSizeToFitWidth = true
77 | self.addSubview(titlelabel)
78 | }
79 | }
80 |
81 | @objc func itemClick(button:UIButton) {
82 | if (self.callBack != nil) {
83 | self.callBack!(self.handler!)
84 | }
85 | }
86 |
87 | public override func layoutSubviews() {
88 | super.layoutSubviews()
89 |
90 | self.backgroundColor = UIColor(red: 0.937, green: 0.937, blue: 0.941, alpha: 0.90).withAlphaComponent(0.0)
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/swiftui/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | MarkerFelt-Wide
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | ## MMShareSheet
3 |
4 |
5 | [](https://cocoapods.org/pods/MMShareSheet)
6 | [](https://github.com/MinMao-Hub/MMShareSheet)
7 | [](https://cocoapods.org/pods/MMShareSheet)
8 | [](https://github.com/MinMao-Hub/MMShareSheet)
9 | [](http://opensource.org/licenses/MIT)
10 |
11 | ### Introduction
12 |
13 | MMShareSheet 是一个简单的弹出选择框,使用纯swift编写,类似于微信(或支付宝)里面的分享(朋友圈打开网页右上角分享)控件
14 |
15 | MMShareSheet is an simple pop-up selection box(ShareSheet) written in pure Swift. Similar to the wechat(or airpay) actionsheet share-UIKit
16 |
17 | ### Rquirements
18 |
19 | * iOS 8.0+
20 | * Xcode 9 (swift 4)
21 | * Xcode 8 (swift 3)
22 | * If you want to run demo in swift3, please switch branch to swift3.0
23 |
24 | ### Installation
25 |
26 |
27 | #### Install with Cocoapods
28 |
29 | * `pod 'MMShareSheet', '~> 0.0'`
30 | * `import MMShareSheet ` in you code
31 |
32 |
33 | #### Copy code into project
34 |
35 | [克隆代码](https://github.com/MinMao-Hub/MMShareSheet.git),然后将components文件夹下面的两个文件 `MMShareSheet.swift` 和 `MMCardItem.swift`加入到你的项目中即可。
36 |
37 | Just clone and add `MMShareSheet.swift`, `MMCardItem.swift` to your project.
38 |
39 | ### Example
40 |
41 | > 1. 【类似于微信分享】- Similar to WeChat share
42 | >
43 | > 2. 【单组cards】- Single group cards(显示组数完全取决于传入的cards数组)
44 | >
45 | > 3. 【多组cards】- Multi group cards
46 | >
47 | > 4. 【支持远程icon】- Support remote Icon
48 |
49 |
50 |

51 |

52 |
53 |
54 |

55 |

56 |
57 |
58 |
59 | ### Usage
60 |
61 | ```swift
62 | let cards = [
63 | [
64 | [
65 | "title": "微信好友",
66 | "icon": "wechat",
67 | "handler": "wxfriend"
68 | ],[
69 | "title": "微信朋友圈",
70 | "icon": "moment",
71 | "handler": "wxmoment"
72 | ],[
73 | "title": "QQ好友",
74 | "icon": "qq",
75 | "handler": "qqfriend",
76 | ],[
77 | "title": "支付宝",
78 | "icon": "airpay",
79 | "handler": "airpay",
80 | ],[
81 | "title": "新浪微博",
82 | "icon": "sina",
83 | "handler": "sinawb",
84 | ]
85 | ],[
86 | [
87 | "title": "拷贝",
88 | "icon": "copy_link",
89 | "handler": "copy"
90 | ],[
91 | "title": "在Safari中打开",
92 | "icon": "safari",
93 | "handler": "safari"
94 | ],[
95 | "title": "收藏",
96 | "icon": "collection",
97 | "handler": "collect",
98 | ],[
99 | "title": "刷新",
100 | "icon": "refresh_icon",
101 | "handler": "refresh",
102 | ],[
103 | "title": "举报",
104 | "icon": "jubao",
105 | "handler": "report",
106 | ]
107 | ]
108 | ]
109 |
110 | let cancelBtn = [
111 | "title": "取消",
112 | "handler": "cancel",
113 | "type": "default",
114 | ]
115 | let mmShareSheet = MMShareSheet.init(title: "此网页由wx.keeponrunning.com提供", cards: cards, duration: nil, cancelBtn: cancelBtn)
116 | mmShareSheet.callBack = { (handler) ->() in
117 | print(handler)
118 | }
119 | mmShareSheet.present()
120 |
121 | ```
122 |
123 | *PS:注释*
124 |
125 | * create sharesheet && init 【创建并初始化】
126 |
127 | `MMShareSheet.init(title: "此网页由wx.keeponrunning.com提供", cards: cards, duration: nil, cancelBtn: cancelBtn)`
128 |
129 | * argument【参数描述】
130 |
131 | * `title` 头部标题
132 | * `cards ` 事件按钮数组,类型为`Array>>`,里面包含每一行卡片组`Array>`,每一行卡片里面又包含item>:
133 |
134 | ```
135 | [
136 | "title": "拍照",
137 | "icon": "wechat"
138 | "handler": "camera",
139 | ]
140 | ```
141 | * `title` item标题
142 | * `icon ` item图标,可以是本地图片名或者远程图片链接
143 | * `handler` item事件唯一标识,回调的时候根据该值区别处理事件
144 | * `duration ` 动画时长
145 | * `cancelBtn ` 取消按钮属性,类型为``;若设置为`nil`则无该按钮, 必须要设置某一个属性,默认值为`[
146 | "title": "取消", "handler": "cancel","type": "default"]`
147 | * callback【回调】
148 |
149 | ```
150 | mmShareSheet.callBack = { (handler) ->() in
151 | print(handler)
152 | }
153 | ```
154 | `handler` 该handler即为cards里面item的`handler`,对应的回调过来
155 |
156 | * present【弹出sharesheet】
157 |
158 | `mmShareSheet.present()`
159 |
160 | ### Contribution
161 |
162 | You are welcome to fork and submit pull requests.
163 |
164 | ### License
165 |
166 | MMShareSheet is open-sourced software licensed under the MIT license.
167 |
--------------------------------------------------------------------------------
/Example/ExampleShareSheetVC.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExampleShareSheetVC.swift
3 | // swiftui
4 | //
5 | // Created by 郭永红 on 2017/10/12.
6 | // Copyright © 2017年 keeponrunning. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ExampleShareSheetVC: UIViewController {
12 | override func viewDidLoad() {
13 | super.viewDidLoad()
14 |
15 | self.view.backgroundColor = UIColor.white
16 | // Do any additional setup after loading the view.
17 | }
18 |
19 | @IBAction func presentActionSheet(_ sender: Any) {
20 | let cards = [
21 | [
22 | [
23 | "title": "微信好友",
24 | "icon": "wechat",
25 | "handler": "wxfriend"
26 | ],[
27 | "title": "微信朋友圈",
28 | "icon": "moment",
29 | "handler": "wxmoment"
30 | ],[
31 | "title": "QQ好友",
32 | "icon": "qq",
33 | "handler": "qqfriend",
34 | ],[
35 | "title": "支付宝",
36 | "icon": "airpay",
37 | "handler": "airpay",
38 | ],[
39 | "title": "新浪微博",
40 | "icon": "sina",
41 | "handler": "sinawb",
42 | ],[
43 | "title": "微信好友",
44 | "icon": "wechat",
45 | "handler": "wxfriend"
46 | ],[
47 | "title": "微信朋友圈",
48 | "icon": "moment",
49 | "handler": "wxmoment"
50 | ]
51 | ],[
52 | [
53 | "title": "拷贝",
54 | "icon": "copy_link",
55 | "handler": "copy"
56 | ],[
57 | "title": "在Safari中打开",
58 | "icon": "safari",
59 | "handler": "safari"
60 | ],[
61 | "title": "收藏",
62 | "icon": "collection",
63 | "handler": "collect",
64 | ],[
65 | "title": "刷新",
66 | "icon": "refresh_icon",
67 | "handler": "refresh",
68 | ],[
69 | "title": "举报",
70 | "icon": "jubao",
71 | "handler": "report",
72 | ]
73 | ]
74 | ]
75 |
76 | let cancelBtn = [
77 | "title": "取消",
78 | ]
79 | let mmShareSheet = MMShareSheet.init(title: "此网页由wx.keeponrunning.com提供", cards: cards, duration: nil, cancelBtn: cancelBtn)
80 | mmShareSheet.callBack = { (handler) ->() in
81 | self.noticeOnlyText(handler)
82 | }
83 | mmShareSheet.present()
84 | }
85 |
86 |
87 | @IBAction func singleLineShareSheet(_ sender: Any) {
88 | let cards = [
89 | [
90 | [
91 | "title": "微信好友",
92 | "icon": "wechat",
93 | "handler": "wxfriend"
94 | ],[
95 | "title": "微信朋友圈",
96 | "icon": "moment",
97 | "handler": "wxmoment"
98 | ],[
99 | "title": "QQ好友",
100 | "icon": "qq",
101 | "handler": "qqfriend",
102 | ],[
103 | "title": "支付宝",
104 | "icon": "airpay",
105 | "handler": "airpay",
106 | ]
107 | ]
108 | ]
109 |
110 | let cancelBtn = [
111 | "title": "取消",
112 | "type": "danger"
113 | ]
114 | let mmShareSheet = MMShareSheet.init(title: "分 享", cards: cards, duration: nil, cancelBtn: cancelBtn)
115 | mmShareSheet.callBack = { (handler) ->() in
116 | self.noticeOnlyText(handler)
117 | }
118 | mmShareSheet.present()
119 |
120 | }
121 |
122 |
123 | @IBAction func mutableLineShareSheet(_ sender: Any) {
124 |
125 | let cards = [
126 | [
127 | [
128 | "title": "微信好友",
129 | "icon": "wechat",
130 | "handler": "wxfriend"
131 | ],[
132 | "title": "微信朋友圈",
133 | "icon": "moment",
134 | "handler": "wxmoment"
135 | ],[
136 | "title": "QQ好友",
137 | "icon": "qq",
138 | "handler": "qqfriend",
139 | ],[
140 | "title": "支付宝",
141 | "icon": "airpay",
142 | "handler": "airpay",
143 | ],[
144 | "title": "新浪微博",
145 | "icon": "sina",
146 | "handler": "sinawb",
147 | ],[
148 | "title": "微信好友",
149 | "icon": "wechat",
150 | "handler": "wxfriend"
151 | ],[
152 | "title": "微信朋友圈",
153 | "icon": "moment",
154 | "handler": "wxmoment"
155 | ]
156 | ],[
157 | [
158 | "title": "拷贝",
159 | "icon": "copy_link",
160 | "handler": "copy"
161 | ],[
162 | "title": "在Safari中打开",
163 | "icon": "safari",
164 | "handler": "safari"
165 | ],[
166 | "title": "收藏",
167 | "icon": "collection",
168 | "handler": "collect",
169 | ],[
170 | "title": "刷新",
171 | "icon": "refresh_icon",
172 | "handler": "refresh",
173 | ],[
174 | "title": "举报",
175 | "icon": "jubao",
176 | "handler": "report",
177 | ]
178 | ],
179 | [
180 | [
181 | "title": "微信好友",
182 | "icon": "wechat",
183 | "handler": "wxfriend"
184 | ],[
185 | "title": "微信朋友圈",
186 | "icon": "moment",
187 | "handler": "wxmoment"
188 | ],[
189 | "title": "QQ好友",
190 | "icon": "qq",
191 | "handler": "qqfriend",
192 | ],[
193 | "title": "支付宝",
194 | "icon": "airpay",
195 | "handler": "airpay",
196 | ],[
197 | "title": "新浪微博",
198 | "icon": "sina",
199 | "handler": "sinawb",
200 | ],[
201 | "title": "微信好友",
202 | "icon": "wechat",
203 | "handler": "wxfriend"
204 | ],[
205 | "title": "微信朋友圈",
206 | "icon": "moment",
207 | "handler": "wxmoment"
208 | ]
209 | ]
210 | ]
211 |
212 | let cancelBtn = [
213 | "title": "取消",
214 | "type": "blue"
215 | ]
216 | let mmShareSheet = MMShareSheet.init(title: "分 享", cards: cards, duration: nil, cancelBtn: cancelBtn)
217 | mmShareSheet.callBack = { (handler) ->() in
218 | self.noticeOnlyText(handler)
219 | }
220 | mmShareSheet.present()
221 | }
222 |
223 |
224 | @IBAction func remoteIconShareSheet(_ sender: Any) {
225 | let cards = [
226 | [
227 | [
228 | "title": "银行卡管理",
229 | "icon": "http://dsposweb.oss-cn-hangzhou.aliyuncs.com/Image/wd_1.png",
230 | "handler": "bankCard"
231 | ],[
232 | "title": "信用卡管理",
233 | "icon": "http://dsposweb.oss-cn-hangzhou.aliyuncs.com/Image/wd_5.png",
234 | "handler": "creditCard"
235 | ],[
236 | "title": "微信",
237 | "icon": "http://dsposweb.oss-cn-hangzhou.aliyuncs.com/Image/wd_2.png",
238 | "handler": "weChat",
239 | ],[
240 | "title": "安全中心",
241 | "icon": "http://dsposweb.oss-cn-hangzhou.aliyuncs.com/Image/wd_6.png",
242 | "handler": "securityCenter",
243 | ]
244 | ]
245 | ]
246 |
247 | let cancelBtn = [
248 | "title": "取消",
249 | "type": "danger"
250 | ]
251 | let mmShareSheet = MMShareSheet.init(title: "远程icon测试", cards: cards, duration: nil, cancelBtn: cancelBtn)
252 | mmShareSheet.callBack = { (handler) ->() in
253 | self.noticeOnlyText(handler)
254 | }
255 | mmShareSheet.present()
256 |
257 | }
258 | }
259 |
--------------------------------------------------------------------------------
/Components/MMShareSheet.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DDShareSheet.swift
3 | // swiftui
4 | //
5 | // Created by 郭永红 on 2017/10/12.
6 | // Copyright © 2017年 keeponrunning. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | //常量
12 | let ss_mmdivideLineHeight:CGFloat = 1 /* 按钮与按钮之间的分割线高度 */
13 | let ss_mmscreenBounds = UIScreen.main.bounds /* 屏幕Bounds */
14 | let ss_mmscreenSize = ss_mmscreenBounds.size /* 屏幕大小 */
15 | let ss_mmscreenWidth = ss_mmscreenSize.width /* 屏幕宽度 */
16 | let ss_mmscreenHeight = ss_mmscreenSize.height /* 屏幕高度 */
17 | let ss_mmbuttonHeight:CGFloat = 48.0 * ss_mmscreenWidth / 375 /* button高度 */
18 | let ss_mmtitleHeight:CGFloat = 35.0 * ss_mmscreenWidth / 375 /* 标题的高度 */
19 | let ss_mmbtnPadding:CGFloat = 5 * ss_mmscreenWidth / 375 /* 取消按钮与其他按钮之间的间距 */
20 | let ss_mmdefaultDuration = 0.3
21 | let ss_mmcardHeight:CGFloat = 120.0 * ss_mmscreenWidth / 375 /* 单行card的高度 */
22 | let ss_mmitemHeight:CGFloat = 100.0 * ss_mmscreenWidth / 375 /* 单个item的高度 */
23 | let ss_mmitemwidth:CGFloat = 93.75 * ss_mmscreenWidth / 375 /* 单个item的宽度 */
24 |
25 |
26 | public typealias ItemClickBlock = (String) ->()
27 |
28 | public class MMShareSheet: UIView {
29 | var title:String? //标题
30 | var cards:Array>>? //按钮组
31 | var duration: Double? //动画时长
32 | var cancelButton: Dictionary? //取消按钮
33 |
34 | //适配iphoneX
35 | var paddng_bottom:CGFloat = ss_mmscreenHeight == 812.0 ? 34.0 : 0.0
36 |
37 | var shareSheetHeight:CGFloat = 0
38 | public var shareSheetView:UIView = UIView()
39 |
40 | public var callBack:ItemClickBlock?
41 |
42 | override init(frame: CGRect) {
43 | super.init(frame: frame)
44 | }
45 |
46 | required public init?(coder aDecoder: NSCoder) {
47 | fatalError("init(coder:) has not been implemented")
48 | }
49 |
50 |
51 | /// 初始化
52 | ///
53 | /// - Parameters:
54 | /// - title: 标题
55 | /// - buttons: 按钮数组
56 | /// - duration: 动画时长
57 | /// - cancel: 是否需要取消按钮
58 | convenience public init(title: String?, cards: Array>>?, duration: Double?, cancelBtn: Dictionary?) {
59 |
60 | //半透明背景
61 | self.init(frame: ss_mmscreenBounds)
62 | self.title = title ?? ""
63 | self.cards = cards ?? []
64 | let btnCount = self.cards?.count ?? 0
65 | self.duration = duration ?? (ss_mmdefaultDuration + ss_mmdefaultDuration * Double(btnCount/30))
66 | self.cancelButton = cancelBtn ?? [:]
67 | //添加单击事件,隐藏sheet
68 | let singleTap = UITapGestureRecognizer.init(target: self, action: #selector(self.singleTapDismiss))
69 | singleTap.delegate = self
70 | self.addGestureRecognizer(singleTap)
71 |
72 | //shareSheet
73 | initShareSheet()
74 | //初始化UI
75 | initUI()
76 | }
77 |
78 | func initShareSheet() {
79 | let btnCount = self.cards?.count ?? 0
80 | var tHeight:CGFloat = 0.0
81 | if (self.title != nil && self.title != "") {
82 | tHeight = ss_mmtitleHeight
83 | }
84 |
85 | var cancelHeight:CGFloat = 0.0
86 | if self.cancelButton! != [:] {
87 | cancelHeight = ss_mmbuttonHeight + ss_mmbtnPadding
88 | }
89 |
90 | shareSheetHeight = CGFloat(btnCount) * ss_mmcardHeight + tHeight + cancelHeight + CGFloat(btnCount) * ss_mmdivideLineHeight + paddng_bottom
91 | let aFrame:CGRect = CGRect.init(x: 0, y: ss_mmscreenHeight, width: ss_mmscreenWidth, height: shareSheetHeight)
92 | self.shareSheetView.frame = aFrame
93 | self.addSubview(self.shareSheetView)
94 | }
95 |
96 | func initUI() {
97 |
98 | //标题不为空,则添加标题
99 | if (self.title != nil && self.title != "") {
100 | let titlelabel = UILabel.init(frame: CGRect.init(x: 0, y: 0, width: ss_mmscreenWidth, height: ss_mmtitleHeight))
101 | titlelabel.text = self.title
102 | titlelabel.textAlignment = .center
103 | titlelabel.textColor = UIColor(red: 0.361, green: 0.361, blue: 0.361, alpha: 1.00)
104 | titlelabel.font = UIFont.systemFont(ofSize: 12)
105 | titlelabel.backgroundColor = UIColor(red: 0.937, green: 0.937, blue: 0.941, alpha: 0.90)
106 | titlelabel.adjustsFontSizeToFitWidth = true
107 | self.shareSheetView.addSubview(titlelabel)
108 | }
109 |
110 | //事件按钮组
111 | let cardsCount = self.cards?.count ?? 0
112 | for index in 0.. 3 {break}
114 | let card = self.cards![index]
115 |
116 | var tHeight:CGFloat = 0.0
117 | if (self.title != nil && self.title != "") {
118 | tHeight = ss_mmtitleHeight
119 | }
120 |
121 | let origin_y = tHeight + ss_mmcardHeight * CGFloat(index) + ss_mmdivideLineHeight * CGFloat(index)
122 |
123 | let scroller = UIScrollView.init(frame: CGRect.init(x: 0.0, y: origin_y, width: ss_mmscreenWidth, height: ss_mmcardHeight))
124 | scroller.backgroundColor = UIColor(red: 1.000, green: 1.000, blue: 1.000, alpha: 0.80)
125 | scroller.showsHorizontalScrollIndicator = false
126 | scroller.showsVerticalScrollIndicator = false
127 | let contentSizeWidth = CGFloat(card.count) * ss_mmitemwidth > ss_mmscreenWidth ? CGFloat(card.count) * ss_mmitemwidth : (ss_mmscreenWidth + 1.0)
128 | scroller.contentSize = CGSize.init(width: contentSizeWidth, height: ss_mmcardHeight)
129 | let itemsCount = card.count
130 | for subIdx in 0..UIImage{
229 | let rect = CGRect(x:0, y:0, width: size.width, height: size.height)
230 | UIGraphicsBeginImageContext(rect.size)
231 | let context = UIGraphicsGetCurrentContext()
232 | context!.setFillColor(color.cgColor)
233 | context!.fill(rect)
234 | let image = UIGraphicsGetImageFromCurrentImageContext()
235 | UIGraphicsEndImageContext()
236 | return image!
237 | }
238 | }
239 |
240 | extension MMShareSheet: UIGestureRecognizerDelegate {
241 | public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
242 | if touch.view == self {
243 | return true
244 | }
245 | return false
246 | }
247 | }
248 |
--------------------------------------------------------------------------------
/Example/Example.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
43 |
62 |
81 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/swiftui.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 194CBE151F8DBA99002729E2 /* SwiftNotice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194CBE141F8DB963002729E2 /* SwiftNotice.swift */; };
11 | 1986B1601F8C3F2B00CBC6AE /* Example.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1986B15F1F8C3F2B00CBC6AE /* Example.storyboard */; };
12 | 19A29C391F8E0978004FBA48 /* MMShareSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A29C381F8E0978004FBA48 /* MMShareSheet.swift */; };
13 | 19A5B11A1F8F417900E5B593 /* MMCardItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A5B1191F8F417900E5B593 /* MMCardItem.swift */; };
14 | 19A84DF81F8AF08400475BEB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A84DF71F8AF08400475BEB /* AppDelegate.swift */; };
15 | 19A84DFF1F8AF08400475BEB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19A84DFE1F8AF08400475BEB /* Assets.xcassets */; };
16 | 19A84E021F8AF08400475BEB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 19A84E001F8AF08400475BEB /* LaunchScreen.storyboard */; };
17 | 19C6410E1F8B5B1C005C0E3B /* ExampleShareSheetVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C6410D1F8B5B1C005C0E3B /* ExampleShareSheetVC.swift */; };
18 | /* End PBXBuildFile section */
19 |
20 | /* Begin PBXFileReference section */
21 | 194CBE141F8DB963002729E2 /* SwiftNotice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftNotice.swift; sourceTree = ""; };
22 | 1986B15F1F8C3F2B00CBC6AE /* Example.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Example.storyboard; sourceTree = ""; };
23 | 19A29C381F8E0978004FBA48 /* MMShareSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MMShareSheet.swift; sourceTree = ""; };
24 | 19A5B1191F8F417900E5B593 /* MMCardItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MMCardItem.swift; sourceTree = ""; };
25 | 19A84DF41F8AF08400475BEB /* swiftui.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = swiftui.app; sourceTree = BUILT_PRODUCTS_DIR; };
26 | 19A84DF71F8AF08400475BEB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
27 | 19A84DFE1F8AF08400475BEB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
28 | 19A84E011F8AF08400475BEB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
29 | 19A84E031F8AF08400475BEB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
30 | 19C6410D1F8B5B1C005C0E3B /* ExampleShareSheetVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleShareSheetVC.swift; sourceTree = ""; };
31 | /* End PBXFileReference section */
32 |
33 | /* Begin PBXFrameworksBuildPhase section */
34 | 19A84DF11F8AF08400475BEB /* Frameworks */ = {
35 | isa = PBXFrameworksBuildPhase;
36 | buildActionMask = 2147483647;
37 | files = (
38 | );
39 | runOnlyForDeploymentPostprocessing = 0;
40 | };
41 | /* End PBXFrameworksBuildPhase section */
42 |
43 | /* Begin PBXGroup section */
44 | 1900C6BC1F8B0E5000DD81B5 /* Example */ = {
45 | isa = PBXGroup;
46 | children = (
47 | 19C6410D1F8B5B1C005C0E3B /* ExampleShareSheetVC.swift */,
48 | 1986B15F1F8C3F2B00CBC6AE /* Example.storyboard */,
49 | );
50 | path = Example;
51 | sourceTree = "";
52 | };
53 | 194CBE131F8DB94B002729E2 /* Tools */ = {
54 | isa = PBXGroup;
55 | children = (
56 | 194CBE141F8DB963002729E2 /* SwiftNotice.swift */,
57 | );
58 | path = Tools;
59 | sourceTree = "";
60 | };
61 | 19A84DEB1F8AF08400475BEB = {
62 | isa = PBXGroup;
63 | children = (
64 | 1900C6BC1F8B0E5000DD81B5 /* Example */,
65 | 19F72E7F1F8AF42D001B1EF7 /* Components */,
66 | 19A84DF61F8AF08400475BEB /* swiftui */,
67 | 194CBE131F8DB94B002729E2 /* Tools */,
68 | 19A84DF51F8AF08400475BEB /* Products */,
69 | );
70 | sourceTree = "";
71 | };
72 | 19A84DF51F8AF08400475BEB /* Products */ = {
73 | isa = PBXGroup;
74 | children = (
75 | 19A84DF41F8AF08400475BEB /* swiftui.app */,
76 | );
77 | name = Products;
78 | sourceTree = "";
79 | };
80 | 19A84DF61F8AF08400475BEB /* swiftui */ = {
81 | isa = PBXGroup;
82 | children = (
83 | 19A84DF71F8AF08400475BEB /* AppDelegate.swift */,
84 | 19A84DFE1F8AF08400475BEB /* Assets.xcassets */,
85 | 19A84E001F8AF08400475BEB /* LaunchScreen.storyboard */,
86 | 19A84E031F8AF08400475BEB /* Info.plist */,
87 | );
88 | path = swiftui;
89 | sourceTree = "";
90 | };
91 | 19F72E7F1F8AF42D001B1EF7 /* Components */ = {
92 | isa = PBXGroup;
93 | children = (
94 | 19A29C381F8E0978004FBA48 /* MMShareSheet.swift */,
95 | 19A5B1191F8F417900E5B593 /* MMCardItem.swift */,
96 | );
97 | path = Components;
98 | sourceTree = "";
99 | };
100 | /* End PBXGroup section */
101 |
102 | /* Begin PBXNativeTarget section */
103 | 19A84DF31F8AF08400475BEB /* swiftui */ = {
104 | isa = PBXNativeTarget;
105 | buildConfigurationList = 19A84E061F8AF08400475BEB /* Build configuration list for PBXNativeTarget "swiftui" */;
106 | buildPhases = (
107 | 19A84DF01F8AF08400475BEB /* Sources */,
108 | 19A84DF11F8AF08400475BEB /* Frameworks */,
109 | 19A84DF21F8AF08400475BEB /* Resources */,
110 | );
111 | buildRules = (
112 | );
113 | dependencies = (
114 | );
115 | name = swiftui;
116 | productName = swiftui;
117 | productReference = 19A84DF41F8AF08400475BEB /* swiftui.app */;
118 | productType = "com.apple.product-type.application";
119 | };
120 | /* End PBXNativeTarget section */
121 |
122 | /* Begin PBXProject section */
123 | 19A84DEC1F8AF08400475BEB /* Project object */ = {
124 | isa = PBXProject;
125 | attributes = {
126 | LastSwiftUpdateCheck = 0830;
127 | LastUpgradeCheck = 0900;
128 | ORGANIZATIONNAME = keeponrunning;
129 | TargetAttributes = {
130 | 19A84DF31F8AF08400475BEB = {
131 | CreatedOnToolsVersion = 8.3.3;
132 | DevelopmentTeam = Q5N6EB6624;
133 | LastSwiftMigration = 0900;
134 | ProvisioningStyle = Automatic;
135 | };
136 | };
137 | };
138 | buildConfigurationList = 19A84DEF1F8AF08400475BEB /* Build configuration list for PBXProject "swiftui" */;
139 | compatibilityVersion = "Xcode 3.2";
140 | developmentRegion = English;
141 | hasScannedForEncodings = 0;
142 | knownRegions = (
143 | en,
144 | Base,
145 | );
146 | mainGroup = 19A84DEB1F8AF08400475BEB;
147 | productRefGroup = 19A84DF51F8AF08400475BEB /* Products */;
148 | projectDirPath = "";
149 | projectRoot = "";
150 | targets = (
151 | 19A84DF31F8AF08400475BEB /* swiftui */,
152 | );
153 | };
154 | /* End PBXProject section */
155 |
156 | /* Begin PBXResourcesBuildPhase section */
157 | 19A84DF21F8AF08400475BEB /* Resources */ = {
158 | isa = PBXResourcesBuildPhase;
159 | buildActionMask = 2147483647;
160 | files = (
161 | 19A84E021F8AF08400475BEB /* LaunchScreen.storyboard in Resources */,
162 | 19A84DFF1F8AF08400475BEB /* Assets.xcassets in Resources */,
163 | 1986B1601F8C3F2B00CBC6AE /* Example.storyboard in Resources */,
164 | );
165 | runOnlyForDeploymentPostprocessing = 0;
166 | };
167 | /* End PBXResourcesBuildPhase section */
168 |
169 | /* Begin PBXSourcesBuildPhase section */
170 | 19A84DF01F8AF08400475BEB /* Sources */ = {
171 | isa = PBXSourcesBuildPhase;
172 | buildActionMask = 2147483647;
173 | files = (
174 | 19A5B11A1F8F417900E5B593 /* MMCardItem.swift in Sources */,
175 | 194CBE151F8DBA99002729E2 /* SwiftNotice.swift in Sources */,
176 | 19C6410E1F8B5B1C005C0E3B /* ExampleShareSheetVC.swift in Sources */,
177 | 19A84DF81F8AF08400475BEB /* AppDelegate.swift in Sources */,
178 | 19A29C391F8E0978004FBA48 /* MMShareSheet.swift in Sources */,
179 | );
180 | runOnlyForDeploymentPostprocessing = 0;
181 | };
182 | /* End PBXSourcesBuildPhase section */
183 |
184 | /* Begin PBXVariantGroup section */
185 | 19A84E001F8AF08400475BEB /* LaunchScreen.storyboard */ = {
186 | isa = PBXVariantGroup;
187 | children = (
188 | 19A84E011F8AF08400475BEB /* Base */,
189 | );
190 | name = LaunchScreen.storyboard;
191 | sourceTree = "";
192 | };
193 | /* End PBXVariantGroup section */
194 |
195 | /* Begin XCBuildConfiguration section */
196 | 19A84E041F8AF08400475BEB /* Debug */ = {
197 | isa = XCBuildConfiguration;
198 | buildSettings = {
199 | ALWAYS_SEARCH_USER_PATHS = NO;
200 | CLANG_ANALYZER_NONNULL = YES;
201 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
202 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
203 | CLANG_CXX_LIBRARY = "libc++";
204 | CLANG_ENABLE_MODULES = YES;
205 | CLANG_ENABLE_OBJC_ARC = YES;
206 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
207 | CLANG_WARN_BOOL_CONVERSION = YES;
208 | CLANG_WARN_COMMA = YES;
209 | CLANG_WARN_CONSTANT_CONVERSION = YES;
210 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
211 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
212 | CLANG_WARN_EMPTY_BODY = YES;
213 | CLANG_WARN_ENUM_CONVERSION = YES;
214 | CLANG_WARN_INFINITE_RECURSION = YES;
215 | CLANG_WARN_INT_CONVERSION = YES;
216 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
217 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
218 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
219 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
220 | CLANG_WARN_STRICT_PROTOTYPES = YES;
221 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
222 | CLANG_WARN_UNREACHABLE_CODE = YES;
223 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
224 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
225 | COPY_PHASE_STRIP = NO;
226 | DEBUG_INFORMATION_FORMAT = dwarf;
227 | ENABLE_STRICT_OBJC_MSGSEND = YES;
228 | ENABLE_TESTABILITY = YES;
229 | GCC_C_LANGUAGE_STANDARD = gnu99;
230 | GCC_DYNAMIC_NO_PIC = NO;
231 | GCC_NO_COMMON_BLOCKS = YES;
232 | GCC_OPTIMIZATION_LEVEL = 0;
233 | GCC_PREPROCESSOR_DEFINITIONS = (
234 | "DEBUG=1",
235 | "$(inherited)",
236 | );
237 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
238 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
239 | GCC_WARN_UNDECLARED_SELECTOR = YES;
240 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
241 | GCC_WARN_UNUSED_FUNCTION = YES;
242 | GCC_WARN_UNUSED_VARIABLE = YES;
243 | IPHONEOS_DEPLOYMENT_TARGET = 10.3;
244 | MTL_ENABLE_DEBUG_INFO = YES;
245 | ONLY_ACTIVE_ARCH = YES;
246 | SDKROOT = iphoneos;
247 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
248 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
249 | TARGETED_DEVICE_FAMILY = "1,2";
250 | };
251 | name = Debug;
252 | };
253 | 19A84E051F8AF08400475BEB /* Release */ = {
254 | isa = XCBuildConfiguration;
255 | buildSettings = {
256 | ALWAYS_SEARCH_USER_PATHS = NO;
257 | CLANG_ANALYZER_NONNULL = YES;
258 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
259 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
260 | CLANG_CXX_LIBRARY = "libc++";
261 | CLANG_ENABLE_MODULES = YES;
262 | CLANG_ENABLE_OBJC_ARC = YES;
263 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
264 | CLANG_WARN_BOOL_CONVERSION = YES;
265 | CLANG_WARN_COMMA = YES;
266 | CLANG_WARN_CONSTANT_CONVERSION = YES;
267 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
268 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
269 | CLANG_WARN_EMPTY_BODY = YES;
270 | CLANG_WARN_ENUM_CONVERSION = YES;
271 | CLANG_WARN_INFINITE_RECURSION = YES;
272 | CLANG_WARN_INT_CONVERSION = YES;
273 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
274 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
275 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
276 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
277 | CLANG_WARN_STRICT_PROTOTYPES = YES;
278 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
279 | CLANG_WARN_UNREACHABLE_CODE = YES;
280 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
281 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
282 | COPY_PHASE_STRIP = NO;
283 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
284 | ENABLE_NS_ASSERTIONS = NO;
285 | ENABLE_STRICT_OBJC_MSGSEND = YES;
286 | GCC_C_LANGUAGE_STANDARD = gnu99;
287 | GCC_NO_COMMON_BLOCKS = YES;
288 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
289 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
290 | GCC_WARN_UNDECLARED_SELECTOR = YES;
291 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
292 | GCC_WARN_UNUSED_FUNCTION = YES;
293 | GCC_WARN_UNUSED_VARIABLE = YES;
294 | IPHONEOS_DEPLOYMENT_TARGET = 10.3;
295 | MTL_ENABLE_DEBUG_INFO = NO;
296 | SDKROOT = iphoneos;
297 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
298 | TARGETED_DEVICE_FAMILY = "1,2";
299 | VALIDATE_PRODUCT = YES;
300 | };
301 | name = Release;
302 | };
303 | 19A84E071F8AF08400475BEB /* Debug */ = {
304 | isa = XCBuildConfiguration;
305 | buildSettings = {
306 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
307 | DEVELOPMENT_TEAM = Q5N6EB6624;
308 | INFOPLIST_FILE = swiftui/Info.plist;
309 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
310 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
311 | PRODUCT_BUNDLE_IDENTIFIER = com.keeponrunning.swiftui;
312 | PRODUCT_NAME = "$(TARGET_NAME)";
313 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
314 | SWIFT_VERSION = 4.0;
315 | };
316 | name = Debug;
317 | };
318 | 19A84E081F8AF08400475BEB /* Release */ = {
319 | isa = XCBuildConfiguration;
320 | buildSettings = {
321 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
322 | DEVELOPMENT_TEAM = Q5N6EB6624;
323 | INFOPLIST_FILE = swiftui/Info.plist;
324 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
325 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
326 | PRODUCT_BUNDLE_IDENTIFIER = com.keeponrunning.swiftui;
327 | PRODUCT_NAME = "$(TARGET_NAME)";
328 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
329 | SWIFT_VERSION = 4.0;
330 | };
331 | name = Release;
332 | };
333 | /* End XCBuildConfiguration section */
334 |
335 | /* Begin XCConfigurationList section */
336 | 19A84DEF1F8AF08400475BEB /* Build configuration list for PBXProject "swiftui" */ = {
337 | isa = XCConfigurationList;
338 | buildConfigurations = (
339 | 19A84E041F8AF08400475BEB /* Debug */,
340 | 19A84E051F8AF08400475BEB /* Release */,
341 | );
342 | defaultConfigurationIsVisible = 0;
343 | defaultConfigurationName = Release;
344 | };
345 | 19A84E061F8AF08400475BEB /* Build configuration list for PBXNativeTarget "swiftui" */ = {
346 | isa = XCConfigurationList;
347 | buildConfigurations = (
348 | 19A84E071F8AF08400475BEB /* Debug */,
349 | 19A84E081F8AF08400475BEB /* Release */,
350 | );
351 | defaultConfigurationIsVisible = 0;
352 | defaultConfigurationName = Release;
353 | };
354 | /* End XCConfigurationList section */
355 | };
356 | rootObject = 19A84DEC1F8AF08400475BEB /* Project object */;
357 | }
358 |
--------------------------------------------------------------------------------
/Tools/SwiftNotice.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftNotice.swift
3 | // SwiftNotice
4 | //
5 | // Created by JohnLui on 15/4/15.
6 | // Copyright (c) 2015年 com.lvwenhan. All rights reserved.
7 | // https://github.com/johnlui/SwiftNotice
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | private let sn_topBar: Int = 1001
13 |
14 | extension UIResponder {
15 | /// wait with your own animated images
16 | @discardableResult
17 | func pleaseWaitWithImages(_ imageNames: Array, timeInterval: Int) -> UIWindow{
18 | return SwiftNotice.wait(imageNames, timeInterval: timeInterval)
19 | }
20 | // api changed from v3.3
21 | @discardableResult
22 | func noticeTop(_ text: String, autoClear: Bool = true, autoClearTime: Int = 1) -> UIWindow{
23 | return SwiftNotice.noticeOnStatusBar(text, autoClear: autoClear, autoClearTime: autoClearTime)
24 | }
25 |
26 | // new apis from v3.3
27 | @discardableResult
28 | func noticeSuccess(_ text: String, autoClear: Bool = false, autoClearTime: Int = 3) -> UIWindow{
29 | return SwiftNotice.showNoticeWithText(NoticeType.success, text: text, autoClear: autoClear, autoClearTime: autoClearTime)
30 | }
31 | @discardableResult
32 | func noticeError(_ text: String, autoClear: Bool = false, autoClearTime: Int = 3) -> UIWindow{
33 | return SwiftNotice.showNoticeWithText(NoticeType.error, text: text, autoClear: autoClear, autoClearTime: autoClearTime)
34 | }
35 | @discardableResult
36 | func noticeInfo(_ text: String, autoClear: Bool = false, autoClearTime: Int = 3) -> UIWindow{
37 | return SwiftNotice.showNoticeWithText(NoticeType.info, text: text, autoClear: autoClear, autoClearTime: autoClearTime)
38 | }
39 |
40 | // old apis
41 | @discardableResult
42 | func successNotice(_ text: String, autoClear: Bool = true) -> UIWindow{
43 | return SwiftNotice.showNoticeWithText(NoticeType.success, text: text, autoClear: autoClear, autoClearTime: 3)
44 | }
45 | @discardableResult
46 | func errorNotice(_ text: String, autoClear: Bool = true) -> UIWindow{
47 | return SwiftNotice.showNoticeWithText(NoticeType.error, text: text, autoClear: autoClear, autoClearTime: 3)
48 | }
49 | @discardableResult
50 | func infoNotice(_ text: String, autoClear: Bool = true) -> UIWindow{
51 | return SwiftNotice.showNoticeWithText(NoticeType.info, text: text, autoClear: autoClear, autoClearTime: 3)
52 | }
53 | @discardableResult
54 | func notice(_ text: String, type: NoticeType, autoClear: Bool, autoClearTime: Int = 3) -> UIWindow{
55 | return SwiftNotice.showNoticeWithText(type, text: text, autoClear: autoClear, autoClearTime: autoClearTime)
56 | }
57 | @discardableResult
58 | func pleaseWait() -> UIWindow{
59 | return SwiftNotice.wait()
60 | }
61 | @discardableResult
62 | func noticeOnlyText(_ text: String) -> UIWindow{
63 | return SwiftNotice.showText(text)
64 | }
65 | func clearAllNotice() {
66 | SwiftNotice.clear()
67 | }
68 | }
69 |
70 | enum NoticeType{
71 | case success
72 | case error
73 | case info
74 | }
75 |
76 | class SwiftNotice: NSObject {
77 |
78 | static var windows = Array()
79 | static let rv = UIApplication.shared.keyWindow?.subviews.first as UIView!
80 | static var timer: DispatchSource!
81 | static var timerTimes = 0
82 |
83 | /* just for iOS 8
84 | */
85 | static var degree: Double {
86 | get {
87 | return [0, 0, 180, 270, 90][UIApplication.shared.statusBarOrientation.hashValue] as Double
88 | }
89 | }
90 |
91 | // fix https://github.com/johnlui/SwiftNotice/issues/2
92 | // thanks broccolii(https://github.com/broccolii) and his PR https://github.com/johnlui/SwiftNotice/pull/5
93 | static func clear() {
94 | self.cancelPreviousPerformRequests(withTarget: self)
95 | if let _ = timer {
96 | timer.cancel()
97 | timer = nil
98 | timerTimes = 0
99 | }
100 | windows.removeAll(keepingCapacity: false)
101 | }
102 |
103 | @discardableResult
104 | static func noticeOnStatusBar(_ text: String, autoClear: Bool, autoClearTime: Int) -> UIWindow{
105 | let frame = UIApplication.shared.statusBarFrame
106 | let window = UIWindow()
107 | window.backgroundColor = UIColor.clear
108 | let view = UIView()
109 | view.backgroundColor = UIColor(red: 0x6a/0x100, green: 0xb4/0x100, blue: 0x9f/0x100, alpha: 1)
110 |
111 | let label = UILabel(frame: frame)
112 | label.textAlignment = NSTextAlignment.center
113 | label.font = UIFont.systemFont(ofSize: 12)
114 | label.textColor = UIColor.white
115 | label.text = text
116 | view.addSubview(label)
117 |
118 | window.frame = frame
119 | view.frame = frame
120 |
121 | if let version = Double(UIDevice.current.systemVersion),
122 | version < 9.0 {
123 | // change center
124 | var array = [UIScreen.main.bounds.width, UIScreen.main.bounds.height]
125 | array = array.sorted(by: <)
126 | let screenWidth = array[0]
127 | let screenHeight = array[1]
128 | let x = [0, screenWidth/2, screenWidth/2, 10, screenWidth-10][UIApplication.shared.statusBarOrientation.hashValue] as CGFloat
129 | let y = [0, 10, screenHeight-10, screenHeight/2, screenHeight/2][UIApplication.shared.statusBarOrientation.hashValue] as CGFloat
130 | window.center = CGPoint(x: x, y: y)
131 |
132 | // change direction
133 | window.transform = CGAffineTransform(rotationAngle: CGFloat(degree * Double.pi / 180))
134 | }
135 |
136 | window.windowLevel = UIWindowLevelStatusBar
137 | window.isHidden = false
138 | window.addSubview(view)
139 | windows.append(window)
140 |
141 | var origPoint = view.frame.origin
142 | origPoint.y = -(view.frame.size.height)
143 | let destPoint = view.frame.origin
144 | view.tag = sn_topBar
145 |
146 | view.frame = CGRect(origin: origPoint, size: view.frame.size)
147 | UIView.animate(withDuration: 0.3, animations: {
148 | view.frame = CGRect(origin: destPoint, size: view.frame.size)
149 | }, completion: { b in
150 | if autoClear {
151 | let selector = #selector(SwiftNotice.hideNotice(_:))
152 | self.perform(selector, with: window, afterDelay: TimeInterval(autoClearTime))
153 | }
154 | })
155 | return window
156 | }
157 |
158 | @discardableResult
159 | static func wait(_ imageNames: Array = Array(), timeInterval: Int = 0) -> UIWindow {
160 | let frame = CGRect(x: 0, y: 0, width: 78, height: 78)
161 | let window = UIWindow()
162 | window.backgroundColor = UIColor.clear
163 | let mainView = UIView()
164 | mainView.layer.cornerRadius = 12
165 | mainView.backgroundColor = UIColor(red:0, green:0, blue:0, alpha: 0.8)
166 |
167 | if imageNames.count > 0 {
168 | if imageNames.count > timerTimes {
169 | let iv = UIImageView(frame: frame)
170 | iv.image = imageNames.first!
171 | iv.contentMode = UIViewContentMode.scaleAspectFit
172 | mainView.addSubview(iv)
173 | timer = DispatchSource.makeTimerSource(flags: DispatchSource.TimerFlags(rawValue: UInt(0)), queue: DispatchQueue.main) as! DispatchSource
174 | timer.schedule(deadline: DispatchTime.now(), repeating: DispatchTimeInterval.milliseconds(timeInterval))
175 | timer.setEventHandler(handler: { () -> Void in
176 | let name = imageNames[timerTimes % imageNames.count]
177 | iv.image = name
178 | timerTimes += 1
179 | })
180 | timer.resume()
181 | }
182 | } else {
183 | let ai = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.whiteLarge)
184 | ai.frame = CGRect(x: 21, y: 21, width: 36, height: 36)
185 | ai.startAnimating()
186 | mainView.addSubview(ai)
187 | }
188 |
189 | window.frame = frame
190 | mainView.frame = frame
191 | window.center = rv!.center
192 |
193 | if let version = Double(UIDevice.current.systemVersion),
194 | version < 9.0 {
195 | // change center
196 | window.center = getRealCenter()
197 | // change direction
198 | window.transform = CGAffineTransform(rotationAngle: CGFloat(degree * Double.pi / 180))
199 | }
200 |
201 | window.windowLevel = UIWindowLevelAlert
202 | window.isHidden = false
203 | window.addSubview(mainView)
204 | windows.append(window)
205 |
206 | mainView.alpha = 0.0
207 | UIView.animate(withDuration: 0.2, animations: {
208 | mainView.alpha = 1
209 | })
210 | return window
211 | }
212 |
213 | @discardableResult
214 | static func showText(_ text: String, autoClear: Bool=true, autoClearTime: Int=2) -> UIWindow {
215 | let window = UIWindow()
216 | window.backgroundColor = UIColor.clear
217 | let mainView = UIView()
218 | mainView.layer.cornerRadius = 12
219 | mainView.backgroundColor = UIColor(red:0, green:0, blue:0, alpha: 0.8)
220 |
221 | let label = UILabel()
222 | label.text = text
223 | label.numberOfLines = 0
224 | label.font = UIFont.systemFont(ofSize: 13)
225 | label.textAlignment = NSTextAlignment.center
226 | label.textColor = UIColor.white
227 | let size = label.sizeThatFits(CGSize(width: UIScreen.main.bounds.width-82, height: CGFloat.greatestFiniteMagnitude))
228 | label.bounds = CGRect(x: 0, y: 0, width: size.width, height: size.height)
229 | mainView.addSubview(label)
230 |
231 | let superFrame = CGRect(x: 0, y: 0, width: label.frame.width + 50 , height: label.frame.height + 30)
232 | window.frame = superFrame
233 | mainView.frame = superFrame
234 |
235 | label.center = mainView.center
236 | window.center = rv!.center
237 |
238 | if let version = Double(UIDevice.current.systemVersion),
239 | version < 9.0 {
240 | // change center
241 | window.center = getRealCenter()
242 | // change direction
243 | window.transform = CGAffineTransform(rotationAngle: CGFloat(degree * Double.pi / 180))
244 | }
245 |
246 | window.windowLevel = UIWindowLevelAlert
247 | window.isHidden = false
248 | window.addSubview(mainView)
249 | windows.append(window)
250 |
251 | if autoClear {
252 | let selector = #selector(SwiftNotice.hideNotice(_:))
253 | self.perform(selector, with: window, afterDelay: TimeInterval(autoClearTime))
254 | }
255 | return window
256 | }
257 |
258 | @discardableResult
259 | static func showNoticeWithText(_ type: NoticeType,text: String, autoClear: Bool, autoClearTime: Int) -> UIWindow {
260 | let frame = CGRect(x: 0, y: 0, width: 90, height: 90)
261 | let window = UIWindow()
262 | window.backgroundColor = UIColor.clear
263 | let mainView = UIView()
264 | mainView.layer.cornerRadius = 10
265 | mainView.backgroundColor = UIColor(red:0, green:0, blue:0, alpha: 0.7)
266 |
267 | var image = UIImage()
268 | switch type {
269 | case .success:
270 | image = SwiftNoticeSDK.imageOfCheckmark
271 | case .error:
272 | image = SwiftNoticeSDK.imageOfCross
273 | case .info:
274 | image = SwiftNoticeSDK.imageOfInfo
275 | }
276 | let checkmarkView = UIImageView(image: image)
277 | checkmarkView.frame = CGRect(x: 27, y: 15, width: 36, height: 36)
278 | mainView.addSubview(checkmarkView)
279 |
280 | let label = UILabel(frame: CGRect(x: 0, y: 60, width: 90, height: 16))
281 | label.font = UIFont.systemFont(ofSize: 13)
282 | label.textColor = UIColor.white
283 | label.text = text
284 | label.textAlignment = NSTextAlignment.center
285 | mainView.addSubview(label)
286 |
287 | window.frame = frame
288 | mainView.frame = frame
289 | window.center = rv!.center
290 |
291 | if let version = Double(UIDevice.current.systemVersion),
292 | version < 9.0 {
293 | // change center
294 | window.center = getRealCenter()
295 | // change direction
296 | window.transform = CGAffineTransform(rotationAngle: CGFloat(degree * Double.pi / 180))
297 | }
298 |
299 | window.windowLevel = UIWindowLevelAlert
300 | window.center = rv!.center
301 | window.isHidden = false
302 | window.addSubview(mainView)
303 | windows.append(window)
304 |
305 | mainView.alpha = 0.0
306 | UIView.animate(withDuration: 0.2, animations: {
307 | mainView.alpha = 1
308 | })
309 |
310 | if autoClear {
311 | let selector = #selector(SwiftNotice.hideNotice(_:))
312 | self.perform(selector, with: window, afterDelay: TimeInterval(autoClearTime))
313 | }
314 | return window
315 | }
316 |
317 | // fix https://github.com/johnlui/SwiftNotice/issues/2
318 | @objc static func hideNotice(_ sender: AnyObject) {
319 | if let window = sender as? UIWindow {
320 |
321 | if let v = window.subviews.first {
322 | UIView.animate(withDuration: 0.2, animations: {
323 |
324 | if v.tag == sn_topBar {
325 | v.frame = CGRect(x: 0, y: -v.frame.height, width: v.frame.width, height: v.frame.height)
326 | }
327 | v.alpha = 0
328 | }, completion: { b in
329 |
330 | if let index = windows.index(where: { (item) -> Bool in
331 | return item == window
332 | }) {
333 | windows.remove(at: index)
334 | }
335 | })
336 | }
337 |
338 | }
339 | }
340 |
341 | // just for iOS 8
342 | static func getRealCenter() -> CGPoint {
343 | if UIApplication.shared.statusBarOrientation.hashValue >= 3 {
344 | return CGPoint(x: rv!.center.y, y: rv!.center.x)
345 | } else {
346 | return rv!.center
347 | }
348 | }
349 | }
350 |
351 | class SwiftNoticeSDK {
352 | struct Cache {
353 | static var imageOfCheckmark: UIImage?
354 | static var imageOfCross: UIImage?
355 | static var imageOfInfo: UIImage?
356 | }
357 | class func draw(_ type: NoticeType) {
358 | let checkmarkShapePath = UIBezierPath()
359 |
360 | // draw circle
361 | checkmarkShapePath.move(to: CGPoint(x: 36, y: 18))
362 | checkmarkShapePath.addArc(withCenter: CGPoint(x: 18, y: 18), radius: 17.5, startAngle: 0, endAngle: CGFloat(Double.pi*2), clockwise: true)
363 | checkmarkShapePath.close()
364 |
365 | switch type {
366 | case .success: // draw checkmark
367 | checkmarkShapePath.move(to: CGPoint(x: 10, y: 18))
368 | checkmarkShapePath.addLine(to: CGPoint(x: 16, y: 24))
369 | checkmarkShapePath.addLine(to: CGPoint(x: 27, y: 13))
370 | checkmarkShapePath.move(to: CGPoint(x: 10, y: 18))
371 | checkmarkShapePath.close()
372 | case .error: // draw X
373 | checkmarkShapePath.move(to: CGPoint(x: 10, y: 10))
374 | checkmarkShapePath.addLine(to: CGPoint(x: 26, y: 26))
375 | checkmarkShapePath.move(to: CGPoint(x: 10, y: 26))
376 | checkmarkShapePath.addLine(to: CGPoint(x: 26, y: 10))
377 | checkmarkShapePath.move(to: CGPoint(x: 10, y: 10))
378 | checkmarkShapePath.close()
379 | case .info:
380 | checkmarkShapePath.move(to: CGPoint(x: 18, y: 6))
381 | checkmarkShapePath.addLine(to: CGPoint(x: 18, y: 22))
382 | checkmarkShapePath.move(to: CGPoint(x: 18, y: 6))
383 | checkmarkShapePath.close()
384 |
385 | UIColor.white.setStroke()
386 | checkmarkShapePath.stroke()
387 |
388 | let checkmarkShapePath = UIBezierPath()
389 | checkmarkShapePath.move(to: CGPoint(x: 18, y: 27))
390 | checkmarkShapePath.addArc(withCenter: CGPoint(x: 18, y: 27), radius: 1, startAngle: 0, endAngle: CGFloat(Double.pi*2), clockwise: true)
391 | checkmarkShapePath.close()
392 |
393 | UIColor.white.setFill()
394 | checkmarkShapePath.fill()
395 | }
396 |
397 | UIColor.white.setStroke()
398 | checkmarkShapePath.stroke()
399 | }
400 | class var imageOfCheckmark: UIImage {
401 | if (Cache.imageOfCheckmark != nil) {
402 | return Cache.imageOfCheckmark!
403 | }
404 | UIGraphicsBeginImageContextWithOptions(CGSize(width: 36, height: 36), false, 0)
405 |
406 | SwiftNoticeSDK.draw(NoticeType.success)
407 |
408 | Cache.imageOfCheckmark = UIGraphicsGetImageFromCurrentImageContext()
409 | UIGraphicsEndImageContext()
410 | return Cache.imageOfCheckmark!
411 | }
412 | class var imageOfCross: UIImage {
413 | if (Cache.imageOfCross != nil) {
414 | return Cache.imageOfCross!
415 | }
416 | UIGraphicsBeginImageContextWithOptions(CGSize(width: 36, height: 36), false, 0)
417 |
418 | SwiftNoticeSDK.draw(NoticeType.error)
419 |
420 | Cache.imageOfCross = UIGraphicsGetImageFromCurrentImageContext()
421 | UIGraphicsEndImageContext()
422 | return Cache.imageOfCross!
423 | }
424 | class var imageOfInfo: UIImage {
425 | if (Cache.imageOfInfo != nil) {
426 | return Cache.imageOfInfo!
427 | }
428 | UIGraphicsBeginImageContextWithOptions(CGSize(width: 36, height: 36), false, 0)
429 |
430 | SwiftNoticeSDK.draw(NoticeType.info)
431 |
432 | Cache.imageOfInfo = UIGraphicsGetImageFromCurrentImageContext()
433 | UIGraphicsEndImageContext()
434 | return Cache.imageOfInfo!
435 | }
436 | }
437 |
438 | extension UIWindow{
439 | func hide(){
440 | SwiftNotice.hideNotice(self)
441 | }
442 | }
443 |
--------------------------------------------------------------------------------