Skip to content

Commit c9bcc71

Browse files
committed
Release 1.0
1 parent a4e9a6c commit c9bcc71

File tree

6 files changed

+555
-6
lines changed

6 files changed

+555
-6
lines changed

README.md

Lines changed: 105 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,112 @@
11
# SPAlert
2-
Native popup alert similar to Apple Music or Feedback in AppStore app. Support animations. **Now in develop**. If you want to follow the project, **put a star ✯**
2+
Native popup alert similar to Apple Music or Feedback in AppStore app. Support animations.<br>**Now in develop**. If you want to follow the project, **put a star ✯**
33

44
### Preview
5+
56
<img src="https://github.com/IvanVorobei/SPAlert/blob/master/Resources/Preview.gif" height="450">
67

8+
Soon I am add cool preview)
9+
10+
## Navigate
11+
12+
- [Requirements](#requirements)
13+
- [Installation](#installation)
14+
- [Quick Start](#quick-start)
15+
- [Usage](#usage)
16+
- [Duration](#duration)
17+
- [Layout](#layout)
18+
- [Dismiss by Tap](#dismiss-by-tap)
19+
- [Corner Radius](#corner-radius)
20+
- [Other Projects (+gif)](#my-projects)
21+
- [SPStorkController](#spstorkcontroller)
22+
- [SPLarkController](#splarkcontroller)
23+
- [SPPermission](#sppermission)
24+
- [Xcode Shop](#xcode-shop)
25+
- [License](#license)
26+
- [Contact or Order Develop](#contact)
27+
28+
## Requirements
29+
30+
Swift 4.2 & **5.0**. Ready for use on iOS 10+
31+
32+
## Installation
33+
34+
### CocoaPods:
35+
36+
[CocoaPods](https://cocoapods.org) is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate `SPAlert` into your Xcode project using CocoaPods, specify it in your `Podfile`:
37+
38+
```ruby
39+
pod 'SPAlert'
40+
```
41+
42+
### Manually
43+
44+
If you prefer not to use any of the aforementioned dependency managers, you can integrate `SPAlert` into your project manually. Put `Source/SPAlert` folder in your Xcode project. Make sure to enable `Copy items if needed` and `Create groups`.
45+
46+
## Quick Start
47+
48+
For best experience, I recomend call alerts by `SPAlert`. These functions are updated regularly and show as Apple way. I focus on presets:
49+
50+
```swift
51+
SPAlert.present(title: "Added to Library", preset: .done)
52+
```
53+
54+
Currently there are few presets. If you want **to add a new preset**, create a [issue](https://github.com/IvanVorobei/SPAlert/issues) and describe how you see it. I will try to quickly add new presets.
55+
56+
57+
If you want use custom image, use func:
58+
59+
```swift
60+
SPAlert.present(title: "Love", message: "We'll recommend more like this in For You", image: UIImage(named: "Heart")!)
61+
```
62+
63+
For show simple text message, use:
64+
65+
```swift
66+
SPAlert.present(message: "Empty UITextField")
67+
```
68+
69+
## Usage
70+
71+
Sometimes it may require deep customization. In this section, I will show you what you can do.
72+
73+
### Duration
74+
75+
To change the time that the `SPAlert` will be shown, use property `duration`:
76+
77+
```swift
78+
let alertView = SPAlertView(title: "Added to Library", message: nil, preset: SPAlertPreset.done)
79+
alertView.duration = 3
80+
alertView.present()
81+
```
82+
83+
### Layout
84+
85+
Here you can change the size and size:
86+
87+
```swift
88+
alertView.layout.topSpace = 18
89+
alertView.layout.iconHeight = 25
90+
```
91+
92+
For more properties see class.
93+
94+
### Dismiss by Tap
95+
96+
If you click on the alert, it will disappear ahead of time. This can be disabled:
97+
98+
```swift
99+
alertView.dismissByTap = false
100+
```
101+
102+
### Corner Radius
103+
104+
I use a corner radius like an Apple. If you need to change it, see the property `cornerRadius`:
105+
106+
```swift
107+
alertView.cornerRadius = 12
108+
```
109+
7110
## My projects
8111

9112
### SPStorkController
@@ -30,7 +133,7 @@ You can download [Code - Learn Swift & Design](https://itunes.apple.com/app/id14
30133

31134
### Xcode Shop
32135

33-
If you want **buy apps with source code**, you can visit my [xcode-shop.com](xcode-shop.com). Here I am sale apps, modules, 3D elements and other. In applications you can find many cool UI that will be useful for your projects. Also by buying, **you support me** and my free GitHub development.
136+
If you want **buy apps with source code**, you can visit my [xcode-shop.com](https://xcode-shop.com). Here I am sale apps, modules, 3D elements and other. In applications you can find many cool UI that will be useful for your projects. Also by buying, **you support me** and my free GitHub development.
34137

35138
## License
36139
`SPAlert` is released under the MIT license. Check `LICENSE.md` for details.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// The MIT License (MIT)
2+
// Copyright © 2019 Ivan Vorobei ([email protected])
3+
//
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy
5+
// of this software and associated documentation files (the "Software"), to deal
6+
// in the Software without restriction, including without limitation the rights
7+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
// copies of the Software, and to permit persons to whom the Software is
9+
// furnished to do so, subject to the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included in all
12+
// copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
// SOFTWARE.
21+
22+
import UIKit
23+
24+
public class SPAlertIconDoneView: UIView, SPAlertIconAnimatable {
25+
26+
public func animate() {
27+
28+
let length = frame.width
29+
let animatablePath = UIBezierPath()
30+
animatablePath.move(to: CGPoint(x: length * 0.196, y: length * 0.527))
31+
animatablePath.addLine(to: CGPoint(x: length * 0.47, y: length * 0.777))
32+
animatablePath.addLine(to: CGPoint(x: length * 0.99, y: length * 0.25))
33+
34+
let animatableLayer = CAShapeLayer()
35+
animatableLayer.path = animatablePath.cgPath
36+
animatableLayer.fillColor = UIColor.clear.cgColor
37+
animatableLayer.strokeColor = tintColor?.cgColor
38+
animatableLayer.lineWidth = 9
39+
animatableLayer.lineCap = .round
40+
animatableLayer.lineJoin = .round
41+
animatableLayer.strokeEnd = 0
42+
self.layer.addSublayer(animatableLayer)
43+
44+
let animation = CABasicAnimation(keyPath: "strokeEnd")
45+
animation.duration = 0.3
46+
animation.fromValue = 0
47+
animation.toValue = 1
48+
animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
49+
animatableLayer.strokeEnd = 1
50+
animatableLayer.add(animation, forKey: "animation")
51+
}
52+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// The MIT License (MIT)
2+
// Copyright © 2019 Ivan Vorobei ([email protected])
3+
//
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy
5+
// of this software and associated documentation files (the "Software"), to deal
6+
// in the Software without restriction, including without limitation the rights
7+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
// copies of the Software, and to permit persons to whom the Software is
9+
// furnished to do so, subject to the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included in all
12+
// copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
// SOFTWARE.
21+
22+
import UIKit
23+
24+
public class SPAlertIconHeartView: UIView {
25+
26+
init() {
27+
super.init(frame: .zero)
28+
self.backgroundColor = .clear
29+
}
30+
31+
required init?(coder aDecoder: NSCoder) {
32+
fatalError("init(coder:) has not been implemented")
33+
}
34+
35+
public override func draw(_ rect: CGRect) {
36+
super.draw(rect)
37+
HeartStyleKit.drawHeart(frame: rect, resizing: .aspectFit, fillColor: self.tintColor)
38+
}
39+
}
40+
41+
class HeartStyleKit : NSObject {
42+
43+
@objc dynamic public class func drawHeart(frame targetFrame: CGRect = CGRect(x: 0, y: 0, width: 510, height: 470), resizing: ResizingBehavior = .aspectFit, fillColor: UIColor = UIColor(red: 0.000, green: 0.000, blue: 0.000, alpha: 1.000)) {
44+
45+
let context = UIGraphicsGetCurrentContext()!
46+
47+
context.saveGState()
48+
let resizedFrame: CGRect = resizing.apply(rect: CGRect(x: 0, y: 0, width: 510, height: 470), target: targetFrame)
49+
context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY)
50+
context.scaleBy(x: resizedFrame.width / 510, y: resizedFrame.height / 470)
51+
52+
let bezierPath = UIBezierPath()
53+
bezierPath.move(to: CGPoint(x: 255, y: 469.6))
54+
bezierPath.addLine(to: CGPoint(x: 219.3, y: 433.9))
55+
bezierPath.addCurve(to: CGPoint(x: 0, y: 140.65), controlPoint1: CGPoint(x: 86.7, y: 316.6), controlPoint2: CGPoint(x: 0, y: 237.55))
56+
bezierPath.addCurve(to: CGPoint(x: 140.25, y: 0.4), controlPoint1: CGPoint(x: 0, y: 61.6), controlPoint2: CGPoint(x: 61.2, y: 0.4))
57+
bezierPath.addCurve(to: CGPoint(x: 255, y: 53.95), controlPoint1: CGPoint(x: 183.6, y: 0.4), controlPoint2: CGPoint(x: 226.95, y: 20.8))
58+
bezierPath.addCurve(to: CGPoint(x: 369.75, y: 0.4), controlPoint1: CGPoint(x: 283.05, y: 20.8), controlPoint2: CGPoint(x: 326.4, y: 0.4))
59+
bezierPath.addCurve(to: CGPoint(x: 510, y: 140.65), controlPoint1: CGPoint(x: 448.8, y: 0.4), controlPoint2: CGPoint(x: 510, y: 61.6))
60+
bezierPath.addCurve(to: CGPoint(x: 290.7, y: 433.9), controlPoint1: CGPoint(x: 510, y: 237.55), controlPoint2: CGPoint(x: 423.3, y: 316.6))
61+
bezierPath.addLine(to: CGPoint(x: 255, y: 469.6))
62+
bezierPath.close()
63+
fillColor.setFill()
64+
bezierPath.fill()
65+
66+
context.restoreGState()
67+
}
68+
69+
@objc(HeartStyleKitResizingBehavior)
70+
public enum ResizingBehavior: Int {
71+
case aspectFit
72+
case aspectFill
73+
case stretch
74+
case center
75+
76+
public func apply(rect: CGRect, target: CGRect) -> CGRect {
77+
if rect == target || target == CGRect.zero {
78+
return rect
79+
}
80+
81+
var scales = CGSize.zero
82+
scales.width = abs(target.width / rect.width)
83+
scales.height = abs(target.height / rect.height)
84+
85+
switch self {
86+
case .aspectFit:
87+
scales.width = min(scales.width, scales.height)
88+
scales.height = scales.width
89+
case .aspectFill:
90+
scales.width = max(scales.width, scales.height)
91+
scales.height = scales.width
92+
case .stretch:
93+
break
94+
case .center:
95+
scales.width = 1
96+
scales.height = 1
97+
}
98+
99+
var result = rect.standardized
100+
result.size.width *= scales.width
101+
result.size.height *= scales.height
102+
result.origin.x = target.minX + (target.width - result.width) / 2
103+
result.origin.y = target.minY + (target.height - result.height) / 2
104+
return result
105+
}
106+
}
107+
}
108+

Source/SPAlert/SPAlert.swift

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// The MIT License (MIT)
2-
// Copyright © 2017 Ivan Vorobei ([email protected])
2+
// Copyright © 2019 Ivan Vorobei ([email protected])
33
//
44
// Permission is hereby granted, free of charge, to any person obtaining a copy
55
// of this software and associated documentation files (the "Software"), to deal
@@ -21,4 +21,21 @@
2121

2222
import UIKit
2323

24-
enum SPAlert {}
24+
public enum SPAlert {
25+
26+
27+
public static func present(title: String, message: String? = nil, preset: SPAlertPreset) {
28+
let alertView = SPAlertView(title: title, message: message, preset: preset)
29+
alertView.present()
30+
}
31+
32+
public static func present(title: String, message: String? = nil, image: UIImage) {
33+
let alertView = SPAlertView(title: title, message: message, image: image)
34+
alertView.present()
35+
}
36+
37+
public static func present(message: String) {
38+
let alertView = SPAlertView(message: message)
39+
alertView.present()
40+
}
41+
}

Source/SPAlert/SPAlertPreset.swift

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// The MIT License (MIT)
2+
// Copyright © 2019 Ivan Vorobei ([email protected])
3+
//
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy
5+
// of this software and associated documentation files (the "Software"), to deal
6+
// in the Software without restriction, including without limitation the rights
7+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
// copies of the Software, and to permit persons to whom the Software is
9+
// furnished to do so, subject to the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included in all
12+
// copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
// SOFTWARE.
21+
22+
import UIKit
23+
24+
public enum SPAlertPreset {
25+
26+
case done
27+
case heart
28+
29+
var iconView: UIView {
30+
switch self {
31+
case .done:
32+
return SPAlertIconDoneView()
33+
case .heart:
34+
return SPAlertIconHeartView()
35+
}
36+
}
37+
38+
var layout: SPAlertLayout {
39+
switch self {
40+
case .done:
41+
var layout = SPAlertLayout()
42+
layout.topSpace = 63
43+
layout.bottomSpace = 29
44+
layout.iconWidth = 112
45+
layout.iconHeight = 112
46+
layout.bottomIconSpace = 35
47+
return layout
48+
case .heart:
49+
var layout = SPAlertLayout()
50+
layout.topSpace = 49
51+
layout.bottomSpace = 25
52+
layout.iconWidth = 112
53+
layout.iconHeight = 77
54+
layout.bottomIconSpace = 35
55+
return layout
56+
}
57+
}
58+
}
59+
60+
public struct SPAlertLayout {
61+
62+
public var topSpace: CGFloat = 43
63+
public var bottomSpace: CGFloat = 25
64+
public var iconWidth: CGFloat = 100
65+
public var iconHeight: CGFloat = 100
66+
public var bottomIconSpace: CGFloat = 41
67+
}
68+
69+
public protocol SPAlertIconAnimatable {
70+
71+
func animate()
72+
}

0 commit comments

Comments
 (0)