├── SwiftEasyPop.jpg
├── Sources
├── SwiftEasyPop
│ └── SwiftEasyPop.swift
├── Resources
│ └── Fonts
│ │ ├── Poppins-Bold.ttf
│ │ ├── Poppins-Medium.ttf
│ │ ├── Poppins-Regular.ttf
│ │ └── Poppins-SemiBold.ttf
├── Helper
│ ├── BlurView.swift
│ ├── CleanerView.swift
│ ├── CGFloatExt.swift
│ ├── TextModifier.swift
│ └── UIColorExt.swift
├── PoppinsFont.swift
├── EasyAlertPop.swift
└── EasyToastView.swift
├── SwiftEasyPopPackageExample
├── SwiftEasyPopPackageExample
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Preview Content
│ │ └── Preview Assets.xcassets
│ │ │ └── Contents.json
│ ├── SwiftEasyPopPackageExampleApp.swift
│ └── ContentView.swift
└── SwiftEasyPopPackageExample.xcodeproj
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── db.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ ├── xcuserdata
│ └── db.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
│ └── project.pbxproj
├── .gitignore
├── Tests
└── SwiftEasyPopTests
│ └── SwiftEasyPopTests.swift
├── Package.swift
├── LICENSE
└── README.md
/SwiftEasyPop.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tunahancelik/SwiftEasyPop/HEAD/SwiftEasyPop.jpg
--------------------------------------------------------------------------------
/Sources/SwiftEasyPop/SwiftEasyPop.swift:
--------------------------------------------------------------------------------
1 | // The Swift Programming Language
2 | // https://docs.swift.org/swift-book
3 |
--------------------------------------------------------------------------------
/Sources/Resources/Fonts/Poppins-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tunahancelik/SwiftEasyPop/HEAD/Sources/Resources/Fonts/Poppins-Bold.ttf
--------------------------------------------------------------------------------
/Sources/Resources/Fonts/Poppins-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tunahancelik/SwiftEasyPop/HEAD/Sources/Resources/Fonts/Poppins-Medium.ttf
--------------------------------------------------------------------------------
/Sources/Resources/Fonts/Poppins-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tunahancelik/SwiftEasyPop/HEAD/Sources/Resources/Fonts/Poppins-Regular.ttf
--------------------------------------------------------------------------------
/Sources/Resources/Fonts/Poppins-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tunahancelik/SwiftEasyPop/HEAD/Sources/Resources/Fonts/Poppins-SemiBold.ttf
--------------------------------------------------------------------------------
/SwiftEasyPopPackageExample/SwiftEasyPopPackageExample/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/SwiftEasyPopPackageExample/SwiftEasyPopPackageExample/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | xcuserdata/
5 | DerivedData/
6 | .swiftpm/configuration/registries.json
7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8 | .netrc
9 |
--------------------------------------------------------------------------------
/SwiftEasyPopPackageExample/SwiftEasyPopPackageExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SwiftEasyPopPackageExample/SwiftEasyPopPackageExample/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/SwiftEasyPopPackageExample/SwiftEasyPopPackageExample.xcodeproj/project.xcworkspace/xcuserdata/db.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tunahancelik/SwiftEasyPop/HEAD/SwiftEasyPopPackageExample/SwiftEasyPopPackageExample.xcodeproj/project.xcworkspace/xcuserdata/db.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/SwiftEasyPopPackageExample/SwiftEasyPopPackageExample/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/SwiftEasyPopPackageExample/SwiftEasyPopPackageExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SwiftEasyPopPackageExample/SwiftEasyPopPackageExample/SwiftEasyPopPackageExampleApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftEasyPopPackageExampleApp.swift
3 | // SwiftEasyPopPackageExample
4 | //
5 | // Created by tnhn on 2.01.2024.
6 | //
7 |
8 | import SwiftUI
9 |
10 | @main
11 | struct SwiftEasyPopPackageExampleApp: App {
12 | var body: some Scene {
13 | WindowGroup {
14 | ContentView()
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Tests/SwiftEasyPopTests/SwiftEasyPopTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import SwiftEasyPop
3 |
4 | final class SwiftEasyPopTests: XCTestCase {
5 | func testExample() throws {
6 | // XCTest Documentation
7 | // https://developer.apple.com/documentation/xctest
8 |
9 | // Defining Test Cases and Test Methods
10 | // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/SwiftEasyPopPackageExample/SwiftEasyPopPackageExample.xcodeproj/xcuserdata/db.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | SwiftEasyPopPackageExample.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.9
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "SwiftEasyPop",
8 | products: [
9 | // Products define the executables and libraries a package produces, making them visible to other packages.
10 | .library(
11 | name: "SwiftEasyPop",
12 | targets: ["SwiftEasyPop"]),
13 | ],
14 | targets: [
15 | // Targets are the basic building blocks of a package, defining a module or a test suite.
16 | // Targets can depend on other targets in this package and products from dependencies.
17 | .target(
18 | name: "SwiftEasyPop",
19 | path: "Sources",
20 | resources: [
21 | .process("Resources")
22 | ]
23 | ),
24 | .testTarget(
25 | name: "SwiftEasyPopTests",
26 | dependencies: ["SwiftEasyPop"]),
27 | ]
28 | )
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Tunahan Çelik
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 |
--------------------------------------------------------------------------------
/Sources/Helper/BlurView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BlurView.swift
3 | //
4 | //
5 | // Created by tnhn on 2.01.2024.
6 | //
7 |
8 | import SwiftUI
9 |
10 | //MARK: - BackgroundBlurView
11 | @available(iOS 14.0, *)
12 | /// `BackgroundBlurView` creates a blur effect overlay in a SwiftUI view.
13 | ///
14 | /// This view is a SwiftUI wrapper around the `UIVisualEffectView` from UIKit to create a light blur effect.
15 | /// It can be used as a background in SwiftUI views to blur the content underneath.
16 | struct BlurView: UIViewRepresentable {
17 |
18 | /// Creates a `UIView` instance to be managed by SwiftUI.
19 | ///
20 | /// - Parameter context: The context in which the view is created.
21 | /// - Returns: A `UIVisualEffectView` configured with a light blur effect.
22 | func makeUIView(context: Context) -> UIView {
23 | let view = UIVisualEffectView(effect: UIBlurEffect(style: .light))
24 | DispatchQueue.main.async {
25 | view.superview?.superview?.backgroundColor = .clear
26 | }
27 | return view
28 | }
29 |
30 | /// Updates the state of the specified view with new information from SwiftUI.
31 | ///
32 | /// In this implementation, this function does not perform any actions.
33 | ///
34 | /// - Parameters:
35 | /// - uiView: The `UIView` instance to update.
36 | /// - context: The context in which the update occurs.
37 | func updateUIView(_ uiView: UIView, context: Context) {}
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/Helper/CleanerView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CleanerView.swift
3 | //
4 | //
5 | // Created by tnhn on 2.01.2024.
6 | //
7 |
8 | import SwiftUI
9 |
10 | @available(iOS 14.0, *)
11 | /// `BackgroundCleanerView` is a view modifier that sets the background of the superviews to clear.
12 | ///
13 | /// This struct creates a transparent `UIView` and uses it to modify the background color of its superviews to clear.
14 | /// It's useful in situations where you need to remove or clean up unwanted background colors from SwiftUI views.
15 | struct CleanerView: UIViewRepresentable {
16 |
17 | /// Creates a `UIView` instance to be managed by SwiftUI.
18 | ///
19 | /// This method creates a transparent `UIView` and is intended to modify the background color of its superviews to clear.
20 | /// - Parameter context: The context in which the view is created.
21 | /// - Returns: A transparent `UIView` instance.
22 | func makeUIView(context: Context) -> UIView {
23 | let view = UIView()
24 | DispatchQueue.main.async {
25 | view.superview?.superview?.backgroundColor = .clear
26 | }
27 | return view
28 | }
29 |
30 | /// Updates the state of the specified view with new information from SwiftUI.
31 | ///
32 | /// In this implementation, this function does not perform any actions as the view is static and does not need updates.
33 | ///
34 | /// - Parameters:
35 | /// - uiView: The `UIView` instance to update.
36 | /// - context: The context in which the update occurs.
37 | func updateUIView(_ uiView: UIView, context: Context) {
38 | // This implementation intentionally left empty
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Sources/Helper/CGFloatExt.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CGFloatExt.swift
3 | //
4 | //
5 | // Created by tnhn on 2.01.2024.
6 | //
7 |
8 | import SwiftUI
9 |
10 | extension CGFloat{
11 | /// Initializes a CGFloat value scaled for a specific width, considering the device type (iPad or iPhone).
12 | ///
13 | /// On iPads, it returns the original width value. On iPhones, if a height is provided, it scales the width based on the aspect ratio.
14 | /// Otherwise, it scales the width based on the screen width of the iPhone.
15 | ///
16 | /// - Parameters:
17 | /// - width: The original width to be scaled.
18 | /// - height: An optional height to maintain aspect ratio on iPhones. Defaults to 0, which ignores aspect ratio.
19 | init(width: CGFloat, for height: CGFloat = 0){
20 | if UIDevice.current.userInterfaceIdiom == .pad {
21 | self.init(width)
22 | }else{
23 | if height > 0{
24 | self.init(.init(height: height) * width / height)
25 | }else{
26 | self.init(width / 414 * UIScreen.main.bounds.size.width)
27 | }
28 | }
29 | }
30 |
31 | /// Initializes a CGFloat value scaled for a specific height, considering the device type (iPad or iPhone).
32 | ///
33 | /// On iPads, it returns the original height value. On iPhones, if a width is provided, it scales the height based on the aspect ratio.
34 | /// Otherwise, it scales the height based on the screen height of the iPhone.
35 | ///
36 | /// - Parameters:
37 | /// - height: The original height to be scaled.
38 | /// - width: An optional width to maintain aspect ratio on iPhones. Defaults to 0, which ignores aspect ratio.
39 | init(height: CGFloat, for width: CGFloat = 0){
40 | if UIDevice.current.userInterfaceIdiom == .pad {
41 | self.init(height)
42 | }else{
43 | if width > 0{
44 | self.init(.init(width: width) * height / width)
45 | }else{
46 | self.init(height / 896 * UIScreen.main.bounds.size.height)
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SwiftEasyPop
2 |
3 | SwiftEasyPop is a lightweight and easy-to-use SwiftUI library for displaying custom alerts and toasts in a Swift application. It provides a flexible way to present customizable alerts and toasts with minimal setup.
4 |
5 | ## Features
6 |
7 | - 🚀 Simple and intuitive API for showing alerts and toasts.
8 | - 🎨 Highly customizable, supporting custom icons, colors, and messages.
9 | - 📱 Compatible with iOS 14.0+.
10 | - 🔄 Supports both light and dark mode.
11 |
12 | 
13 |
14 | ## Installation
15 |
16 | ### Swift Package Manager
17 |
18 | You can add SwiftEasyPop to your project via Swift Package Manager. Add the following dependency to your `Package.swift` file:
19 |
20 | ```swift
21 | dependencies: [
22 | .package(url: "https://github.com/tunahancelik/SwiftEasyPop.git", from: "1.0.0")
23 | ]
24 | ```
25 | ## Usage
26 | Import SwiftEasyPop into your SwiftUI view and use the provided modifiers to present alerts and toasts.
27 |
28 | ```swift
29 | import SwiftUI
30 | import SwiftEasyPop
31 |
32 | struct ContentView: View {
33 | @State private var showAlert = false
34 | @State private var showToast: EasyToastView? = nil
35 |
36 | var body: some View {
37 | // Your view code
38 | }
39 | }
40 | ```
41 |
42 | ### Showing an Alert
43 | ```swift
44 | // Use EasyAlertPop to show custom alerts
45 | Button("Show Alert") {
46 | showAlert = true
47 | }
48 | .easyAlertPop(presentAlert: $showAlert, alertType: .constant(.oneButton(...)))
49 | ```
50 | ### Showing a Toast
51 | ```swift
52 | // Use EasyToastView to show custom toasts
53 | Button("Show Toast") {
54 | showToast = EasyToastView(...)
55 | }
56 | .toastView(toast: $showToast)
57 | ````
58 | ### Customization
59 | SwiftEasyPop allows for extensive customization of alerts and toasts. You can set custom icons, messages, colors, and more.
60 |
61 | ### Contribution
62 | Contributions are welcome! Please read the contribution guidelines first.
63 |
64 | ### License
65 | SwiftEasyPop is released under the MIT License.
66 |
67 | [](https://www.buymeacoffee.com/tunahancelik)
68 |
--------------------------------------------------------------------------------
/Sources/Helper/TextModifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TextModifier.swift
3 | //
4 | //
5 | // Created by tnhn on 2.01.2024.
6 | //
7 |
8 | import SwiftUI
9 |
10 | /// A `ViewModifier` to apply custom styling to text views.
11 | ///
12 | /// This modifier can be used to uniformly style text across your application.
13 | /// It applies multiple text alignment, font, foreground color, and line limit to the content.
14 | @available(iOS 14.0, *)
15 | struct TextModifier: ViewModifier {
16 |
17 | let multiTextAlignment: TextAlignment
18 | let font: Font
19 | let foregroundColor: Color
20 | let lineLimit: Int
21 |
22 | /// Modifies the content view with text-related styles.
23 | ///
24 | /// - Parameter content: The content view to which the styles will be applied.
25 | /// - Returns: A modified view with the specified text styles.
26 | func body(content: Content) -> some View {
27 | content
28 | .multilineTextAlignment(multiTextAlignment)
29 | .font(font)
30 | .foregroundColor(foregroundColor)
31 | .lineLimit(lineLimit)
32 | }
33 | }
34 |
35 | /// An extension on `View` to provide an easy way to apply the `TextModifier`.
36 | ///
37 | /// This extension adds a `textVM` method to any SwiftUI view, allowing for easy customization of text-related properties.
38 | @available(iOS 14.0, *)
39 | extension View {
40 |
41 | /// Applies custom text styling to the view.
42 | ///
43 | /// This method is a convenient way to apply common text styles like alignment, font, foreground style, and line limit.
44 | ///
45 | /// - Parameters:
46 | /// - multiTextAlignment: The alignment of the text within the view.
47 | /// - font: The font to be used for the text.
48 | /// - foregroundStyle: The color of the text.
49 | /// - lineLimit: The maximum number of lines for the text. A value of 0 means no limit.
50 | /// - Returns: The view with the applied text styling.
51 | func textVM(
52 | multiTextAlignment: TextAlignment,
53 | font: Font,
54 | foregroundStyle: Color,
55 | lineLimit: Int = 0
56 |
57 | ) -> some View {
58 |
59 | modifier(TextModifier(
60 | multiTextAlignment: multiTextAlignment,
61 | font: font,
62 | foregroundColor: foregroundStyle,
63 | lineLimit: lineLimit
64 | ))
65 |
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Sources/PoppinsFont.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PoppinsFont.swift
3 | //
4 | //
5 | // Created by tnhn on 2.01.2024.
6 | //
7 |
8 | import SwiftUI
9 |
10 | /// An enumeration representing the different weights of the Poppins font.
11 | ///
12 | /// - `regular`: The regular weight of the Poppins font.
13 | /// - `medium`: The medium weight of the Poppins font.
14 | /// - `semiBold`: The semi-bold weight of the Poppins font.
15 | /// - `bold`: The bold weight of the Poppins font.
16 | public enum Poppins: String, CaseIterable {
17 | case regular = "Poppins-Regular"
18 | case medium = "Poppins-Medium"
19 | case semiBold = "Poppins-SemiBold"
20 | case bold = "Poppins-Bold"
21 | }
22 |
23 | @available(iOS 14.0, *)
24 | extension Font {
25 | /// Creates a font with the specified Poppins style and size.
26 | ///
27 | /// - Parameters:
28 | /// - poppins: The Poppins font weight to use.
29 | /// - size: The size of the font.
30 | /// - Returns: A `Font` object with the specified Poppins style and size.
31 | public static func poppins(_ poppins: Poppins, size: CGFloat) -> Font {
32 | return .custom(poppins.rawValue, size: size, relativeTo: .body)
33 | }
34 | }
35 |
36 | public struct PoppinsFont {
37 | /// A utility struct for registering Poppins fonts.
38 | ///
39 | /// Use `registerFonts` to load and register all Poppins font weights contained in the app bundle.
40 | public static func registerFonts(){
41 | Poppins.allCases.forEach {
42 | registerFont(bundle: .module, fontName: $0.rawValue, fontExtension: "ttf")
43 | }
44 | }
45 |
46 | /// Registers a font with the given bundle, font name, and extension.
47 | ///
48 | /// - Parameters:
49 | /// - bundle: The bundle containing the font file.
50 | /// - fontName: The name of the font file.
51 | /// - fontExtension: The extension of the font file.
52 | fileprivate static func registerFont(bundle: Bundle, fontName: String, fontExtension: String) {
53 | guard let fontURL = bundle.url(forResource: fontName, withExtension: fontExtension), let fontDataProvider = CGDataProvider(url: fontURL as CFURL), let font = CGFont(fontDataProvider) else {
54 | fatalError("couldn't create font from filename")
55 | }
56 |
57 | var error: Unmanaged?
58 | CTFontManagerRegisterGraphicsFont(font, &error)
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/SwiftEasyPopPackageExample/SwiftEasyPopPackageExample/ContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ContentView.swift
3 | // SwiftEasyPopPackageExample
4 | //
5 | // Created by tnhn on 2.01.2024.
6 | //
7 |
8 | import SwiftUI
9 | import SwiftEasyPop
10 |
11 | struct ContentView: View {
12 | /// State variables to control the presentation of the alert and toast
13 | @State private var toast: EasyToastView? = nil
14 | @State private var presentAlert: Bool = false
15 |
16 | var body: some View {
17 | ZStack {
18 | VStack {
19 | // Button to show an alert
20 | Button("Show Alert") {
21 | presentAlert = true
22 | }
23 | .buttonStyle(.borderedProminent)
24 |
25 | // Button to show a toast
26 | Button("Show Toast") {
27 | /*
28 | Examples Toast Messages
29 | */
30 |
31 | // toast = EasyToastView(type: .success, title: "Success", message: "This is success message", duration: 6.0)
32 |
33 | toast = EasyToastView(type: .custom, title: "Custom", message: "This is custom message",iconName: "lamp.desk",customColor: .indigo, duration: 6.0)
34 | // toast = EasyToastView(type: .error, title: "Error", message: "This is error message", duration: 6.0)
35 | // toast = EasyToastView(type: .info, title: "Info", message: "This is info message", duration: 6.0)
36 | // toast = EasyToastView(type: .warning, title: "Warning", message: "This is warning message")
37 | }
38 | .buttonStyle(.borderedProminent)
39 |
40 | }
41 | .padding()
42 |
43 | // Presenting a custom alert
44 | if presentAlert{
45 | EasyAlertPop(presentAlert: $presentAlert, alertType: .constant(.oneButton(title: "Do you want to delete?", message: "If you delete this file then you won’t please again check everything"))){ withAnimation{ presentAlert.toggle() }
46 | } rightButtonAction: { withAnimation{ presentAlert.toggle() } }
47 |
48 | // EasyAlertPop(presentAlert: $presentAlert, alertType: .constant(.twoButton(title: "Do you want to delete?", message: "If you delete this file then you won’t please again check everything", leftButtonText: "Cancel", rightButtonText: "Delete"))){
49 | // withAnimation{
50 | // presentAlert.toggle()
51 | // }
52 | // } rightButtonAction: {
53 | // withAnimation{
54 | // presentAlert.toggle()
55 | // }
56 | // }
57 | }
58 | }
59 | // Applying the custom toast view modifier to the ZStack
60 | .toastView(toast: $toast)
61 | }
62 | }
63 |
64 | #Preview {
65 | ContentView()
66 | }
67 |
--------------------------------------------------------------------------------
/Sources/Helper/UIColorExt.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColorExt.swift
3 | //
4 | //
5 | // Created by tnhn on 2.01.2024.
6 | //
7 |
8 | import SwiftUI
9 | import UIKit
10 |
11 | //MARK: - UIColor
12 | extension UIColor{
13 | /// Creates a UIColor from a hexadecimal string.
14 | ///
15 | /// This initializer converts a hex string into a UIColor object.
16 | /// It supports hex strings in 3, 6, and 8 digits, representing RGB and ARGB values.
17 | ///
18 | /// - Parameter hexString: A hexadecimal string representation of the color.
19 | convenience init(hexString: String) {
20 | let hex = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
21 | var int = UInt64()
22 | Scanner(string: hex).scanHexInt64(&int)
23 | let a, r, g, b: UInt64
24 | switch hex.count {
25 | case 3: // RGB (12-bit)
26 | (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
27 | case 6: // RGB (24-bit)
28 | (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
29 | case 8: // ARGB (32-bit)
30 | (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
31 | default:
32 | (a, r, g, b) = (255, 0, 0, 0)
33 | }
34 | self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255)
35 | }
36 |
37 | /// Creates a UIColor from RGB values.
38 | ///
39 | /// - Parameters:
40 | /// - red: Red component of the color.
41 | /// - green: Green component of the color.
42 | /// - blue: Blue component of the color.
43 | /// - Returns: A UIColor object with the specified RGB values.
44 | static func rgb(red: CGFloat, green: CGFloat, blue: CGFloat) -> UIColor {
45 | return UIColor.init(red: red/255, green: green/255, blue: blue/255, alpha: 1.0)
46 | }
47 |
48 | /// Converts a UIColor to a hexadecimal string representation.
49 | ///
50 | /// - Parameter color: The UIColor to convert to a hex string.
51 | /// - Returns: A hexadecimal string representation of the color.
52 | func hexStringFromColor(color: UIColor) -> String {
53 | let components = color.cgColor.components
54 | let r: CGFloat = components?[0] ?? 0.0
55 | let g: CGFloat = components?[1] ?? 0.0
56 | let b: CGFloat = components?[2] ?? 0.0
57 |
58 | let hexString = String.init(format: "#%02lX%02lX%02lX", lroundf(Float(r * 255)), lroundf(Float(g * 255)), lroundf(Float(b * 255)))
59 | return hexString
60 | }
61 | }
62 |
63 | //MARK: - Color
64 | @available(iOS 13.0, *)
65 | extension Color{
66 | /// Initializes a SwiftUI Color from a hexadecimal string.
67 | ///
68 | /// This initializer allows creating a SwiftUI Color directly from a hex string.
69 | ///
70 | /// - Parameter hexString: A hexadecimal string representation of the color.
71 | init(hexString: String){
72 | self.init(UIColor(hexString: hexString))
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Sources/EasyAlertPop.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EasyAlertPop.swift
3 | //
4 | //
5 | // Created by tnhn on 2.01.2024.
6 | //
7 |
8 | import SwiftUI
9 |
10 | /// Represents the types of alerts that can be displayed.
11 | ///
12 | /// This enum provides two alert types:
13 | /// - `oneButton`: An alert with a single button.
14 | /// - `twoButton`: An alert with two buttons.
15 | public enum AlertType {
16 | case oneButton(title: String = "One button title", message: String = "One button description message", buttonText: String = "Ok")
17 | case twoButton(title: String = "Two button title", message: String = "Two button description message", leftButtonText: String = "No", rightButtonText: String = "Yes")
18 |
19 | func title() -> String {
20 | switch self {
21 | case .oneButton(title: let title, _, _),
22 | .twoButton(title: let title, _, _, _):
23 | return title
24 | }
25 | }
26 |
27 | func message() -> String {
28 | switch self {
29 | case .oneButton(_, message: let message, _),
30 | .twoButton(_, message: let message, _, _):
31 | return message
32 | }
33 | }
34 |
35 | var leftActionText: String {
36 | switch self {
37 | case .oneButton(_, _, let buttonText):
38 | return buttonText
39 | case .twoButton(_, _, let leftButtonText, _):
40 | return leftButtonText
41 | }
42 | }
43 |
44 | var rightActionText: String {
45 | switch self {
46 | case .oneButton:
47 | return "" // Tek butonlu durumda sağ buton metni yok
48 | case .twoButton(_, _, _, let rightButtonText):
49 | return rightButtonText
50 | }
51 | }
52 | }
53 |
54 |
55 | /// A SwiftUI view that presents a customizable alert pop-up.
56 | ///
57 | /// This view uses the `AlertType` enum to configure and present different styles of alerts.
58 | /// It supports customization for the alert's title, message, and action buttons.
59 | @available(iOS 14.0, *)
60 | public struct EasyAlertPop: View {
61 |
62 | @Environment(\.colorScheme) private var colorScheme: ColorScheme
63 | /// Flag used to dismiss the alert on the presenting view
64 | @Binding var presentAlert: Bool
65 |
66 | /// The alert type being shown
67 | @Binding var alertType: AlertType
68 |
69 | var leftButtonAction: (() -> ())?
70 | var rightButtonAction: (() -> ())?
71 |
72 | let verticalButtonsHeight: CGFloat = 80
73 |
74 | /// Initializes and configures an alert view.
75 | ///
76 | /// - Parameters:
77 | /// - presentAlert: A binding to a Boolean that determines if the alert should be presented.
78 | /// - alertType: A binding to the type of alert to present.
79 | /// - isShowVerticalButtons: A flag to determine if buttons should be shown vertically.
80 | /// - leftButtonAction: An optional closure to execute when the left button is tapped.
81 | /// - rightButtonAction: An optional closure to execute when the right button is tapped.
82 | public init(presentAlert: Binding, alertType: Binding, isShowVerticalButtons: Bool = false, leftButtonAction: ( () -> Void)? = nil, rightButtonAction: ( () -> Void)? = nil) {
83 | self._presentAlert = presentAlert
84 | self._alertType = alertType
85 | self.leftButtonAction = leftButtonAction
86 | self.rightButtonAction = rightButtonAction
87 | }
88 |
89 | public var body: some View {
90 |
91 | ZStack {
92 |
93 | // faded background
94 | Color.black.opacity(0.75)
95 | .edgesIgnoringSafeArea(.all)
96 | VStack(alignment: .center, spacing: 0) {
97 |
98 | // alert title
99 | Text(alertType.title())
100 | .lineLimit(2)
101 | .textVM(multiTextAlignment: .center, font: .poppins(.semiBold, size: .init(height: 18)), foregroundStyle: colorScheme == .light ? Color(hexString: "#232323") : Color(hexString: "#F2F2F2"))
102 | //.frame(height: .init(height: 25))
103 | .padding(.top, .init(height: 18))
104 | .padding(.bottom, .init(height: 12))
105 | .padding(.horizontal, .init(width: 16))
106 |
107 | // alert message
108 | Text(alertType.message())
109 | .lineLimit(20)
110 | .textVM(multiTextAlignment: .center, font: .poppins(.regular, size: .init(height: 15)), foregroundStyle: colorScheme == .light ? Color(hexString: "#232323") : Color(hexString: "#F2F2F2"))
111 | //.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
112 | .padding(.horizontal, .init(width: 16))
113 | .padding(.bottom, .init(height: 18))
114 | .minimumScaleFactor(0.5)
115 |
116 | Divider()
117 | .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 0.5)
118 | .padding(.all, 0)
119 |
120 | HStack(spacing: 0) {
121 |
122 | switch alertType {
123 | case .oneButton:
124 | // left button
125 | Button {
126 | leftButtonAction?()
127 | } label: {
128 | Text(alertType.leftActionText)
129 | .textVM(multiTextAlignment: .center, font: .poppins(.medium, size: .init(height: 18)), foregroundStyle: Color(hexString: "#007AFF"))
130 | .padding()
131 | .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
132 | }
133 |
134 | case .twoButton:
135 | // left button
136 | Button {
137 | leftButtonAction?()
138 | } label: {
139 | Text(alertType.leftActionText)
140 | .textVM(multiTextAlignment: .center, font: .poppins(.medium, size: .init(height: 18)), foregroundStyle: Color(hexString: "#F14B4B"))
141 | .padding()
142 | .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
143 | }
144 | Divider()
145 | .frame(minWidth: 0, maxWidth: 0.5, minHeight: 0, maxHeight: .infinity)
146 |
147 | // right button (default)
148 | Button {
149 | rightButtonAction?()
150 | } label: {
151 | Text(alertType.rightActionText)
152 | .textVM(multiTextAlignment: .center, font: .poppins(.medium, size: .init(height: 18)), foregroundStyle: Color(hexString: "#007AFF"))
153 | .padding(.init(height: 15))
154 | .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
155 | }
156 | }
157 |
158 | }
159 | .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .init(height: 53))
160 | .padding([.horizontal, .bottom], 0)
161 |
162 | }
163 | .frame(width: .init(width: 349))
164 | .background(
165 | colorScheme == .light ? Color(hexString: "#F2F2F2") : Color(hexString: "#232323")
166 | )
167 | .cornerRadius(.init(height: 10))
168 | }
169 | .zIndex(2)
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/Sources/EasyToastView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EasyToastView.swift
3 | //
4 | //
5 | // Created by tnhn on 2.01.2024.
6 | //
7 |
8 | import SwiftUI
9 |
10 | //MARK: - Custom Toast View
11 | @available(iOS 14.0, *)
12 | /// A SwiftUI view for displaying customizable toast messages.
13 | ///
14 | /// This view creates a toast message with a configurable style, title, message, and a dismiss button.
15 | /// The toast style is determined by `CustomToastStyle`, which affects the icon and theme color.
16 | ///
17 | /// - Parameters:
18 | /// - toastType: The style of the toast, defined in `CustomToastStyle`.
19 | /// - toastTitle: The title text of the toast.
20 | /// - toastMessage: The message text of the toast.
21 | /// - onCancelTapped: A closure that is executed when the dismiss button is tapped.
22 | public struct CustomToastView: View {
23 |
24 | @Environment(\.colorScheme) private var colorScheme: ColorScheme
25 | public let toastType: CustomToastStyle
26 | public let toastTitle: String
27 | public let toastMessage: String
28 | public let onCancelTapped: (() -> Void)
29 |
30 | @available(iOS 14.0, *)
31 | public var body: some View {
32 | VStack(alignment: .leading) {
33 | HStack(alignment: toastTitle.isEmpty || toastMessage.isEmpty ? .center : .top) {
34 | Image(systemName: toastType.iconFileName)
35 | .foregroundColor(toastType.themeColor)
36 |
37 | VStack(alignment: .leading, spacing: .init(height: toastTitle.isEmpty || toastMessage.isEmpty ? 0 : 5)) {
38 |
39 | if !toastTitle.isEmpty {
40 | Text(toastTitle)
41 | .lineLimit(1)
42 | .textVM(multiTextAlignment: .leading, font: .poppins(.semiBold, size: .init(height: 16)), foregroundStyle: colorScheme == .light ? Color(hexString: "#232323") : Color(hexString: "#F2F2F2"))
43 | }
44 |
45 | if !toastMessage.isEmpty {
46 | Text(toastMessage)
47 | .textVM(multiTextAlignment: .leading, font: .poppins(.regular, size: .init(height: 14)), foregroundStyle: colorScheme == .light ? Color(hexString: "#232323") : Color(hexString: "#F2F2F2"))
48 | .lineLimit(2)
49 | }
50 |
51 | }
52 |
53 | Spacer(minLength: .init(height: 10))
54 |
55 | Button { /// dismiss button
56 | onCancelTapped()
57 | } label: {
58 | Image(systemName: "xmark")
59 | .foregroundColor(colorScheme == .light ? Color(hexString: "#232323") : Color(hexString: "#F2F2F2"))
60 | }
61 | }
62 | .padding()
63 | }
64 | .background(colorScheme == .light ? Color(hexString: "#F2F2F2") : Color(hexString: "#232323"))
65 | .overlay(
66 | Rectangle()
67 | .fill(toastType.themeColor)
68 | .frame(width: toastTitle.isEmpty || toastMessage.isEmpty ? 0 : 6)
69 | .clipped()
70 | , alignment: .leading
71 | )
72 | .frame(minWidth: 0, maxWidth: .infinity)
73 | .cornerRadius(.init(height: 10))
74 | .shadow(color: Color.black.opacity(0.25), radius: 4, x: 0, y: 1)
75 | .padding(.horizontal, .init(width: 20))
76 | }
77 |
78 | }
79 |
80 | //MARK: - Enum Model
81 | @available(iOS 14.0, *)
82 | /// `ToastView` is a customizable view component for displaying toast messages.
83 | /// It supports custom styles, icons, colors, and fonts.
84 | ///
85 | /// Use the `init` method to create a new instance with custom configurations.
86 | public struct EasyToastView: Equatable {
87 | var type: CustomToastStyle
88 | var title: String
89 | var message: String
90 | var customIconName: String?
91 | var customColor: Color?
92 | var duration: Double = 3
93 | var yOffset: Double = -30
94 |
95 | /// Initializes a new ToastView with specified properties.
96 | ///
97 | /// - Parameters:
98 | /// - type: The style of the toast, defined in `CustomToastStyle`.
99 | /// - title: The title of the toast message.
100 | /// - message: The message body of the toast.
101 | /// - iconName: Optional custom icon name. If not provided, default icon will be used based on `type`.
102 | /// - customColor: Optional custom color. If not provided, default color will be used based on `type`.
103 | /// - duration: The duration for which the toast is visible. Default is 3 seconds.
104 | /// - yOffset: The vertical offset for the toast position. Default is -30.
105 | ///
106 | /// - Note: If `type` is set to `.custom`, you can provide custom values for `iconName`, `customFontName`, and `customColor`.
107 | public init(type: CustomToastStyle, title: String, message: String, iconName: String? = nil, customColor: Color? = nil, duration: Double = 3.0, yOffset: Double = -30.0) {
108 | self.type = type
109 | self.title = title
110 | self.message = message
111 | self.duration = duration
112 | self.yOffset = yOffset
113 |
114 |
115 | if type == .custom {
116 | CustomToastStyle.setCustomColor(customColor ?? .clear)
117 | CustomToastStyle.setCustomIconName(iconName ?? "")
118 | }
119 |
120 | }
121 | }
122 |
123 | //MARK: - Enum
124 | @available(iOS 14.0, *)
125 | /// Enum representing different styles for custom toast messages.
126 | ///
127 | /// This enum includes several predefined styles (`error`, `warning`, `success`, `info`) and a `custom` style.
128 | /// The `custom` style allows for setting a custom color and icon name.
129 | public enum CustomToastStyle {
130 | case error
131 | case warning
132 | case success
133 | case info
134 | case custom
135 |
136 | static var customColor: Color = Color.clear // Default Value
137 | static var customIconName: String = "" // Default Value
138 |
139 | /// Sets the custom color for the `custom` toast style.
140 | ///
141 | /// - Parameter color: The color to set for the custom style.
142 | static func setCustomColor(_ color: Color) {
143 | customColor = color
144 | }
145 |
146 | /// Sets the custom icon name for the `custom` toast style.
147 | ///
148 | /// - Parameter iconName: The icon name to set for the custom style.
149 |
150 | static func setCustomIconName(_ iconName: String) {
151 | customIconName = iconName
152 | }
153 | }
154 |
155 | @available(iOS 14.0, *)
156 | extension CustomToastStyle {
157 | /// Returns the theme color associated with the toast style.
158 | ///
159 | /// For predefined styles, this will return specific colors.
160 | /// For the `custom` style, it will return the color set by `setCustomColor`.
161 | var themeColor: Color {
162 | switch self {
163 | case .error:
164 | return Color.red
165 | case .warning:
166 | return Color.orange
167 | case .success:
168 | return Color.green
169 | case .info:
170 | return Color.blue
171 | case .custom:
172 | return CustomToastStyle.customColor
173 |
174 | }
175 | }
176 | /// Returns the icon file name associated with the toast style.
177 | ///
178 | /// For predefined styles, this will return specific icons.
179 | /// For the `custom` style, it will return the icon name set by `setCustomIconName`.
180 | var iconFileName: String {
181 | switch self {
182 | case .info: return "info.circle.fill"
183 | case .warning: return "exclamationmark.triangle.fill"
184 | case .success: return "checkmark.circle.fill"
185 | case .error: return "xmark.circle.fill"
186 | case .custom:
187 | return CustomToastStyle.customIconName
188 | }
189 | }
190 | }
191 |
192 | //MARK: - Custom Toast Modifier
193 | @available(iOS 14.0, *)
194 | /// A `ViewModifier` for presenting custom toast messages on top of a view.
195 | ///
196 | /// This modifier overlays a `CustomToastView` on the content. The toast can be dismissed either automatically after a certain duration or by user interaction.
197 |
198 | struct CustomToastModifier: ViewModifier {
199 | @Binding var toast: EasyToastView?
200 | @State private var workItem: DispatchWorkItem?
201 |
202 | /// Modifies the body of the content to include a toast overlay.
203 | ///
204 | /// - Parameter content: The content view that the modifier is applied to.
205 | /// - Returns: A view that has been modified to include a toast overlay.
206 | func body(content: Content) -> some View {
207 | content
208 | .frame(maxWidth: .infinity, maxHeight: .infinity)
209 | .overlay(
210 | ZStack {
211 | mainToastView()
212 | .offset(y: toast?.yOffset ?? -30)
213 | }.animation(.spring(), value: toast)
214 | )
215 | .onChange(of: toast) { value in
216 | showToast()
217 | }
218 | }
219 |
220 | /// Creates the view for the main toast.
221 | ///
222 | /// - Returns: A view representing the actual toast message, if any.
223 | @ViewBuilder func mainToastView() -> some View {
224 | if let toast = toast {
225 | VStack {
226 | Spacer()
227 | CustomToastView(
228 | toastType: toast.type,
229 | toastTitle: toast.title,
230 | toastMessage: toast.message, onCancelTapped: {
231 | dismissToast()
232 | })
233 | }
234 | .transition(.move(edge: .bottom))
235 | }
236 | }
237 |
238 | /// Triggers the presentation of the toast message with optional auto dismissal.
239 | ///
240 | /// Presents the toast and sets up a timer for automatic dismissal if a duration is specified.
241 | private func showToast() {
242 | guard let toast = toast else { return }
243 |
244 | UIImpactFeedbackGenerator(style: .light).impactOccurred()
245 |
246 | if toast.duration > 0 {
247 | workItem?.cancel()
248 |
249 | let task = DispatchWorkItem {
250 | dismissToast()
251 | }
252 |
253 | workItem = task
254 | DispatchQueue.main.asyncAfter(deadline: .now() + toast.duration, execute: task)
255 | }
256 | }
257 |
258 | /// Dismisses the current toast message.
259 | ///
260 | /// Resets the `toast` binding to `nil` and cancels any dismissal timer.
261 | private func dismissToast() {
262 | withAnimation {
263 | toast = nil
264 | }
265 |
266 | workItem?.cancel()
267 | workItem = nil
268 | }
269 | }
270 |
271 | //MARK: - View Extension
272 | @available(iOS 14.0, *)
273 | public extension View {
274 | /// Adds a toast view modifier to the view.
275 | ///
276 | /// - Parameter toast: A binding to an optional `EasyToastView` that controls the toast's presentation.
277 | /// - Returns: The modified view that can present a custom toast message.
278 | func toastView(toast: Binding) -> some View {
279 | self.modifier(CustomToastModifier(toast: toast))
280 | }
281 | }
282 |
--------------------------------------------------------------------------------
/SwiftEasyPopPackageExample/SwiftEasyPopPackageExample.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 60;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 23418E6F2B4418D300D6BFE1 /* SwiftEasyPopPackageExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23418E6E2B4418D300D6BFE1 /* SwiftEasyPopPackageExampleApp.swift */; };
11 | 23418E712B4418D300D6BFE1 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23418E702B4418D300D6BFE1 /* ContentView.swift */; };
12 | 23418E732B4418D500D6BFE1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 23418E722B4418D500D6BFE1 /* Assets.xcassets */; };
13 | 23418E762B4418D500D6BFE1 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 23418E752B4418D500D6BFE1 /* Preview Assets.xcassets */; };
14 | /* End PBXBuildFile section */
15 |
16 | /* Begin PBXFileReference section */
17 | 23418E6B2B4418D300D6BFE1 /* SwiftEasyPopPackageExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftEasyPopPackageExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
18 | 23418E6E2B4418D300D6BFE1 /* SwiftEasyPopPackageExampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftEasyPopPackageExampleApp.swift; sourceTree = ""; };
19 | 23418E702B4418D300D6BFE1 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; };
20 | 23418E722B4418D500D6BFE1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
21 | 23418E752B4418D500D6BFE1 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
22 | /* End PBXFileReference section */
23 |
24 | /* Begin PBXFrameworksBuildPhase section */
25 | 23418E682B4418D300D6BFE1 /* Frameworks */ = {
26 | isa = PBXFrameworksBuildPhase;
27 | buildActionMask = 2147483647;
28 | files = (
29 | );
30 | runOnlyForDeploymentPostprocessing = 0;
31 | };
32 | /* End PBXFrameworksBuildPhase section */
33 |
34 | /* Begin PBXGroup section */
35 | 23418E622B4418D300D6BFE1 = {
36 | isa = PBXGroup;
37 | children = (
38 | 23418E6D2B4418D300D6BFE1 /* SwiftEasyPopPackageExample */,
39 | 23418E6C2B4418D300D6BFE1 /* Products */,
40 | );
41 | sourceTree = "";
42 | };
43 | 23418E6C2B4418D300D6BFE1 /* Products */ = {
44 | isa = PBXGroup;
45 | children = (
46 | 23418E6B2B4418D300D6BFE1 /* SwiftEasyPopPackageExample.app */,
47 | );
48 | name = Products;
49 | sourceTree = "";
50 | };
51 | 23418E6D2B4418D300D6BFE1 /* SwiftEasyPopPackageExample */ = {
52 | isa = PBXGroup;
53 | children = (
54 | 23418E6E2B4418D300D6BFE1 /* SwiftEasyPopPackageExampleApp.swift */,
55 | 23418E702B4418D300D6BFE1 /* ContentView.swift */,
56 | 23418E722B4418D500D6BFE1 /* Assets.xcassets */,
57 | 23418E742B4418D500D6BFE1 /* Preview Content */,
58 | );
59 | path = SwiftEasyPopPackageExample;
60 | sourceTree = "";
61 | };
62 | 23418E742B4418D500D6BFE1 /* Preview Content */ = {
63 | isa = PBXGroup;
64 | children = (
65 | 23418E752B4418D500D6BFE1 /* Preview Assets.xcassets */,
66 | );
67 | path = "Preview Content";
68 | sourceTree = "";
69 | };
70 | /* End PBXGroup section */
71 |
72 | /* Begin PBXNativeTarget section */
73 | 23418E6A2B4418D300D6BFE1 /* SwiftEasyPopPackageExample */ = {
74 | isa = PBXNativeTarget;
75 | buildConfigurationList = 23418E792B4418D500D6BFE1 /* Build configuration list for PBXNativeTarget "SwiftEasyPopPackageExample" */;
76 | buildPhases = (
77 | 23418E672B4418D300D6BFE1 /* Sources */,
78 | 23418E682B4418D300D6BFE1 /* Frameworks */,
79 | 23418E692B4418D300D6BFE1 /* Resources */,
80 | );
81 | buildRules = (
82 | );
83 | dependencies = (
84 | );
85 | name = SwiftEasyPopPackageExample;
86 | packageProductDependencies = (
87 | );
88 | productName = SwiftEasyPopPackageExample;
89 | productReference = 23418E6B2B4418D300D6BFE1 /* SwiftEasyPopPackageExample.app */;
90 | productType = "com.apple.product-type.application";
91 | };
92 | /* End PBXNativeTarget section */
93 |
94 | /* Begin PBXProject section */
95 | 23418E632B4418D300D6BFE1 /* Project object */ = {
96 | isa = PBXProject;
97 | attributes = {
98 | BuildIndependentTargetsInParallel = 1;
99 | LastSwiftUpdateCheck = 1500;
100 | LastUpgradeCheck = 1500;
101 | TargetAttributes = {
102 | 23418E6A2B4418D300D6BFE1 = {
103 | CreatedOnToolsVersion = 15.0.1;
104 | };
105 | };
106 | };
107 | buildConfigurationList = 23418E662B4418D300D6BFE1 /* Build configuration list for PBXProject "SwiftEasyPopPackageExample" */;
108 | compatibilityVersion = "Xcode 14.0";
109 | developmentRegion = en;
110 | hasScannedForEncodings = 0;
111 | knownRegions = (
112 | en,
113 | Base,
114 | );
115 | mainGroup = 23418E622B4418D300D6BFE1;
116 | packageReferences = (
117 | 23418E7C2B4418E600D6BFE1 /* XCLocalSwiftPackageReference "../SwiftEasyPop" */,
118 | );
119 | productRefGroup = 23418E6C2B4418D300D6BFE1 /* Products */;
120 | projectDirPath = "";
121 | projectRoot = "";
122 | targets = (
123 | 23418E6A2B4418D300D6BFE1 /* SwiftEasyPopPackageExample */,
124 | );
125 | };
126 | /* End PBXProject section */
127 |
128 | /* Begin PBXResourcesBuildPhase section */
129 | 23418E692B4418D300D6BFE1 /* Resources */ = {
130 | isa = PBXResourcesBuildPhase;
131 | buildActionMask = 2147483647;
132 | files = (
133 | 23418E762B4418D500D6BFE1 /* Preview Assets.xcassets in Resources */,
134 | 23418E732B4418D500D6BFE1 /* Assets.xcassets in Resources */,
135 | );
136 | runOnlyForDeploymentPostprocessing = 0;
137 | };
138 | /* End PBXResourcesBuildPhase section */
139 |
140 | /* Begin PBXSourcesBuildPhase section */
141 | 23418E672B4418D300D6BFE1 /* Sources */ = {
142 | isa = PBXSourcesBuildPhase;
143 | buildActionMask = 2147483647;
144 | files = (
145 | 23418E712B4418D300D6BFE1 /* ContentView.swift in Sources */,
146 | 23418E6F2B4418D300D6BFE1 /* SwiftEasyPopPackageExampleApp.swift in Sources */,
147 | );
148 | runOnlyForDeploymentPostprocessing = 0;
149 | };
150 | /* End PBXSourcesBuildPhase section */
151 |
152 | /* Begin XCBuildConfiguration section */
153 | 23418E772B4418D500D6BFE1 /* Debug */ = {
154 | isa = XCBuildConfiguration;
155 | buildSettings = {
156 | ALWAYS_SEARCH_USER_PATHS = NO;
157 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
158 | CLANG_ANALYZER_NONNULL = YES;
159 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
160 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
161 | CLANG_ENABLE_MODULES = YES;
162 | CLANG_ENABLE_OBJC_ARC = YES;
163 | CLANG_ENABLE_OBJC_WEAK = YES;
164 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
165 | CLANG_WARN_BOOL_CONVERSION = YES;
166 | CLANG_WARN_COMMA = YES;
167 | CLANG_WARN_CONSTANT_CONVERSION = YES;
168 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
169 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
170 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
171 | CLANG_WARN_EMPTY_BODY = YES;
172 | CLANG_WARN_ENUM_CONVERSION = YES;
173 | CLANG_WARN_INFINITE_RECURSION = YES;
174 | CLANG_WARN_INT_CONVERSION = YES;
175 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
176 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
177 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
178 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
179 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
180 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
181 | CLANG_WARN_STRICT_PROTOTYPES = YES;
182 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
183 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
184 | CLANG_WARN_UNREACHABLE_CODE = YES;
185 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
186 | COPY_PHASE_STRIP = NO;
187 | DEBUG_INFORMATION_FORMAT = dwarf;
188 | ENABLE_STRICT_OBJC_MSGSEND = YES;
189 | ENABLE_TESTABILITY = YES;
190 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
191 | GCC_C_LANGUAGE_STANDARD = gnu17;
192 | GCC_DYNAMIC_NO_PIC = NO;
193 | GCC_NO_COMMON_BLOCKS = YES;
194 | GCC_OPTIMIZATION_LEVEL = 0;
195 | GCC_PREPROCESSOR_DEFINITIONS = (
196 | "DEBUG=1",
197 | "$(inherited)",
198 | );
199 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
200 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
201 | GCC_WARN_UNDECLARED_SELECTOR = YES;
202 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
203 | GCC_WARN_UNUSED_FUNCTION = YES;
204 | GCC_WARN_UNUSED_VARIABLE = YES;
205 | IPHONEOS_DEPLOYMENT_TARGET = 17.0;
206 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
207 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
208 | MTL_FAST_MATH = YES;
209 | ONLY_ACTIVE_ARCH = YES;
210 | SDKROOT = iphoneos;
211 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
212 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
213 | };
214 | name = Debug;
215 | };
216 | 23418E782B4418D500D6BFE1 /* Release */ = {
217 | isa = XCBuildConfiguration;
218 | buildSettings = {
219 | ALWAYS_SEARCH_USER_PATHS = NO;
220 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
221 | CLANG_ANALYZER_NONNULL = YES;
222 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
223 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
224 | CLANG_ENABLE_MODULES = YES;
225 | CLANG_ENABLE_OBJC_ARC = YES;
226 | CLANG_ENABLE_OBJC_WEAK = YES;
227 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
228 | CLANG_WARN_BOOL_CONVERSION = YES;
229 | CLANG_WARN_COMMA = YES;
230 | CLANG_WARN_CONSTANT_CONVERSION = YES;
231 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
232 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
233 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
234 | CLANG_WARN_EMPTY_BODY = YES;
235 | CLANG_WARN_ENUM_CONVERSION = YES;
236 | CLANG_WARN_INFINITE_RECURSION = YES;
237 | CLANG_WARN_INT_CONVERSION = YES;
238 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
239 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
240 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
241 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
242 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
243 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
244 | CLANG_WARN_STRICT_PROTOTYPES = YES;
245 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
246 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
247 | CLANG_WARN_UNREACHABLE_CODE = YES;
248 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
249 | COPY_PHASE_STRIP = NO;
250 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
251 | ENABLE_NS_ASSERTIONS = NO;
252 | ENABLE_STRICT_OBJC_MSGSEND = YES;
253 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
254 | GCC_C_LANGUAGE_STANDARD = gnu17;
255 | GCC_NO_COMMON_BLOCKS = YES;
256 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
257 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
258 | GCC_WARN_UNDECLARED_SELECTOR = YES;
259 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
260 | GCC_WARN_UNUSED_FUNCTION = YES;
261 | GCC_WARN_UNUSED_VARIABLE = YES;
262 | IPHONEOS_DEPLOYMENT_TARGET = 17.0;
263 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
264 | MTL_ENABLE_DEBUG_INFO = NO;
265 | MTL_FAST_MATH = YES;
266 | SDKROOT = iphoneos;
267 | SWIFT_COMPILATION_MODE = wholemodule;
268 | VALIDATE_PRODUCT = YES;
269 | };
270 | name = Release;
271 | };
272 | 23418E7A2B4418D500D6BFE1 /* Debug */ = {
273 | isa = XCBuildConfiguration;
274 | buildSettings = {
275 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
276 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
277 | CODE_SIGN_STYLE = Automatic;
278 | CURRENT_PROJECT_VERSION = 1;
279 | DEVELOPMENT_ASSET_PATHS = "\"SwiftEasyPopPackageExample/Preview Content\"";
280 | DEVELOPMENT_TEAM = SMZG7GRLGM;
281 | ENABLE_PREVIEWS = YES;
282 | GENERATE_INFOPLIST_FILE = YES;
283 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
284 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
285 | INFOPLIST_KEY_UILaunchScreen_Generation = YES;
286 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
287 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
288 | LD_RUNPATH_SEARCH_PATHS = (
289 | "$(inherited)",
290 | "@executable_path/Frameworks",
291 | );
292 | MARKETING_VERSION = 1.0;
293 | PRODUCT_BUNDLE_IDENTIFIER = com.tunix.SwiftEasyPopPackageExample;
294 | PRODUCT_NAME = "$(TARGET_NAME)";
295 | SWIFT_EMIT_LOC_STRINGS = YES;
296 | SWIFT_VERSION = 5.0;
297 | TARGETED_DEVICE_FAMILY = "1,2";
298 | };
299 | name = Debug;
300 | };
301 | 23418E7B2B4418D500D6BFE1 /* Release */ = {
302 | isa = XCBuildConfiguration;
303 | buildSettings = {
304 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
305 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
306 | CODE_SIGN_STYLE = Automatic;
307 | CURRENT_PROJECT_VERSION = 1;
308 | DEVELOPMENT_ASSET_PATHS = "\"SwiftEasyPopPackageExample/Preview Content\"";
309 | DEVELOPMENT_TEAM = SMZG7GRLGM;
310 | ENABLE_PREVIEWS = YES;
311 | GENERATE_INFOPLIST_FILE = YES;
312 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
313 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
314 | INFOPLIST_KEY_UILaunchScreen_Generation = YES;
315 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
316 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
317 | LD_RUNPATH_SEARCH_PATHS = (
318 | "$(inherited)",
319 | "@executable_path/Frameworks",
320 | );
321 | MARKETING_VERSION = 1.0;
322 | PRODUCT_BUNDLE_IDENTIFIER = com.tunix.SwiftEasyPopPackageExample;
323 | PRODUCT_NAME = "$(TARGET_NAME)";
324 | SWIFT_EMIT_LOC_STRINGS = YES;
325 | SWIFT_VERSION = 5.0;
326 | TARGETED_DEVICE_FAMILY = "1,2";
327 | };
328 | name = Release;
329 | };
330 | /* End XCBuildConfiguration section */
331 |
332 | /* Begin XCConfigurationList section */
333 | 23418E662B4418D300D6BFE1 /* Build configuration list for PBXProject "SwiftEasyPopPackageExample" */ = {
334 | isa = XCConfigurationList;
335 | buildConfigurations = (
336 | 23418E772B4418D500D6BFE1 /* Debug */,
337 | 23418E782B4418D500D6BFE1 /* Release */,
338 | );
339 | defaultConfigurationIsVisible = 0;
340 | defaultConfigurationName = Release;
341 | };
342 | 23418E792B4418D500D6BFE1 /* Build configuration list for PBXNativeTarget "SwiftEasyPopPackageExample" */ = {
343 | isa = XCConfigurationList;
344 | buildConfigurations = (
345 | 23418E7A2B4418D500D6BFE1 /* Debug */,
346 | 23418E7B2B4418D500D6BFE1 /* Release */,
347 | );
348 | defaultConfigurationIsVisible = 0;
349 | defaultConfigurationName = Release;
350 | };
351 | /* End XCConfigurationList section */
352 |
353 | /* Begin XCLocalSwiftPackageReference section */
354 | 23418E7C2B4418E600D6BFE1 /* XCLocalSwiftPackageReference "../SwiftEasyPop" */ = {
355 | isa = XCLocalSwiftPackageReference;
356 | relativePath = ../SwiftEasyPop;
357 | };
358 | /* End XCLocalSwiftPackageReference section */
359 | };
360 | rootObject = 23418E632B4418D300D6BFE1 /* Project object */;
361 | }
362 |
--------------------------------------------------------------------------------