GithubHelp home page GithubHelp logo

luximetr / anyformatkit Goto Github PK

View Code? Open in Web Editor NEW
425.0 17.0 59.0 1.57 MB

Simple text formatting in Swift

License: MIT License

Ruby 0.68% Swift 99.12% Objective-C 0.15% Shell 0.05%
symbols regex swift formatter delegate uitextfield uitextview phone-number card-number cocoapods

anyformatkit's Introduction

AnyFormatKit: Simple text formatting in Swift

CI Status Pod Version License Platform SwiftPM compatible Swift

Text formatting framework written on Swift 5.0.

Features

Features
🎭 Convert string into formatted string and vice versa
🚴 Formatting text during typing
#️⃣ Set format using '#' characters like '### ##-###'
😛 Supporting emojis
💲 Formatting money amount
🅿️ Formatting with placeholders
🌱 UITextField and UITextView support

Example

To run the example project, clone the repo and run pod install from the Example directory first.

Demo

Phone number example

Currency example

Card number example

Placeholder number number example

Requirements

  • iOS 8.0+
  • Swift 4.0+
  • Xcode 9.0+

SwiftUI

AnyFormatKit has SwiftUI version, that exists as separate framework AnyFormatKitSwiftUI

Migration Guides

Installation

CocoaPods

AnyFormatKit is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'AnyFormatKit', '~> 2.5.2'

Then, run the following command:

$ pod install

Swift Package Manager

AnyFormatKit is available with Swift Package Manager. Once you have your Swift package set up, than simply add AnyFormatKit to the dependencies value of your Package.swift

dependencies: [
    .package(url: "https://github.com/luximetr/AnyFormatKit.git", .upToNextMajor(from: "2.5.2"))
]

Usage

Import

import AnyFormatKit

Formatting with TextFormatter

let phoneFormatter = DefaultTextInputFormatter(textPattern: "### (###) ###-##-##")
let phoneInputController = TextFieldInputController()

textField.delegate = phoneInputController
phoneInputController.formatter = phoneFormatter

Get only your input

phoneNumberFormatter.unformat("+51 (013) 442-55-11") // +51013442551 

In case you want to use textField.delegate by yourself

let phoneFormatter = DefaultTextInputFormatter(textPattern: "### (###) ###-##-##")

// inside of UITextFieldDelegate shouldChangeTextIn method
let result = formatter.formatInput(currentText: textField.text ?? "", range: range, replacementString: string)
textField.text = result.formattedText
textField.setCursorLocation(result.caretBeginOffset)

You can find example of setCursorLocation here

Formatter kinds

Author

luximetr, [email protected]

Say thank you

License

AnyFormatKit is available under the MIT license. See the LICENSE file for more info.

anyformatkit's People

Contributors

caramell0 avatar devcarlos avatar jimvanzummeren avatar juanxme avatar jvanzummeren avatar ky1vstar avatar luximetr avatar luximetreducation avatar twodollarsesq 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

anyformatkit's Issues

Undefined symbol error trying to build

See error below
Xcode 12.5

Undefined symbols for architecture x86_64:
  "type metadata accessor for AnyFormatKit.DefaultTextInputFormatter", referenced from:
      TapCard.SocialLink.getFormattedNumber() -> Swift.String in SocialLink.o
  "AnyFormatKit.DefaultTextInputFormatter.__allocating_init(textPattern: Swift.String, patternSymbol: Swift.Character) -> AnyFormatKit.DefaultTextInputFormatter", referenced from:
      TapCard.SocialLink.getFormattedNumber() -> Swift.String in SocialLink.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Exposing maximumIntegerCharacters in SumTextInputFormatter

Hi,

In the version 2.0.1 that I previously used, we can change the maximumIntegerCharacters from SumTextInputFormatter. Previously it is possible since SumTextInputFormatter is inherited from SumTextFormatter, and maximumIntegerCharacters is declared public in SumTextFormatter.

On the current version (2.2.1) this is not the case anymore. Now SumTextInputFormatter are composed from SumTextFormatter and the instance of it (textFormatter) is declared as private. Now we have no way to change maximumIntegerCharacters if what we use is SumTextInputFormatter. Changing maximumIntegerDigits of its numberFormatter won't affect it.

I hope this can be added (or maybe give us another way to change it)

DefaultTextInputFormatter subclassing

In DefaultTextInputFormatter method formatInput calls textFormatter.unformat and textFormatter.format methods.
I suggest to call self.format and self.unformat instead, to allow for subclasses change the behavior correctly.

dyld: Library not loaded: @rpath/AnyFormatKit.framework/AnyFormatKit

I'm having the following error when trying to run my app with AnyFormatKit:

dyld: Library not loaded: @rpath/AnyFormatKit.framework/AnyFormatKit
  Referenced from: /Users/recruta/Library/Developer/CoreSimulator/Devices/1DA80144-E533-42D4-AD37-330F4DC051C0/data/Containers/Bundle/Application/E1D7058C-7D21-47F5-B513-180EC649B14D/IPS.app/IPS
  Reason: no suitable image found.  Did find:
	/Users/recruta/Library/Developer/CoreSimulator/Devices/1DA80144-E533-42D4-AD37-330F4DC051C0/data/Containers/Bundle/Application/E1D7058C-7D21-47F5-B513-180EC649B14D/IPS.app/Frameworks/AnyFormatKit.framework/AnyFormatKit: required code signature missing for '/Users/recruta/Library/Developer/CoreSimulator/Devices/1DA80144-E533-42D4-AD37-330F4DC051C0/data/Containers/Bundle/Application/E1D7058C-7D21-47F5-B513-180EC649B14D/IPS.app/Frameworks/AnyFormatKit.framework/AnyFormatKit'

	/Users/recruta/Library/Developer/CoreSimulator/Devices/1DA80144-E533-42D4-AD37-330F4DC051C0/data/Containers/Bundle/Application/E1D7058C-7D21-47F5-B513-180EC649B14D/IPS.app/Frameworks/AnyFormatKit.framework/AnyFormatKit: required code signature missing for '/Users/recruta/Library/Developer/CoreSimulator/Devices/1DA80144-E533-42D4-AD37-330F4DC051C0/data/Containers/Bundle/Application/E1D7058C-7D21-47F5-B513-180EC649B14D/IPS.app/Frameworks/AnyFormatKit.framework/AnyFormatKit'

	/Users/recruta/Library/Developer/CoreSimulator/Devices/1DA80144-E533-42D4-AD37-330F4DC051C0/data/Containers/Bundle/Application/E1D7058C-7D21-47F5-B513-180EC649B14D/IPS.app/Frameworks/AnyFormatKit.framework/AnyFormatKit: required code signature missing for '/Users/recruta/Library/Developer/CoreSimulator/Devices/1DA80144-E533-42D4-AD37-330F4DC051C0/data/Containers/Bundle/Application/E1D7058C-7D21-47F5-B513-180EC649B14D/IPS.app/Frameworks/AnyFormatKit.framework/AnyFormatKit' 

Is this an error in the library? Can someone help me figure it out?

Edit: I'm using Cocoapods to install it.

Doesn't work with xcode 10 as a cocoa pod

When I build an existing project (that was fine in xcode 9) with xcode 10, I get the following error:

Multiple commands produce '/Users/xxxUserNamexxx/Library/Developer/Xcode/DerivedData/xxxAppxxx-budrinxtnjnzsobhgwboeiqsfcsk/Build/Products/Debug-iphonesimulator/AnyFormatKit/AnyFormatKit.framework/Info.plist':
1) Target 'AnyFormatKit' (project 'Pods') has copy command from '/Users/xxxAppLocationxxx/Pods/AnyFormatKit/Source/Info.plist' to '/Users/xxxUserNamexxx/Library/Developer/Xcode/DerivedData/xxxAppxxx-budrinxtnjnzsobhgwboeiqsfcsk/Build/Products/Debug-iphonesimulator/AnyFormatKit/AnyFormatKit.framework/Info.plist'
2) Target 'AnyFormatKit' (project 'Pods') has process command with output '/Users/xxxUserNamexxx/Library/Developer/Xcode/DerivedData/xxxAppxxx-budrinxtnjnzsobhgwboeiqsfcsk/Build/Products/Debug-iphonesimulator/AnyFormatKit/AnyFormatKit.framework/Info.plist'

I removed it from the podfile and used carthage and then it works. Looks like there is something wrong in the pod specifications?

Prevention from passing non-numeric signs

It would be great if the text field would remove non-numeric signs on phone paste (f.e. pasted tel. +48-123-123-123 to (48)-123-123-123 for pattern (##)-###-###-###) - so text field receives only numbers from pasted text and formats it accordingly.

Autofill

If a TextField has textContentType set, autofill options will appear on the keyboard.
Tapping those options does nothing when using TextInputField.

How to initialize MulticastDelegate in my own UITextField class?

When I add TextInput protocol into my own UITextField class and It wants me to initialize MulticastDelegate but I don't know how. I tried MulticastDelegate() but It gives "'MulticastDelegate' initializer is inaccessible due to 'internal' protection level" error.

Can I use this TextController/TextInputFormatter with TextInputField set in storyboard?

I have tried to use this library in my project. I have added such code in ViewController:

 let textInputController1 = TextInputController()
        textInputController1.formatter = TextInputFormatter(textPattern: "(###) ###-####")
        textInputController1.textInput = mobilePhoneTextField

And then I have added TextInputField custom class in Identity Inspector of mobilePhoneTextField (here it is IBOutlet with type TextInputField)

But live formatting doesn't work.

Cannot Implement TextInput protocol

Due to a lack of an accessible init on MulticastDelegate class there is no way to create a class implementing the TextInput protocol.

When trying to instantiate a MulticastDelegate, I get the following error:

'MulticastDelegate<T>' initializer is inaccessible due to 'internal' protection level

how change group separator to whitespace

when i set let sumFormatter = SumTextInputFormatter(textPattern: "# ###,## ₽") cursor position wrong when delete text. let sumFormatter = SumTextInputFormatter(textPattern: "#.###,## ₽") delete work fine

Proper way to create a custom TextInputFormatter

Hello, I'm using the library but needed some custom input formatter, my first instinct was to check the implementation of the DefaultTextInputFormatter and copying its structure changing it for my case.

However when overriding theformatInput(currentText: String, range: NSRange, replacementString text: String) -> FormattedTextValue function I can't init the FormattedTextValue type due to the struct not having a public init

Is there a way to achieve what I'm looking using other methods or the lib should have a public init for this case?

Swift 4.2?

Any plans to update for Swift 4.2? and if so how soon?

Have a running project that can't get to compile with Swift 4.2.

If I update all the new replacements wanted for 4.2, it is stuck on 2 places (textView's & textField's input overrides). Basically, the Swift-Language changes wanted to change [rename]: 'NSAttributedStringKey' to 'NSAttributedString.Key'. Which then (ultimately) creates these 2 issues:

  1. Property 'defaultTextAttributes' with type '[String : Any]' cannot override a property with type '[NSAttributedString.Key : Any]' -- FOR: TextField

  2. Property 'typingAttributes' with type '[String : Any]' cannot override a property with type '[NSAttributedString.Key : Any]' -- FOR: TextView

These need to get a property Type change since now the compiler doesn't like it.

Xcode 14 bitcode

Hi, in Beta Xcode 14 there is an error when building application.
Is it possible to enable bitcode, or is there any other problem?
error build: '/Users/marekslaninka/Library/Developer/Xcode/DerivedData/Surglogs-blzrfqsijprnfacgxqyzrxxylqzd/Build/Products/Debug-iphoneos/AnyFormatKit.o' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. file '/Users/marekslaninka/Library/Developer/Xcode/DerivedData/Surglogs-blzrfqsijprnfacgxqyzrxxylqzd/Build/Products/Debug-iphoneos/AnyFormatKit.o' for architecture arm64

Release 0.1.3

Hi @luximetr,

Was great that you could merge those pull requests so quickly but i think there is still a release missing. I understand that maintaining a Cocoapod / Github can take up time and you're probably busy on different projects. I don't mind helping you out a bit if you give me some access rights on Github and Cocoapods so i can assist in maintaining it.

I'm also actively maintaining Markymark, as a reference.

Let me know what you think,

Kind regards,

Jim van Zummeren
M2mobi

How to set the delegate?

Hi @luximetr
I like this library and really want to use it, but I really need to get access to some delegate methods for when the text changes, didBegin/didEnd editing, shouldReturn etc.

How do I attach a delegate. When I try to do:
mField.textInputFieldDelegates = self

I get the error message:
Cannot assign to property: 'textInputFieldDelegates' setter is inaccessible

Can you advise me?

(PS Using AnyFormatKit (0.1.2))

Why iOS9 is not supported? :'(

Tried to use it in my project which is iOS9.3+ and see error
Compiling for iOS 9.3, but module 'AnyFormatKit' has a minimum deployment target of iOS 10.0
That's sad..

Filtering entered/pasted characters

Users can input any characters either by using a physical keyboard, or copy pasting into FormatTextField.

The issue is most prominent when the user is trying to paste something. Here is our example:

private struct AccountEditorView: View {
    @Binding var text: String
    let prompt: String
    let textColor: Color
    let cursorColor: Color

    var body: some View {
        FormatTextField(
            unformattedText: $text,
            placeholder: prompt,
            textPattern: "######## - ######## - ########"
        )
            .font(.body1)
            .keyboardType(.numberPad)
            .foregroundColor(textColor)
            .accentColor(cursorColor)
    }
}

user pastes: 12345678 - 12345678 - 12345678
FormatTextField shows: 12345678 - 12345678 - 12

Despite Tinamu's suggestion on a previous issue, this problem cannot be solved on SwiftUI view level, nor with using .onReceive modifier, nor with using a custom Binding implementation that filters the input, because these filtering closures run after the paste happened.

Suggested solution

FormatTextField should accept an optional CharacterSet as an init argument.
If given, use this characterset to filter user input at the very first line of
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool

The following proof of concept solution seems to fix the problem:

        private let  allowedInput: CharacterSet = .decimalDigits
        
        public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
            let string = String(string.unicodeScalars.filter { self.allowedInput.contains($0) })

Wrong caret calculation in SumTextInputFormatter

In my app pattern for SumTextInputFormatter calculates by this small hack:

let f = NumberFormatter()
f.numberStyle = .currency
let source = f.string(from: NSNumber(value: 1234.56))
guard let pattern = source?.replacingOccurrences(of: "[0-9]", with: "#", options: .regularExpression) else {
    return
}
formatter = SumTextInputFormatter(textPattern: pattern)

So, for Russian locale on the device pattern will be # ###,## ₽ and for English locale, it will be $#,###.##. This hack adopts my app for multiple locales and ICU CLDR.

And here we are. The problem occurred when we use Russian locale and trying to delete characters with an amount greater than 1000 (In this case text formats with grouping symbol with space, like a "1 220"). When amount less than 1000 or locale is English – everything works fine.

Amount < 1000 – Works fine:
2019-08-07 12 12 32

Amount > 1000 – Doesn't work:
2019-08-07 12 13 11

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.