A collection of missing SwiftUI components

Overview

SwiftUIKit

A collection of components that will simplify and accelerate your iOS development.

Components

  1. CurrencyTextField
  2. AdaptToKeyboard (not needed for iOS 14 beta 6+)
  3. ContactPicker

Demo

There is an example app at SwiftUIKitExampleApp which can be built and run. Just clone this repo and run it.

1. CurrencyTextField

Demo

Description

Real time formatting of users input into currency format.

Usage

import SwiftUIKit

struct ContentView: View {
    @State private var value = 0.0

    var body: some View {
        //Minimal configuration
        CurrencyTextField("Amount", value: self.$value)
        
        //All configurations
        CurrencyTextField("Amount", value: self.$value, alwaysShowFractions: false, numberOfDecimalPlaces: 2, currencySymbol: "US$")
            .font(.largeTitle)
            .multilineTextAlignment(TextAlignment.center)
    }
}

2. AdaptToKeyboard

Demo

Description

Animate view's position when keyboard is shown / hidden

Usage

import SwiftUIKit

struct ContentView: View {
    var body: some View {
        VStack {
            Spacer()
            Button(action: {}) {
              Text("Hi")
                  .adaptToKeyboard()
            }
        }
    }
}

3. ContactPicker

Demo

Description

SwiftUI doesn't work well with CNContactPickerViewController if you just put it inside a UIViewControllerRepresentable. See this stackoverflow post. With ContactPicker here its just a one liner.

To enable multiple selection use onSelectContacts instead.

Usage

import SwiftUIKit

struct ContentView: View {
    @State var showPicker = false

    var body: some View {
        ZStack {
            // This is just a dummy view to present the contact picker,
            // it won't display anything, so place this anywhere.
            // Here I have created a ZStack and placed it beneath the main view.
            ContactPicker(
                showPicker: $showPicker,
                onSelectContact: {c in
                    self.contact = c
                }
            )
            VStack {
                Button(action: {
                    self.showPicker.toggle()
                }) {
                    Text("Pick a contact")
                }
            }
        }
    }
}
Comments
  • CurrencyTextField does not allow for more than 2 positions after decimal point

    CurrencyTextField does not allow for more than 2 positions after decimal point

    This looked like it would work for the project I am working on where I need a currency field to be formatted/validated for a price per unit. however, i need values with at least 4 digits past the decimal. for example, $0.0475.

    opened by KevinOlive 6
  • Issue with regional settings different from US

    Issue with regional settings different from US

    I'm not sure if it's a known bug but when region is not US, for example in Brazil where currency is R$ 999.999,99 the decimal place divider (, colon) is not allowed to be typed, only accept . dot and when you change to other field it displays correctly but maximum amount is 9.999 without decimal places. Could you please let me know if is there any workaround into your pack documentation ? I could not locate into the code.

    Simulator Screen Shot - iPhone 12 - 2020-11-21 at 23 36 11 Simulator Screen Shot - iPhone 12 - 2020-11-21 at 23 31 37

    opened by alphadogbkbone 4
  • How do I initialise this textField with a pre-populated value?

    How do I initialise this textField with a pre-populated value?

    Looking at the demo app in CurrencyTextFieldDemoView if I change the value from 0.0 to 4.5

    @State private var value: Double? = 4.5

    I would expect the app to launch with a value of £4.50 in the text filed however, when run, the field still only shows the Placeholder of 'Amount'. If I type nothing but click the "Print" button with it still showing the Placeholder it then prints the value it was init'd with:

    Optional(4.5)

    So the value is there, its just not being displayed.

    The other behaviour I think is odd, is that if I set the field to say 2.1 when I dismiss the keyboard I would expect that to re-format as £2.10 however its still displays as £2.1 which is obviously an improper currency format.

    Thanks Plasma

    good first issue 
    opened by PlasmaSoftUK 4
  • CurrencyTextField not showing decimals onChange

    CurrencyTextField not showing decimals onChange

    I'm trying to update CurrencyTextField based on another textfield but it doesn't seems to work well. The problem I'm facing is when I updated hourlySalary to a decimal like 0.02 it always round to 0

    Also the button in this view show the decimals in hourlySalary just on the initial state, if I start inputting something in any textFields then it just jumps from 2.0 to 0.0 without showing decimals

    ` import SwiftUI

    struct ContentView: View {

    @State var hourlySalary: Double? = 1.0
    @State var montlhySalary: Double? = 0.0
    @State var yearlySalary: Double? = 0.0
    
    @State var test: Bool = false
    
    
    
    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 20) {
                Text("Hourly")
                CurrencyTextField(currencyString(amount: 0), value: $hourlySalary)
                    .font(.title)
                
                Text("Monthly")
                CurrencyTextField(currencyString(amount: 0), value: $montlhySalary)
                    .font(.title)
                
                Text("Yearly")
                CurrencyTextField(currencyString(amount: 0), value: $yearlySalary, tag: 10)
                    .font(.title)
                
                Button(action: {
                    if test {
                        hourlySalary = 0.5
                    } else {
                        hourlySalary = 2
                    }
                    test.toggle()
                }, label: {
                    Text("Button")
                })
                
            }
            .onChange(of: hourlySalary ?? 0, perform: { value in
                let hourly = value
                let monthly = (hourly * 8) * 20
                let yearly = monthly * 12
                montlhySalary = monthly
                yearlySalary = yearly
            })
            .onChange(of: montlhySalary ?? 0, perform: { value in
                let monthly = value
                let hourly = (monthly / 20) / 8
                let yearly = monthly * 12
                hourlySalary = hourly
                yearlySalary = yearly
            })
            .onChange(of: yearlySalary ?? 0, perform: { value in
                let yearly = value
                let monthly = yearly / 12
                let hourly = (monthly / 20) / 8
                hourlySalary = hourly
                montlhySalary = monthly
            })
            .padding()
            .navigationTitle("What's your salary?")
        }
    }
    

    `

    opened by LualdiD 4
  • Error when building with Xcode Version 14.0 beta 3 (14A5270f)

    Error when building with Xcode Version 14.0 beta 3 (14A5270f)

    Receiving the following build errors:

    1. /Users/dev/Library/Developer/Xcode/DerivedData/AppName-hbeklfnuvwbepyaujkierepomydw/SourcePackages/checkouts/SwiftUIKit/Sources/SwiftUIKit/views/ContactPicker.swift:73:24: error build: Inheritance from non-protocol, non-class type 'ContactPicker.Coordinator' (aka 'any Coordinator')

    2. /Users/dev/Library/Developer/Xcode/DerivedData/AppName-hbeklfnuvwbepyaujkierepomydw/SourcePackages/checkouts/SwiftUIKit/Sources/SwiftUIKit/views/ContactPicker.swift:91:24: error build: Inheritance from non-protocol, non-class type 'ContactPicker.Coordinator' (aka 'any Coordinator')

    opened by TheApApp 3
  • ContactPicker dismisses my sheet

    ContactPicker dismisses my sheet

    I'm displaying the ContactPicker inside a sheet and it all worked when it was contained in a form. However, I struggled with the form, so I removed it.

    Now when you chose a contact, my sheet gets dismissed.

    Any ideas?

    This code shows the issue that I am facing.

    struct ContactPickerDemoView: View {
        @State var contact: CNContact?
        @State var showPicker = false
        @State var showingSheet = false
    
        var body: some View {
            Button(action: {
                self.showingSheet.toggle()
            }) {
                Text("Show Sheet")
            }
            .sheet(isPresented: $showingSheet) {
                ZStack {
                    ContactPicker(
                        showPicker: $showPicker,
                        onSelectContact: {c in
                            self.contact = c})
                    VStack{
                        Spacer()
                        Button(action: {
                            self.showPicker.toggle()
                        }) {
                            Text("Pick a contact")
                        }
                        Spacer()
                        Text("\(self.contact?.givenName ?? "")")
                        Spacer()
                    }
                }
            }
        }
    }
    
    opened by hackzilla 2
  • Fixing Xcode 14 Coordinator warnings

    Fixing Xcode 14 Coordinator warnings

    Replaced Coordinator with ContactPickerCoordinator to silence errors with Xcode 14. Can confirm the original warnings and that this fixes it.

    (So sorry if this isn't the right way to do things...still new to GitHub...)

    Co-Authored-By: youjinp [email protected]

    opened by kudit 1
  • ContactPicker disables TexFields in SwiftUI view.

    ContactPicker disables TexFields in SwiftUI view.

    When using the ContactPicker, my code does not allow me to access the TextFields.. Here's my code using your Picker. `struct AddNewRecipientView: View { @Environment(.managedObjectContext) var moc @Environment(.presentationMode) var presentationMode

    private let borderWidth: CGFloat = 1.0
    
    @State private var lastName: String = ""
    @State private var firstName: String = ""
    @State private var addressLine1: String = ""
    @State private var addressLine2: String = ""
    @State private var city: String = ""
    @State private var state: String = ""
    @State private var zip: String = ""
    @State private var country: String = ""
    
    @State var showPicker = false
    
    init() {
        let navBarApperance = UINavigationBarAppearance()
        navBarApperance.largeTitleTextAttributes = [
            .foregroundColor: UIColor.systemGreen,
            .font: UIFont(name: "ArialRoundedMTBold", size: 35)!]
        navBarApperance.titleTextAttributes = [
            .foregroundColor: UIColor.systemGreen,
            .font: UIFont(name: "ArialRoundedMTBold", size: 20)!]
        UINavigationBar.appearance().standardAppearance = navBarApperance
        UINavigationBar.appearance().scrollEdgeAppearance = navBarApperance
        UINavigationBar.appearance().compactAppearance = navBarApperance
    }
    
    var body: some View {
        NavigationView {
            GeometryReader { geomtry in
                VStack {
                    Spacer()
                    HStack {
                        VStack(alignment: .leading) {
                            TextField("First Name", text: $firstName)
                                .customTextField()
                        }
                        VStack(alignment: .leading) {
                            TextField("Last Name", text: $lastName)
                                .customTextField()
                        }
                    }
                    TextField("Address Line 1", text: $addressLine1)
                        .customTextField()
                    TextField("Address Line 2", text: $addressLine2)
                        .customTextField()
                    HStack {
                        TextField("City", text: $city)
                            .customTextField()
                            .frame(width: geomtry.size.width * 0.48)
                        Spacer()
                        TextField("ST", text: $state)
                            .customTextField()
                            .frame(width: geomtry.size.width * 0.18)
                        Spacer()
                        TextField("Zip", text: $zip)
                            .customTextField()
                            .frame(width: geomtry.size.width * 0.28)
                    }
                    TextField("Country", text: $country)
                        .customTextField()
                    Spacer()
                    Spacer()
                }
                ContactPicker(showPicker: $showPicker, onSelectContact: {contact in
                    firstName = contact.givenName
                    lastName = contact.familyName
                    if contact.postalAddresses.count > 0 {
                        if let addressString = (
                            ((contact.postalAddresses[0] as AnyObject).value(forKey: "labelValuePair")
                                as AnyObject).value(forKey: "value"))
                            as? CNPostalAddress {
                            // swiftlint:disable:next line_length
                            let mailAddress = CNPostalAddressFormatter.string(from: addressString, style: .mailingAddress)
                            addressLine1 = "\(addressString.street)"
                            addressLine2 = ""
                            city = "\(addressString.city)"
                            state = "\(addressString.state)"
                            zip = "\(addressString.postalCode)"
                            country = "\(addressString.country)"
                            print(mailAddress)
                        }
                    } else {
                        addressLine1 = "No Address Provided"
                        addressLine2 = ""
                        city = ""
                        state = ""
                        zip = ""
                        country = ""
                        print("No Address Provided")
                    }
                    self.showPicker.toggle()
                }, onCancel: nil)
            }
            .padding([.leading, .trailing], 10 )
            .navigationTitle("Recipient")
            .navigationBarItems(trailing:
                                    HStack {
                                        Button(action: {
                                            let contactsPermsissions = checkContactsPermissions()
                                            if contactsPermsissions == true {
                                                self.showPicker.toggle()
                                            }
                                        }, label: {
                                            Image(systemName: "magnifyingglass")
                                                .font(.largeTitle)
                                                .foregroundColor(.green)
                                        })
                                        Button(action: {
                                            saveRecipient()
                                            self.presentationMode.wrappedValue.dismiss()
                                        }, label: {
                                            Image(systemName: "square.and.arrow.down")
                                                .font(.largeTitle)
                                                .foregroundColor(.green)
                                        })
                                        Button(action: {
                                            self.presentationMode.wrappedValue.dismiss()
                                        }, label: {
                                            Image(systemName: "chevron.down.circle.fill")
                                                .font(.largeTitle)
                                                .foregroundColor(.green)
                                        })
                                    }
            )
        }
    }
    
    func saveRecipient() {
        print("Saving...")
        if firstName != "" {
            let recipient = Recipient(context: self.moc)
            recipient.firstName = firstName
            recipient.lastName = lastName
            recipient.addressLine1 = addressLine1.capitalized(with: NSLocale.current)
            recipient.addressLine2 = addressLine2.capitalized(with: NSLocale.current)
            recipient.state = state.uppercased()
            recipient.city = city.capitalized(with: NSLocale.current)
            recipient.zip = zip
            recipient.country = country.capitalized(with: NSLocale.current)
        }
        do {
            try moc.save()
        } catch let error as NSError {
            print("Save error: \(error), \(error.userInfo)")
        }
    }
    
    func checkContactsPermissions() -> Bool {
        let authStatus = CNContactStore.authorizationStatus(for: .contacts)
        switch authStatus {
        case .restricted:
            print("User cannot grant premission, e.g. perental controls are in force.")
            return false
        case .denied:
            print("User has denided permissions")
            // add a popup to say you have denied permissions
            return false
        case .notDetermined:
            print("you need to request authorization via the API now")
        case .authorized:
            print("already authorized")
        @unknown default:
            print("unknown error")
            return false
        }
        let store = CNContactStore()
        if authStatus == .notDetermined {
            store.requestAccess(for: .contacts) {success, error in
                if !success {
                    print("Not authorized to access contacts. Error = \(String(describing: error))")
                    exit(1)
                }
                print("Authorized")
            }
        }
        return true
    }
    

    }`

    opened by TheApApp 1
  • Add option to specify currency symbol.  Updated documentation

    Add option to specify currency symbol. Updated documentation

    This option si backwards compatible and sticks to default currency system symbol. If set, the currency is forced to the currency symbol specified in the initializer.

    opened by jgalindosl 1
  • The color of the text field does not automatically change

    The color of the text field does not automatically change

    This section of code is wrong https://github.com/youjinp/SwiftUIKit/blob/3f3dc095ead21c90355e4b18ad6fc5ecb2bc97e7/Sources/SwiftUIKit/views/CurrencyTextField.swift#L151

    Rather that checking the color at runtime, it should just set the color to UIColor.label so that the system automatically adapts it when the user changes it. Will submit a PR later when I’m front of a computer

    opened by ghost 0
  • Update currencyTextField and readme

    Update currencyTextField and readme

    • update CurrencyTextField to be focusable
    • removed keyboard accessory "done" button
    • use view extensions dismissKeyboardOnTap and dismissKeyboardOnSwipe instead to dismiss the keyboard
    • update readme
    opened by youjinp 0
  • Given option to pass locale in Currency TextFields

    Given option to pass locale in Currency TextFields

    Currency TextField was taking phone locale for Number Formatter. there was no option to provide fixed Locale added that.

    The TextField was taking only 9 chracters. Increased that to 20 characters.

    opened by veereshKS 0
  • CurrencyTextField should use decimal rather than double

    CurrencyTextField should use decimal rather than double

    given this is dealing with financial data should really use Decimal to ensure no loss of precision for large values or for currencies that commonly use large values eg. yen, Indonesian rupiah etc.

    opened by bcyng 0
  • ContactPicker: closes parent sheet when ContactPicker is closed

    ContactPicker: closes parent sheet when ContactPicker is closed

    removing line 58 fixes it,

    viewModel.dummy.dismiss(animated: true)
    

    but I believe it was there for some reason. I'm new to Swift so I need some help in making a PR for that.

    opened by dderg 1
  • CurrencyTextField textAlignment property is not used

    CurrencyTextField textAlignment property is not used

    Setting textAlignment in the CurrencyTextField constructor does not do anything. Alignment is set by the SwiftUI multilineTextAlignment context, and the textAlignment property is never accessed in the source code.

    opened by AustinBrrtt 1
  • CurrencyTextField ignores RoundedBorderTextFieldStyle

    CurrencyTextField ignores RoundedBorderTextFieldStyle

    Sorry, me again, it seems that its not possible to apply this setting to the Currency Text Field:

    .textFieldStyle(RoundedBorderTextFieldStyle())

    When I add this option nothing about the text field appearance changes, it is in a view with other normal TextFields and so I would like it to be styled the same. I can get close to the effect I am wanting using this:

    .foregroundColor(Color.black)
    .background(Color.white)
    .cornerRadius(12)
    

    This gives a white background with black text and rounded corners, but just like a normal TextField when viewing in Dark Mode it's all black as it ignores the white background. So the above styling option would fix that but doesn't work.

    Kind Regards

    Plasma

    opened by PlasmaSoftUK 1
Releases(v0.0.17)
Owner
youjinp
youjinp
The missing Apple Weather App for Mac.

BetterWeather The missing Weather App for your Mac and iPad. Installation for mac. Download the notarized, universal binary from here Click the curren

Aayush 21 Jul 31, 2022
A SwiftUI system components and interactions demo app

SwiftUI Kit A SwiftUI system components and interactions demo app based on iOS 14, macOS Big Sur, watchOS 7, and tvOS 14. Use the SwiftUI Kit app to s

Jordan Singer 2k Jan 6, 2023
A Swift library for documenting, isolating, and testing SwiftUI, UIKIt & AppKit components.

A Swift library for documenting, isolating, and testing SwiftUI, UIKit & AppKit components. Minimal Example An example demonstrated with the Slider ui

Hayden Pennington 9 Dec 15, 2022
Introspect underlying UIKit components from SwiftUI

Introspect for SwiftUI Introspect allows you to get the underlying UIKit or AppKit element of a SwiftUI view. For instance, with Introspect you can ac

Siteline 3.7k Jan 4, 2023
NeoPop is CRED's inbuilt library for using NeoPop components in your app

NeoPOP NeoPOP is CRED's inbuilt library for using NeoPOP components in your app. What really is NeoPOP? NeoPOP was created with one simple goal; to cr

CRED 125 Dec 29, 2022
SwiftUI Backports - Introducing a collection of SwiftUI backports to make your iOS development easier

SwiftUI Backports Introducing a collection of SwiftUI backports to make your iOS development easier. Many backports support iOS 13+ but where UIKIt fe

Shaps 530 Dec 28, 2022
A collection of Swift functions, extensions, and SwiftUI and UIKit Views.

J's Helper A collection of Swift functions, extensions, and SwiftUI and UIKit Views. Legend: ?? UIKit ?? SwiftUI ?? Shared Installation In XCode 12 go

Jem Alvarez 3 Oct 1, 2022
Native iOS app built in SwiftUI, displays a collection of user's books.

Native iOS app built in SwiftUI, displays a collection of user's books.

Matthew Eilar 1 May 23, 2022
A collection of additional custom SFSymbols for Swift

MoreSFSymbols A collection of additional custom SFSymbols for Swift Content Usage Symbols Developer Logos Contributing Licence Usage iOS 15.0: Downloa

Cameron Shemilt 57 Dec 2, 2022
iOS App that allows a pilot to check drone photo collection after a mapping mission for any issues

DronePhotoChecker iOS App that allows a pilot to check drone photo collection after a mapping mission for any issues. Features: Connects to DJI drone

null 0 Dec 30, 2021
Movies is a collection of a few UI/UX ideas that came up whilst developing an iOS app

Movies Introduction: Movies is a collection of a few UI/UX ideas that came up whilst developing an iOS app called Wattmo You'll find tableviews, detai

Kevin Mindeguia 861 Nov 19, 2022
🎲 100% SwiftUI 2.0, classic 2048 game [SwiftUI 2.0, iOS 14.0+, iPadOS 14.0+, macOS 11.0+, Swift 5.3].

swiftui-2048 If you like the project, please give it a star ⭐ It will show the creator your appreciation and help others to discover the repo. ✍️ Abou

Astemir Eleev 174 Dec 17, 2022
A simple SwiftUI Application to demonstrate creation of UI using SwiftUI.

WatchShop_UI A simple SwiftUI Application to demonstrate creation of UI using SwiftUI. How to run the project ? Fork the project. Run the project usin

Shubham Kr. Singh 12 Apr 15, 2022
E-commerce app built in SwiftUI. Built in the course SwiftUI Masterclass in Udemy.

Touchdown-SwiftUI E-commerce app built in SwiftUI. Built in the course SwiftUI Masterclass in Udemy. Main components and concepts used: @EnvironmentOb

Jorge Martinez 5 Aug 18, 2022
A multiplatform SwiftUI project demonstrating various SwiftUI features.

WikiDemo A multiplatform SwiftUI project demonstrating various SwiftUI features, including creating a master-detail interface. It's a multiplatform ve

Swift Dev Journal 6 Oct 17, 2022
SwiftUI Projects from Udemy SwiftUI Masterclass

SwiftUI Masterclass Repos: AsyncImage (N/A) Fructus (finished): an app for getting information about different fruits. Data comes from json files. Afr

Patrick Spafford 1 Mar 3, 2022
Best architecture for SwiftUI + CombineBest architecture for SwiftUI + Combine

Best architecture for SwiftUI + Combine The content of the presentation: First of the proposed architectures - MVP + C Second of the proposed architec

Kyrylo Triskalo 3 Sep 1, 2022
Weather-swiftui - An example of using SwiftUI

weather-swiftui An example of using SwiftUI Installation Get openweather api key

null 0 Jan 1, 2022
Orbit-swiftui - Orbit design system implemented in SwiftUI for iOS

Orbit is a SwiftUI component library which provides developers the easiest possi

Kiwi.com 37 Jan 3, 2023