Giter Site home page Giter Site logo

swiftuikit's Introduction

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")
                }
            }
        }
    }
}

swiftuikit's People

Contributors

alex-taffe avatar jgalindosl avatar kudit avatar youjin avatar youjinp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

swiftuikit's Issues

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')

Support arabic number

Hello sir, thank you for your code, but as I noticed this currency text field does not support Arabic numbers (١٢٣٤٥٦٧٨٩٠).

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()
                }
            }
        }
    }
}

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

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

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
}

}`

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.

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?")
    }
}

`

Consider adding a license

Hi, thanks for creating this repo and I found the currency text field very useful. Would you consider to add a license for your project? Thanks

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.