├── assets
├── logo.png
├── demo1.gif
├── demo2.gif
└── demo3.png
├── A_J_Dot_Loading_Indicator.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── project.pbxproj
├── A_J_Dot_Loading_Indicator
├── ViewController.swift
├── helper
│ └── UIViewHelper.swift
├── Info.plist
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── core
│ ├── AJDotLoadingView.swift
│ ├── AJDotLoadingView.xib
│ └── UIDotLoadingIndicator.swift
└── AppDelegate.swift
├── .gitignore
└── README.md
/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigfly/A_J_Dot_Loading_Indicator/HEAD/assets/logo.png
--------------------------------------------------------------------------------
/assets/demo1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigfly/A_J_Dot_Loading_Indicator/HEAD/assets/demo1.gif
--------------------------------------------------------------------------------
/assets/demo2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigfly/A_J_Dot_Loading_Indicator/HEAD/assets/demo2.gif
--------------------------------------------------------------------------------
/assets/demo3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigfly/A_J_Dot_Loading_Indicator/HEAD/assets/demo3.png
--------------------------------------------------------------------------------
/A_J_Dot_Loading_Indicator.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/A_J_Dot_Loading_Indicator/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // A_J_Dot_Loading_Indicator
4 | //
5 | // Created by Alex Jiang on 13/3/18.
6 | // Copyright © 2018 Alex Jiang. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController {
12 | override func viewWillAppear(_ animated: Bool) {
13 | super.viewWillAppear(animated)
14 |
15 | view.aj_showDotLoadingIndicator()
16 | }
17 |
18 | @IBAction func stop(_ sender: UIButton) {
19 | view.aj_hideDotLoadingIndicator()
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/A_J_Dot_Loading_Indicator/helper/UIViewHelper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIViewHelper.swift
3 | // A_J_Dot_Loading_Indicator
4 | //
5 | // Created by Alex Jiang on 14/3/18.
6 | // Copyright © 2018 Alex Jiang. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // MARK: - Safe Add SubView
12 |
13 | public extension UIView {
14 | public func safeAddSubView(subView: UIView, viewTag: Int = 1000000) {
15 | guard tag != viewTag else { return }
16 |
17 | let addedView = subviews.flatMap { $0.viewWithTag(viewTag) }.first
18 |
19 | if let _addedView = addedView {
20 | _addedView.removeFromSuperview()
21 | }
22 |
23 | subView.tag = viewTag
24 | addSubview(subView)
25 | }
26 | }
27 |
28 | // MARK: - Nib Loadable
29 |
30 | public protocol NibLoadable: class {
31 | static var nibName: String { get }
32 | static var bundle: Bundle? { get }
33 | }
34 |
35 | public extension NibLoadable {
36 | static var bundle: Bundle? {
37 | return Bundle(for: Self.self)
38 | }
39 |
40 | static var nibName: String {
41 | return String(describing: Self.self)
42 | }
43 |
44 | static var nib: UINib {
45 | return UINib(nibName: nibName, bundle: bundle)
46 | }
47 | }
48 |
49 | public extension NibLoadable where Self: UIView {
50 | static func createFromNib(_ owner: AnyObject? = nil) -> Self {
51 | return (nib.instantiate(withOwner: owner, options: nil).first as? Self)!
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/A_J_Dot_Loading_Indicator/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
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 | Main
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 |
45 |
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | ## Playgrounds
32 | timeline.xctimeline
33 | playground.xcworkspace
34 |
35 | # Swift Package Manager
36 | #
37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38 | # Packages/
39 | # Package.pins
40 | # Package.resolved
41 | .build/
42 |
43 | # CocoaPods
44 | #
45 | # We recommend against adding the Pods directory to your .gitignore. However
46 | # you should judge for yourself, the pros and cons are mentioned at:
47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
48 | #
49 | # Pods/
50 |
51 | # Carthage
52 | #
53 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
54 | # Carthage/Checkouts
55 |
56 |
57 | # fastlane
58 | #
59 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
60 | # screenshots whenever they are needed.
61 | # For more information about the recommended setup visit:
62 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
63 |
64 | fastlane/report.xml
65 | fastlane/Preview.html
66 | fastlane/screenshots
67 | fastlane/test_output
68 |
--------------------------------------------------------------------------------
/A_J_Dot_Loading_Indicator/Base.lproj/LaunchScreen.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 |
25 |
26 |
--------------------------------------------------------------------------------
/A_J_Dot_Loading_Indicator/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 | "info" : {
90 | "version" : 1,
91 | "author" : "xcode"
92 | }
93 | }
--------------------------------------------------------------------------------
/A_J_Dot_Loading_Indicator/core/AJDotLoadingView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WrapperView.swift
3 | // A_J_Dot_Loading_Indicator
4 | //
5 | // Created by Alex Jiang on 14/3/18.
6 | // Copyright © 2018 Alex Jiang. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public final class AJDotLoadingView: UIView {
12 |
13 | // MARK: - Public API
14 |
15 | @IBOutlet weak var dotLoadingIndicator: UIDotLoadingIndicator!
16 |
17 | public func startAnimating() {
18 | dotLoadingIndicator.startAnimating()
19 | }
20 |
21 | public func stopAnimating() {
22 | dotLoadingIndicator.stopAnimating()
23 | dotLoadingIndicator.removeFromSuperview()
24 | }
25 | }
26 |
27 | private var aj_loadingIndicatorAssociationKey = 0x1023
28 |
29 | extension AJDotLoadingView: NibLoadable {}
30 |
31 | public extension UIView {
32 | private var aj_loadingIndicator: AJDotLoadingView? {
33 | get {
34 | return objc_getAssociatedObject(self, &aj_loadingIndicatorAssociationKey) as? AJDotLoadingView
35 | }
36 | set {
37 | objc_setAssociatedObject(self, &aj_loadingIndicatorAssociationKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
38 | }
39 | }
40 |
41 | public func aj_showDotLoadingIndicator() {
42 | let dotLoadView = AJDotLoadingView.createFromNib()
43 | aj_loadingIndicator = dotLoadView
44 |
45 | safeAddSubView(subView: dotLoadView, viewTag: Int(aj_loadingIndicatorAssociationKey))
46 |
47 | dotLoadView.translatesAutoresizingMaskIntoConstraints = false
48 | self.topAnchor.constraint(equalTo: dotLoadView.topAnchor).isActive = true
49 | self.bottomAnchor.constraint(equalTo: dotLoadView.bottomAnchor).isActive = true
50 | self.leftAnchor.constraint(equalTo: dotLoadView.leftAnchor).isActive = true
51 | self.rightAnchor.constraint(equalTo: dotLoadView.rightAnchor).isActive = true
52 |
53 | aj_loadingIndicator?.startAnimating()
54 | }
55 |
56 | public func aj_hideDotLoadingIndicator() {
57 | aj_loadingIndicator?.stopAnimating()
58 | aj_loadingIndicator?.removeFromSuperview()
59 | aj_loadingIndicator = nil
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/A_J_Dot_Loading_Indicator/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // A_J_Dot_Loading_Indicator
4 | //
5 | // Created by Alex Jiang on 13/3/18.
6 | // Copyright © 2018 Alex Jiang. 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 |
--------------------------------------------------------------------------------
/A_J_Dot_Loading_Indicator/core/AJDotLoadingView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # A-J-Dot-Loading-Indicator
6 |
7 | 
8 | 
9 | 
10 | 
11 |
12 | A-J-Dot-Loading-Indicator is an drop-in solution for custom dot loading indicator in iOS
13 |
14 | ## Features
15 |
16 | - [x] No Dependency, 100% iOS Native
17 | - [x] Support both iPad and iPhone family
18 | - [x] Support device rotation
19 | - [x] Non-intrusive integration
20 | - [x] Full documentation
21 | - [x] Easy to customise
22 |
23 | ## Requirements
24 |
25 | - iOS 8.0+ / macOS 10.10+ / tvOS 9.0+ / watchOS 2.0+
26 | - Xcode 8.3+
27 | - Swift 3.1+
28 |
29 | ## Installation
30 |
31 | - drag and drop the entire `core` folder and `helper` folder into your project
32 |
33 | ## Full Usage Example
34 |
35 | ```swift
36 | import UIKit
37 |
38 | final class ViewController: UIViewController {
39 | override func viewWillAppear(_ animated: Bool) {
40 | super.viewWillAppear(animated)
41 |
42 | view.aj_showDotLoadingIndicator()
43 | }
44 |
45 | @IBAction func stop(_ sender: UIButton) {
46 | view.aj_hideDotLoadingIndicator()
47 | }
48 | }
49 | ```
50 |
51 | ## Folder Structure
52 |
53 | ```shell
54 | ├── ViewController.swift
55 | ├── core
56 | │ ├── AJDotLoadingView.swift
57 | │ ├── AJDotLoadingView.xib
58 | │ └── UIDotLoadingIndicator.swift
59 | └── helper
60 | └── UIViewHelper.swift
61 | ```
62 |
63 | | File | Responsiblity |
64 | |--------------------------------------|--------------------------------------------------------------------------------------|
65 | | ViewController | example view controller to show how to use `A-J-Dot-Loading-Indicator` |
66 | | UIViewHelper | helper `UIView` methods to refactor out common patterns |
67 | | core/AJDotLoadingView | wrapper view to include `UIDotLoadingIndicator` custom control |
68 | | core/UIDotLoadingIndicator | UI custom control for the dot loading indicator |
69 |
70 | ## Demo
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | ## Credits
85 |
86 | A-J-Dot-Loading-Indicator is owned and maintained by the [Alex Jiang](https://pigfly.github.io). Thanks [iTMan.design](https://itman.design) for providing computational resources.
87 |
88 | ## License
89 |
90 | A-J-Dot-Loading-Indicator is released under the MIT license.
--------------------------------------------------------------------------------
/A_J_Dot_Loading_Indicator/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/A_J_Dot_Loading_Indicator/core/UIDotLoadingIndicator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIDotLoadingIndicator.swift
3 | // A_J_Dot_Loading_Indicator
4 | //
5 | // Created by Alex Jiang on 13/3/18.
6 | // Copyright © 2018 Alex Jiang. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | //@IBDesignable
12 | public final class UIDotLoadingIndicator : UIView {
13 |
14 | // MARK: - Public API
15 |
16 | @IBInspectable public var dotsCount: Int = 3 {
17 | didSet {
18 | layer.sublayers?.forEach { $0.removeFromSuperlayer() }
19 | dotLayers.removeAll()
20 | setupLayers()
21 | }
22 | }
23 |
24 | @IBInspectable public var dotsRadius: CGFloat = 6.0 {
25 | didSet {
26 | for layer in dotLayers {
27 | layer.bounds = CGRect(origin: .zero, size: CGSize(width: dotsRadius * 2.0, height: dotsRadius * 2.0))
28 | layer.path = UIBezierPath(roundedRect: layer.bounds, cornerRadius: dotsRadius).cgPath
29 | }
30 | setNeedsLayout()
31 | }
32 | }
33 |
34 | @IBInspectable public var dotsSpacing: CGFloat = 10 {
35 | didSet {
36 | setNeedsLayout()
37 | }
38 | }
39 |
40 | override public var tintColor: UIColor! {
41 | didSet {
42 | for layer in dotLayers {
43 | layer.fillColor = tintColor.cgColor
44 | }
45 | }
46 | }
47 |
48 | public func startAnimating() {
49 | var offset :TimeInterval = 0.0
50 | dotLayers.forEach {
51 | $0.removeAllAnimations()
52 | $0.add(scaleAnimation(offset), forKey: "aj.dotLoading.scaleAnima")
53 | offset = offset + 0.25
54 | }
55 | }
56 |
57 | public func stopAnimating() {
58 | dotLayers.forEach { $0.removeAllAnimations() }
59 | }
60 |
61 | // MARK: - Init
62 |
63 | override public init(frame: CGRect) {
64 | super.init(frame: frame)
65 |
66 | setupLayers()
67 | }
68 |
69 | required public init?(coder aDecoder: NSCoder) {
70 | super.init(coder: aDecoder)
71 |
72 | setupLayers()
73 | }
74 |
75 | // MARK: - View Lifecycle
76 |
77 | public override func layoutSubviews() {
78 | super.layoutSubviews()
79 |
80 | let center = CGPoint(x: frame.size.width / 2.0, y: frame.size.height / 2.0)
81 | let middle: Int = dotsCount / 2
82 | for (index, layer) in dotLayers.enumerated() {
83 | let x = center.x + CGFloat(index - middle) * ((dotsRadius*2)+dotsSpacing)
84 | layer.position = CGPoint(x: x, y: center.y)
85 | }
86 | startAnimating()
87 | }
88 |
89 | // MARK: - Private API
90 |
91 | private var dotLayers = [CAShapeLayer]()
92 | private var dotsScale = 1.3
93 |
94 | private func dotLayer() -> CAShapeLayer {
95 | let layer = CAShapeLayer()
96 | layer.bounds = CGRect(origin: .zero, size: CGSize(width: dotsRadius*2.0, height: dotsRadius*2.0))
97 | layer.path = UIBezierPath(roundedRect: layer.bounds, cornerRadius: dotsRadius).cgPath
98 | layer.fillColor = tintColor.cgColor
99 | return layer
100 | }
101 |
102 | private func setupLayers() {
103 | for _ in 0.. CAAnimationGroup {
111 | let scaleUp = CABasicAnimation(keyPath: "transform.scale")
112 | scaleUp.beginTime = after
113 | scaleUp.fromValue = 1
114 | scaleUp.toValue = dotsScale
115 | scaleUp.duration = 0.3
116 | scaleUp.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
117 |
118 | let scaleDown = CABasicAnimation(keyPath: "transform.scale")
119 | scaleDown.beginTime = after+scaleUp.duration
120 | scaleDown.fromValue = dotsScale
121 | scaleDown.toValue = 1.0
122 | scaleDown.duration = 0.2
123 | scaleDown.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
124 |
125 | let group = CAAnimationGroup()
126 | group.animations = [scaleUp, scaleDown]
127 | group.repeatCount = Float.infinity
128 |
129 | let sum = CGFloat(dotsCount)*0.2 + CGFloat(0.4)
130 | group.duration = CFTimeInterval(sum)
131 |
132 | return group
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/A_J_Dot_Loading_Indicator.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 48;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | D6439B6420577A9600EFF8AF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6439B6320577A9600EFF8AF /* AppDelegate.swift */; };
11 | D6439B6620577A9600EFF8AF /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6439B6520577A9600EFF8AF /* ViewController.swift */; };
12 | D6439B6920577A9600EFF8AF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D6439B6720577A9600EFF8AF /* Main.storyboard */; };
13 | D6439B6B20577A9600EFF8AF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D6439B6A20577A9600EFF8AF /* Assets.xcassets */; };
14 | D6439B6E20577A9600EFF8AF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D6439B6C20577A9600EFF8AF /* LaunchScreen.storyboard */; };
15 | D6439B7620577ADA00EFF8AF /* UIDotLoadingIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6439B7520577ADA00EFF8AF /* UIDotLoadingIndicator.swift */; };
16 | D6C23CE720589EF1009E1974 /* AJDotLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C23CE620589EF1009E1974 /* AJDotLoadingView.swift */; };
17 | D6C23CEB20589F5E009E1974 /* AJDotLoadingView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6C23CEA20589F5E009E1974 /* AJDotLoadingView.xib */; };
18 | D6C23CEE2058A32B009E1974 /* UIViewHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C23CED2058A32B009E1974 /* UIViewHelper.swift */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXFileReference section */
22 | D6439B6020577A9600EFF8AF /* A_J_Dot_Loading_Indicator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = A_J_Dot_Loading_Indicator.app; sourceTree = BUILT_PRODUCTS_DIR; };
23 | D6439B6320577A9600EFF8AF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
24 | D6439B6520577A9600EFF8AF /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
25 | D6439B6820577A9600EFF8AF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
26 | D6439B6A20577A9600EFF8AF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
27 | D6439B6D20577A9600EFF8AF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
28 | D6439B6F20577A9600EFF8AF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
29 | D6439B7520577ADA00EFF8AF /* UIDotLoadingIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIDotLoadingIndicator.swift; sourceTree = ""; };
30 | D6C23CE620589EF1009E1974 /* AJDotLoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AJDotLoadingView.swift; sourceTree = ""; };
31 | D6C23CEA20589F5E009E1974 /* AJDotLoadingView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AJDotLoadingView.xib; sourceTree = ""; };
32 | D6C23CED2058A32B009E1974 /* UIViewHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewHelper.swift; sourceTree = ""; };
33 | /* End PBXFileReference section */
34 |
35 | /* Begin PBXFrameworksBuildPhase section */
36 | D6439B5D20577A9600EFF8AF /* Frameworks */ = {
37 | isa = PBXFrameworksBuildPhase;
38 | buildActionMask = 2147483647;
39 | files = (
40 | );
41 | runOnlyForDeploymentPostprocessing = 0;
42 | };
43 | /* End PBXFrameworksBuildPhase section */
44 |
45 | /* Begin PBXGroup section */
46 | D6439B5720577A9600EFF8AF = {
47 | isa = PBXGroup;
48 | children = (
49 | D6439B6220577A9600EFF8AF /* A_J_Dot_Loading_Indicator */,
50 | D6439B6120577A9600EFF8AF /* Products */,
51 | );
52 | sourceTree = "";
53 | };
54 | D6439B6120577A9600EFF8AF /* Products */ = {
55 | isa = PBXGroup;
56 | children = (
57 | D6439B6020577A9600EFF8AF /* A_J_Dot_Loading_Indicator.app */,
58 | );
59 | name = Products;
60 | sourceTree = "";
61 | };
62 | D6439B6220577A9600EFF8AF /* A_J_Dot_Loading_Indicator */ = {
63 | isa = PBXGroup;
64 | children = (
65 | D6439B6320577A9600EFF8AF /* AppDelegate.swift */,
66 | D6439B6520577A9600EFF8AF /* ViewController.swift */,
67 | D6439B6720577A9600EFF8AF /* Main.storyboard */,
68 | D6439B6A20577A9600EFF8AF /* Assets.xcassets */,
69 | D6439B6C20577A9600EFF8AF /* LaunchScreen.storyboard */,
70 | D6439B6F20577A9600EFF8AF /* Info.plist */,
71 | D6C23CEC2058A2DC009E1974 /* helper */,
72 | D6439B7720577AE000EFF8AF /* core */,
73 | );
74 | path = A_J_Dot_Loading_Indicator;
75 | sourceTree = "";
76 | };
77 | D6439B7720577AE000EFF8AF /* core */ = {
78 | isa = PBXGroup;
79 | children = (
80 | D6439B7520577ADA00EFF8AF /* UIDotLoadingIndicator.swift */,
81 | D6C23CE620589EF1009E1974 /* AJDotLoadingView.swift */,
82 | D6C23CEA20589F5E009E1974 /* AJDotLoadingView.xib */,
83 | );
84 | path = core;
85 | sourceTree = "";
86 | };
87 | D6C23CEC2058A2DC009E1974 /* helper */ = {
88 | isa = PBXGroup;
89 | children = (
90 | D6C23CED2058A32B009E1974 /* UIViewHelper.swift */,
91 | );
92 | path = helper;
93 | sourceTree = "";
94 | };
95 | /* End PBXGroup section */
96 |
97 | /* Begin PBXNativeTarget section */
98 | D6439B5F20577A9600EFF8AF /* A_J_Dot_Loading_Indicator */ = {
99 | isa = PBXNativeTarget;
100 | buildConfigurationList = D6439B7220577A9600EFF8AF /* Build configuration list for PBXNativeTarget "A_J_Dot_Loading_Indicator" */;
101 | buildPhases = (
102 | D6439B5C20577A9600EFF8AF /* Sources */,
103 | D6439B5D20577A9600EFF8AF /* Frameworks */,
104 | D6439B5E20577A9600EFF8AF /* Resources */,
105 | );
106 | buildRules = (
107 | );
108 | dependencies = (
109 | );
110 | name = A_J_Dot_Loading_Indicator;
111 | productName = A_J_Dot_Loading_Indicator;
112 | productReference = D6439B6020577A9600EFF8AF /* A_J_Dot_Loading_Indicator.app */;
113 | productType = "com.apple.product-type.application";
114 | };
115 | /* End PBXNativeTarget section */
116 |
117 | /* Begin PBXProject section */
118 | D6439B5820577A9600EFF8AF /* Project object */ = {
119 | isa = PBXProject;
120 | attributes = {
121 | LastSwiftUpdateCheck = 0910;
122 | LastUpgradeCheck = 0910;
123 | ORGANIZATIONNAME = "Alex Jiang";
124 | TargetAttributes = {
125 | D6439B5F20577A9600EFF8AF = {
126 | CreatedOnToolsVersion = 9.1;
127 | ProvisioningStyle = Automatic;
128 | };
129 | };
130 | };
131 | buildConfigurationList = D6439B5B20577A9600EFF8AF /* Build configuration list for PBXProject "A_J_Dot_Loading_Indicator" */;
132 | compatibilityVersion = "Xcode 8.0";
133 | developmentRegion = en;
134 | hasScannedForEncodings = 0;
135 | knownRegions = (
136 | en,
137 | Base,
138 | );
139 | mainGroup = D6439B5720577A9600EFF8AF;
140 | productRefGroup = D6439B6120577A9600EFF8AF /* Products */;
141 | projectDirPath = "";
142 | projectRoot = "";
143 | targets = (
144 | D6439B5F20577A9600EFF8AF /* A_J_Dot_Loading_Indicator */,
145 | );
146 | };
147 | /* End PBXProject section */
148 |
149 | /* Begin PBXResourcesBuildPhase section */
150 | D6439B5E20577A9600EFF8AF /* Resources */ = {
151 | isa = PBXResourcesBuildPhase;
152 | buildActionMask = 2147483647;
153 | files = (
154 | D6C23CEB20589F5E009E1974 /* AJDotLoadingView.xib in Resources */,
155 | D6439B6E20577A9600EFF8AF /* LaunchScreen.storyboard in Resources */,
156 | D6439B6B20577A9600EFF8AF /* Assets.xcassets in Resources */,
157 | D6439B6920577A9600EFF8AF /* Main.storyboard in Resources */,
158 | );
159 | runOnlyForDeploymentPostprocessing = 0;
160 | };
161 | /* End PBXResourcesBuildPhase section */
162 |
163 | /* Begin PBXSourcesBuildPhase section */
164 | D6439B5C20577A9600EFF8AF /* Sources */ = {
165 | isa = PBXSourcesBuildPhase;
166 | buildActionMask = 2147483647;
167 | files = (
168 | D6C23CEE2058A32B009E1974 /* UIViewHelper.swift in Sources */,
169 | D6C23CE720589EF1009E1974 /* AJDotLoadingView.swift in Sources */,
170 | D6439B6620577A9600EFF8AF /* ViewController.swift in Sources */,
171 | D6439B6420577A9600EFF8AF /* AppDelegate.swift in Sources */,
172 | D6439B7620577ADA00EFF8AF /* UIDotLoadingIndicator.swift in Sources */,
173 | );
174 | runOnlyForDeploymentPostprocessing = 0;
175 | };
176 | /* End PBXSourcesBuildPhase section */
177 |
178 | /* Begin PBXVariantGroup section */
179 | D6439B6720577A9600EFF8AF /* Main.storyboard */ = {
180 | isa = PBXVariantGroup;
181 | children = (
182 | D6439B6820577A9600EFF8AF /* Base */,
183 | );
184 | name = Main.storyboard;
185 | sourceTree = "";
186 | };
187 | D6439B6C20577A9600EFF8AF /* LaunchScreen.storyboard */ = {
188 | isa = PBXVariantGroup;
189 | children = (
190 | D6439B6D20577A9600EFF8AF /* Base */,
191 | );
192 | name = LaunchScreen.storyboard;
193 | sourceTree = "";
194 | };
195 | /* End PBXVariantGroup section */
196 |
197 | /* Begin XCBuildConfiguration section */
198 | D6439B7020577A9600EFF8AF /* Debug */ = {
199 | isa = XCBuildConfiguration;
200 | buildSettings = {
201 | ALWAYS_SEARCH_USER_PATHS = NO;
202 | CLANG_ANALYZER_NONNULL = YES;
203 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
204 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
205 | CLANG_CXX_LIBRARY = "libc++";
206 | CLANG_ENABLE_MODULES = YES;
207 | CLANG_ENABLE_OBJC_ARC = YES;
208 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
209 | CLANG_WARN_BOOL_CONVERSION = YES;
210 | CLANG_WARN_COMMA = YES;
211 | CLANG_WARN_CONSTANT_CONVERSION = YES;
212 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
213 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
214 | CLANG_WARN_EMPTY_BODY = YES;
215 | CLANG_WARN_ENUM_CONVERSION = YES;
216 | CLANG_WARN_INFINITE_RECURSION = YES;
217 | CLANG_WARN_INT_CONVERSION = YES;
218 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
219 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
220 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
221 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
222 | CLANG_WARN_STRICT_PROTOTYPES = YES;
223 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
224 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
225 | CLANG_WARN_UNREACHABLE_CODE = YES;
226 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
227 | CODE_SIGN_IDENTITY = "iPhone Developer";
228 | COPY_PHASE_STRIP = NO;
229 | DEBUG_INFORMATION_FORMAT = dwarf;
230 | ENABLE_STRICT_OBJC_MSGSEND = YES;
231 | ENABLE_TESTABILITY = YES;
232 | GCC_C_LANGUAGE_STANDARD = gnu11;
233 | GCC_DYNAMIC_NO_PIC = NO;
234 | GCC_NO_COMMON_BLOCKS = YES;
235 | GCC_OPTIMIZATION_LEVEL = 0;
236 | GCC_PREPROCESSOR_DEFINITIONS = (
237 | "DEBUG=1",
238 | "$(inherited)",
239 | );
240 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
241 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
242 | GCC_WARN_UNDECLARED_SELECTOR = YES;
243 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
244 | GCC_WARN_UNUSED_FUNCTION = YES;
245 | GCC_WARN_UNUSED_VARIABLE = YES;
246 | IPHONEOS_DEPLOYMENT_TARGET = 11.1;
247 | MTL_ENABLE_DEBUG_INFO = YES;
248 | ONLY_ACTIVE_ARCH = YES;
249 | SDKROOT = iphoneos;
250 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
251 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
252 | };
253 | name = Debug;
254 | };
255 | D6439B7120577A9600EFF8AF /* Release */ = {
256 | isa = XCBuildConfiguration;
257 | buildSettings = {
258 | ALWAYS_SEARCH_USER_PATHS = NO;
259 | CLANG_ANALYZER_NONNULL = YES;
260 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
261 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
262 | CLANG_CXX_LIBRARY = "libc++";
263 | CLANG_ENABLE_MODULES = YES;
264 | CLANG_ENABLE_OBJC_ARC = YES;
265 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
266 | CLANG_WARN_BOOL_CONVERSION = YES;
267 | CLANG_WARN_COMMA = YES;
268 | CLANG_WARN_CONSTANT_CONVERSION = YES;
269 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
270 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
271 | CLANG_WARN_EMPTY_BODY = YES;
272 | CLANG_WARN_ENUM_CONVERSION = YES;
273 | CLANG_WARN_INFINITE_RECURSION = YES;
274 | CLANG_WARN_INT_CONVERSION = YES;
275 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
276 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
277 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
278 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
279 | CLANG_WARN_STRICT_PROTOTYPES = YES;
280 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
281 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
282 | CLANG_WARN_UNREACHABLE_CODE = YES;
283 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
284 | CODE_SIGN_IDENTITY = "iPhone Developer";
285 | COPY_PHASE_STRIP = NO;
286 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
287 | ENABLE_NS_ASSERTIONS = NO;
288 | ENABLE_STRICT_OBJC_MSGSEND = YES;
289 | GCC_C_LANGUAGE_STANDARD = gnu11;
290 | GCC_NO_COMMON_BLOCKS = YES;
291 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
292 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
293 | GCC_WARN_UNDECLARED_SELECTOR = YES;
294 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
295 | GCC_WARN_UNUSED_FUNCTION = YES;
296 | GCC_WARN_UNUSED_VARIABLE = YES;
297 | IPHONEOS_DEPLOYMENT_TARGET = 11.1;
298 | MTL_ENABLE_DEBUG_INFO = NO;
299 | SDKROOT = iphoneos;
300 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
301 | VALIDATE_PRODUCT = YES;
302 | };
303 | name = Release;
304 | };
305 | D6439B7320577A9600EFF8AF /* Debug */ = {
306 | isa = XCBuildConfiguration;
307 | buildSettings = {
308 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
309 | CODE_SIGN_STYLE = Automatic;
310 | INFOPLIST_FILE = A_J_Dot_Loading_Indicator/Info.plist;
311 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
312 | PRODUCT_BUNDLE_IDENTIFIER = "io.github.pigfly.A-J-Dot-Loading-Indicator";
313 | PRODUCT_NAME = "$(TARGET_NAME)";
314 | SWIFT_VERSION = 4.0;
315 | TARGETED_DEVICE_FAMILY = "1,2";
316 | };
317 | name = Debug;
318 | };
319 | D6439B7420577A9600EFF8AF /* Release */ = {
320 | isa = XCBuildConfiguration;
321 | buildSettings = {
322 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
323 | CODE_SIGN_STYLE = Automatic;
324 | INFOPLIST_FILE = A_J_Dot_Loading_Indicator/Info.plist;
325 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
326 | PRODUCT_BUNDLE_IDENTIFIER = "io.github.pigfly.A-J-Dot-Loading-Indicator";
327 | PRODUCT_NAME = "$(TARGET_NAME)";
328 | SWIFT_VERSION = 4.0;
329 | TARGETED_DEVICE_FAMILY = "1,2";
330 | };
331 | name = Release;
332 | };
333 | /* End XCBuildConfiguration section */
334 |
335 | /* Begin XCConfigurationList section */
336 | D6439B5B20577A9600EFF8AF /* Build configuration list for PBXProject "A_J_Dot_Loading_Indicator" */ = {
337 | isa = XCConfigurationList;
338 | buildConfigurations = (
339 | D6439B7020577A9600EFF8AF /* Debug */,
340 | D6439B7120577A9600EFF8AF /* Release */,
341 | );
342 | defaultConfigurationIsVisible = 0;
343 | defaultConfigurationName = Release;
344 | };
345 | D6439B7220577A9600EFF8AF /* Build configuration list for PBXNativeTarget "A_J_Dot_Loading_Indicator" */ = {
346 | isa = XCConfigurationList;
347 | buildConfigurations = (
348 | D6439B7320577A9600EFF8AF /* Debug */,
349 | D6439B7420577A9600EFF8AF /* Release */,
350 | );
351 | defaultConfigurationIsVisible = 0;
352 | defaultConfigurationName = Release;
353 | };
354 | /* End XCConfigurationList section */
355 | };
356 | rootObject = D6439B5820577A9600EFF8AF /* Project object */;
357 | }
358 |
--------------------------------------------------------------------------------