An open source package for as-you-type formatting in SwiftUI.

Last update: Apr 18, 2022

DiffableTextViews

An open source package for as-you-type formatting in SwiftUI.

DiffableTextFieldXAmount.gif

DiffableTextFieldXPhone.gif

Features

Feature Description
⌨️ Responsive Formats text as you type
🪄 Automagical Binds text to a chosen data type
✔️ Proper Validates and autocorrects input
🛠️ Versatile Uses snapshots and attributes
🏃‍♂️ Performant Uses O(n) differentiation algorithms
🏝️ Standalone Uses no remote dependencies
📖 Open source 100% transparent, as it should be

Algorithms

Algorithm Description Complexity
📖 ∆Text Determines selection when text changes ≤ Linear
↔️ ∆Selection Determines selection when selection changes ≤ Linear
⭐ Attributes Determines selection based on attributes ≤ Linaer

Installation

Simple instructions on how to install this package.

Swift Package Manager

  1. Select https://github.com/oscbyspro/DiffableTextViews.
  2. Select a VERSIONED release.

Import

import DiffableTextViews

Requirements

Swift iOS iPadOS Mac Catalyst tvOS
5.0+ 15.0+ 15.0+ 15.0+ 15.0+

Examples

The example app provides quick-and-easy-to-use customization tools.

Number Pattern
Number Pattern

Installation

Download this package and compile/run it with Xcode.

Views

DiffableTextField

A text field that binds values and formats them as you type.

Features

Feature Description
📱 SwiftUI Value, style, done
⛰️ Environment Uses environment values
🔎 Focus Supports SwiftUI.FocusState

Environment

environment(\.locale, _:)
environment(\.layoutDirection, _:)
diffableTextViews_disableAutocorrection(_:)
diffableTextViews_font(_:)
diffableTextViews_foregroundColor(_:)
diffableTextViews_multilineTextAlignment(_:)
diffableTextViews_onSubmit(_:)
diffableTextViews_submitLabel(_:)
diffableTextViews_textContentType(_:)
diffableTextViews_textFieldStyle(_:)
diffableTextViews_textInputAutocapitalization(_:)
diffableTextViews_tint(_:)

Styles

NumberTextStyle (Source, Tests)

A style that binds localized numbers using various formats.

Features

Feature Description
🪙 Values Decimal, Double and (U)Int(8-64)
❔ Optionals Optional and non-optional values
🏹 Precision Up to 38 digits of precision
🧱 Bounds Values are clamped to bounds
🎨 Formats Number, currency and percent
🏞️ Locales Supports every Foundation.Locale
2️⃣ Bilingual Accepts both local and ASCII inputs 

Examples

DiffableTextFieldXAmount.gif

import DiffableTextViews
import SwiftUI

//*============================================================================*
// MARK: View
//*============================================================================*

struct DiffableTextFieldXAmount: View {

    //=------------------------------------------------------------------------=
    // MARK: State
    //=------------------------------------------------------------------------=

    @State var amount = 0 as Decimal
    @State var locale = Locale(identifier: "sv_SE")

    //=------------------------------------------------------------------------=
    // MARK: Body
    //=------------------------------------------------------------------------=

    /// default precision is chosen based on currency
    var body: some View {
        DiffableTextField(value: $amount) {
            .currency(code: "SEK")
            .bounds((0 as Decimal)...)
            // .precision(integer: 1..., fraction: 2)
        }
        .environment(\.locale, locale)
        .diffableTextViews_keyboardType(.decimalPad)
    }
}

PatternTextStyle (Source, Tests)

A style that processes characters laid out in custom patterns.

Features

Feature Description
🏁 Pattern Characters are laid out as described by a pattern
♟️ Placeholders Placeholders represent not-yet-assigned values
✊ Independance Supports multiple placeholders with different rules
👻 Invisibility Pattern suffix can easily be \.hidden()

Examples

DiffableTextFieldXPhone.gif

import DiffableTextViews
import SwiftUI

//*============================================================================*
// MARK: View
//*============================================================================*

struct DiffableTextFieldXPhone: View {

    //=------------------------------------------------------------------------=
    // MARK: State
    //=------------------------------------------------------------------------=

    @State var number: String = ""
    @State var style = PatternTextStyle<String>
        .pattern("+## (###) ###-##-##")
        .placeholder("#") { $0.isASCII && $0.isNumber }
        .equals(())
    
    //=------------------------------------------------------------------------=
    // MARK: Body
    //=------------------------------------------------------------------------=
    
    var body: some View {
        DiffableTextField(value: $number, style: style)
            .diffableTextViews_keyboardType(.numberPad)
    }
}

WrapperTextStyle(s) (Source, Tests)

Decorative styles that modify the behavior of their content.

Style Description Method
Constant Prevents style transformations constant()
Equals Binds the style's equality to a proxy value equals(_:)

GitHub

https://github.com/oscbyspro/DiffableTextViews
Comments
  • 1. Support: optional numbers.

    When an optional value is nil the view should show a placeholder. While supporting Optional<T> is orthogonal to number processing, and arguably does little to improve UX, it’s like a 0th class citizen in Swift-ville and people just expect it to work, even if SwiftUI.TextField doesn’t support it.

    Reviewed by oscbyspro at 2022-05-04 12:34
  • 2. Environment overrides `Style/onSetup(_:)`

    In v4.0.0+ it works like it does in SwiftUI. I thought it was rather neat, however, that NumberTextStyle could choose the correct keyboard automatically. So I will have to think about how I can reintroduce this feature, so it works alongside the environment.

    Reviewed by oscbyspro at 2022-05-10 15:52
  • 3. SwiftUI toolbar does not appear above keyboard.

    SwiftUI.TextField can add a toolbar above the keyboard as shown below.

    view.toolbar {
        ToolbarItemGroup(placement: .keyboard) {
            Spacer()
            Button("Done") { /* action */ }
        }
    }
    

    This does not work on DiffableTextField, however. It should be fixed, if possible, otherwise an alternative should be offered.

    Reviewed by oscbyspro at 2022-03-24 07:18
  • 4. UIViewRepresentableContext

    Learned that UIViewRepresentableContext provides environment values. It can/should replace the use of environment observers. https://developer.apple.com/documentation/swiftui/uiviewrepresentablecontext

    Reviewed by oscbyspro at 2022-03-22 06:19
  • 5. Improve project's modularization.

    The current structure cannot export text styles, as it would create cyclical dependencies. It is also ill suited for supporting additional platforms such as macOS, because DiffableTextViews becomes too crowded. A solution is to restructure the project as

    Level 0: 
    - DiffableTextKit
    
    Level 1:
    - NumericTextStyles
    - PatternTextStyles
    - DiffableTextViews_iOS
    - DiffableTextViews_macOS
    
    Level 2:
    - DiffableTextViews [exports]
    

    where the dependencies are Level 0 —> Level 1 —> Level 2 and the current DiffableTextViews target is split into two new targets: DiffableTextKit (models) and DiffableTextViews_iOS. A new DiffableTextViews then exports based on platform.

    Reviewed by oscbyspro at 2022-03-05 15:00
  • 6. Use SwiftUI-esque environment values and retire ProxyTextField.

    This makes it easier to adopt real SwiftUI environment values when Apple realizes that making them public is the most straight forward business decision in the history of business decisions. It's the difference between an awesome 3rd party ecosystem and a barren wasteland. SwiftUI without public environment values is like UIKit without subclasses. Image how unwieldy SwiftUI would be if it used per-view modifiers such as someTextModifier(_:), someTextFieldModifier(_:), etc.

    Example

    keyboardType(_:) // SwiftUI
    diffableTextViews_keyboardType(_:) // DiffableTextViews
    

    Documentation

    The README should contain a table of all UITextField related SwiftUI modifiers. It should show whether the modifier works, if there is a DiffableTextViews specific analogue, or if it does not work. Some things just work, like multilineTextAlignment(_:) because Apple decided to make just that one public for some reason. It should also show when the modifier is applied: on setup or on update, which should match the behavior of SwiftUI.TextField.

    Edit: layoutDirection and disableAutocorrection are also public.

    Considerations

    It is probably a good idea to also offer analogue methods for environment values that are already exposed, because it is a lot of cognitive overhead to keep track of what works as normal and what doesn't. It's much easier to assume that everything or nothing works as normal.

    Reviewed by oscbyspro at 2022-05-07 05:34
  • 7. Disable UITextField marked text…

    Marked text: An input session used by some languages to combine characters. It does NOT mean text selection.

    It’s not compatible with as-you-type formatting, or requires a decent amount of additional work. If you need marked text, for whatever reason, please pitch your use case and how you want it to work. Until then, I’ve decided to disable it.

    Also, the previous mini-rework made it so the app crashes when marked text is entered due to an index out of bounds error. That will be fixed in the next update.

    Reviewed by oscbyspro at 2022-05-06 13:23
  • 8. Close SwiftUI.TextField behavior gap.

    Two easy-to-fix behavioral differences.

    A) onSubmit(of:)

    SwiftUI closure triggers stack (first in, last out). So

    SwiftUI.TextField(…)
        .onSubmit(of: .text) { … }
        .onSubmit(of: .text) { … }
        .onSubmit(of: .text) { … }
    

    the above example will run each closure on submit.

    B) textFieldShouldReturn(_:)

    SwiftUI.TextField always resigns first responder status on submit.

    Reviewed by oscbyspro at 2022-04-21 03:26
  • 9. Reject new styles when equal.

    This would remove the need for #77. I also think it would be more SwiftUI-y, as equatable views do not update unless their new values are different, for example. It's expected that styles work the same way.

    Reviewed by oscbyspro at 2022-04-01 13:49
  • 10. Rework: DiffableTextStyle protocols.

    Required by #74, eventually. It is important that the type is the same on all platforms. A solution resulting in some DiffableTextStyleXiOS<.Value == Value> and some DiffableTextStyleXmacOS<.Value == Value> is not an option.

    Reviewed by oscbyspro at 2022-03-31 18:27
  • 11. Rework: ConstantTextStyle.

    ConstantTextStyle wrapper does two things (it should only really do one).

    • it prevents changes through the environment (skips the transformation)
    • it does what style.equals(()) would do if Void conformed to Equatable

    It should be split into .equals() and .ignoresEnvironmentValues() or similar.

    Reviewed by oscbyspro at 2022-03-31 12:41
  • 12. Awaiting generalized opaque type constraints

    Wrapper styles can/should then be made internal, and all methods previously exposing them can/should then return some DiffableTextStyle<.Value == Value> or equivalent.

    Reviewed by oscbyspro at 2022-03-31 13:05
  • 13. Awaiting improved interoperability.

    Public UIKit compatible environment values

    Mimicking environment values adds a lot of overhead, for library authors and especially for users. Nobody wants 12 different modules with 12 different ways of writing the same value to the environment. In an alternative universe, where environment values are exposed, there is peace and harmony and all nations sing Kumbayah because custom 3rd party iOS libraries just work as if Apple themselves had built them.

    Use of SwiftUI.Font, environment \.font

    Requires public SwiftUI.Font to UIKit.UIFont conversion.

    Use of view.toolbar as input accessory view

    Requires exposure of whatever is used behind the scenes.

    Use of other environment values

    Private environment values == decent 3rd party libraries. Public environment values == amazing 3rd party libraries.

    Reviewed by oscbyspro at 2022-03-24 12:11
A curated list of Open Source example iOS apps developed in Swift
A curated list of Open Source example iOS apps developed in Swift

 A curated list of Open Source example iOS apps developed in Swift. An amazing list for people who are beginners and learning ios development and for ios developers who need any example app or feature.

May 9, 2022
CodeEdit App for macOS – Elevate your code editing experience. Open source, free forever.
CodeEdit App for macOS – Elevate your code editing experience. Open source, free forever.

CodeEdit for macOS CodeEdit is a code editor built by the community, for the community, written entirely and unapologetically for macOS. Features incl

May 16, 2022
SwiftUI package to present a Bottom Sheet interactable view with the desired Detents. Also known as Half sheet.
SwiftUI package to present a Bottom Sheet interactable view with the desired Detents. Also known as Half sheet.

BottomSheetSUI BottomSheetSUI is a package that gives you the ability to show a Bottom sheet intractable, where you can add your own SwiftUI view. You

Mar 28, 2022
NStack is a SwiftUI view that allows you to hoist navigation state into a Coordinator

An NStack allows you to manage SwiftUI navigation state with a single stack property. This makes it easy to hoist that state into a high-level view, such as a coordinator. The coordinator pattern allows you to write isolated views that have zero knowledge of their context within the navigation flow of an app.

May 17, 2022
The source of V2er.iOS
The source of V2er.iOS

V2er-iOS A beautiful V2EX client built for iOS platform. This project is under develop, is not avaiable in App store yet, you could download it from h

Apr 26, 2022
Compose is a library that helps you compose complex and dynamic views.

Compose is a data driven library that will help compose your complex and dynamic Views. It helps you create complex and dynamic Views using easy and s

Jun 9, 2021
This library allows you to make any UIView tap-able like a UIButton.

UIView-TapListnerCallback Example To run the example project, clone the repo, and run pod install from the Example directory first. Installation UIVie

May 13, 2022
iOS App that helps you breath properly.
iOS App that helps you breath properly.

Breathing App iOS App that helps you breath properly. I created this iOS app in my Intro to iOS Develepmont class at Hunter College. I am not a profes

Dec 24, 2021
iOS constraint maker you always wanted. Write constraints like sentences in English. Simple

YeahLayout iOS constraint maker you always wanted. Write constraints like sentences in English. Simple. Intuitive. No frightening abstractions. One fi

Jan 10, 2022
An iOS application enables you explore art works provided by DeviartArt.com with high quality UX.
An iOS application enables you explore art works provided by DeviartArt.com with high quality UX.

Iris.iOS Iris is a model mobile application based on iOS. It provides basic functions allow users to explore on DeviantArt and check Daily Arts, Notif

Feb 10, 2022
Using the UIKitChain framework, You can create a UIKit component in one line of code.
Using the UIKitChain framework, You can create a UIKit component in one line of code.

Using the UIKitChain framework, You can create a UIKit component in one line of code. Installation CocoaPods CocoaPods is a dependency manager for Coc

Jan 16, 2022
Flixtor-iOS - iOS streaming app inspired by Netflix that allows you to watch any film and series
Flixtor-iOS - iOS streaming app inspired by Netflix that allows you to watch any film and series

Flixtor-iOS iOS streaming app inspired by Netflix that allows you to watch any f

Jan 14, 2022
Build 1 scene, let AutoLayoutMagic generate the constraints for you!

Auto Layout Magic Create 1 scene, let Auto Layout Magic generate the constraints for you Hello friends, We've all been there. You have an app supporti

Sep 21, 2019
The most powerful Grid container missed in SwiftUI
The most powerful Grid container missed in SwiftUI

Grid Grid view inspired by CSS Grid and written with SwiftUI We are a development agency building phenomenal apps. Overview Grid is a powerful and eas

May 13, 2022
Flow layout / tag cloud / collection view in SwiftUI.
Flow layout / tag cloud / collection view in SwiftUI.

SwiftUIFlowLayout A Flow Layout is a container that orders its views sequentially, breaking into a new "line" according to the available width of the

May 13, 2022
Half modal view for SwiftUI
Half modal view for SwiftUI

ResizableSheet ResizableSheeet is a half modal view library for SwiftUI. You can easily implement a half modal view. Target Swift5.5 iOS14+ Installati

May 12, 2022
✨ Super sweet syntactic sugar for SwiftUI.View initializers.

ViewCondition ✨ Super sweet syntactic sugar for SwiftUI.View initializers. At a Glance struct BorderTextView: View { var color: Color? @ViewBuild

May 6, 2022
Expose layout margins and readable content width to SwiftUI's Views

SwiftUI Layout Guides This micro-library exposes UIKit's layout margins and readable content guides to SwiftUI. Usage Make a view fit the readable con

May 17, 2022
This app presents few examples for common patterns using purer SwiftUI code

VIPERtoSwiftUI GOAL This app presents few examples for common patterns using purer (from authors experience) SwiftUI code. LITERATURE https://www.appy

Dec 19, 2021