TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

SOLVED: How to remove extra numbers? 🙄

Forums > SwiftUI

Good afternoon.

I decided to use Mr. @ygeras method formatting a test field.

What I can’t understand is why the check for the number and number of digits in the input field does not work? At least I print it correctly? 🙄

import SwiftUI

struct TestPhoneF {
    @PhoneMumberFormattedTest var phoneNumberTest: String
}

class TextFielsPhoneViewModel: ObservableObject {
    @Published var phoneMask = TestPhoneF(phoneNumberTest: "")
}

struct TextFielsPhoneView: View {
    @StateObject var vm = TextFielsPhoneViewModel()

    var body: some View {
        VStack {
            TextField("", text: $vm.phoneMask.phoneNumberTest)
                .foregroundColor(.black)
                .border(Color.black)
            Text("Example: +7 (555) 555-99-00")
                .foregroundColor(.black)
            Text("Count: \(vm.phoneMask.phoneNumberTest.count)")
                .foregroundColor(.red)
        }
        .padding()
        .background(.white)
        .border(Color.black)
    }
}

#if DEBUG
struct TextFielsPhoneView_Previews: PreviewProvider {
    static var previews: some View {
        TextFielsPhoneView()
    }
}
#endif
import Foundation

@propertyWrapper
struct PhoneMumberFormattedTest {

    enum MaskPhone: String {
        case mobile = "+X (XXX) XXX-XX-XX"
        case landline = "+XX XXXXXXXXXX"
    }

    private var phoneNumberTest: String

    init(wrappedValue: String) {
        phoneNumberTest = wrappedValue
    }

    var wrappedValue: String {
        get { phoneNumberTest }

        set(value) {
            if value.count <= 18 {
                print("Fill number")
                print("value - \(value)")
                let removeNonNuneric = value.removeNonNum()
                print("removeNonNuneric - \(removeNonNuneric)")
                let convert = removeNonNuneric.formatMaskPhone(.mobile)
                print("convert - \(convert)")
                let crop = String(convert.prefix(18))
                print("crop - \(crop)")
                phoneNumberTest = crop
            }
            if phoneNumberTest.count >= 18 {
                phoneNumberTest.removeLast()

            }

        }
    }
}
extension String {

    func removeNonNum() -> String {
        let target = "[^0-9]"
        let result = self.replacingOccurrences( of: target,
                                                 with: "",
                                                 options: .regularExpression)
        return result
    }

    func formatMaskPhone(_ mask: MaskPhone) -> String {
        let currentMask = mask.rawValue
        var result = ""
        var index = self.startIndex
        for ch in currentMask where index < self.endIndex {
            if ch == "X" {
                result.append(self[index])
                index = self.index(after: index)

            } else {
                result.append(ch)
            }
        }
        return result
    }
}

2      

Hi Steven! If you use XCode 15, it is some changes they probably implemented behind the scene or there is a bug. My previous code also stopped working correclty. I found only this way to hanle this situation. Sample code below works as before. No idea what has been changed in XCode 15. When I installed 14 version back it worked just fine...

import Observation

struct BirthDateViewXcode15: View {
    @State var vm = UserModel()

    var body: some View {
        VStack {
            TextField("DD/MM/YYYY", text: $vm.user.birthDate)
                .onChange(of: vm.user.birthDate) {
                    vm.user.formatBirthDateString()
                }
        }
        .padding()
    }

}

@Observable
class UserModel {
    var user = User(birthDate: "")
}

struct User {
    var birthDate: String

    mutating func formatBirthDateString() {
        /// Inserting a slash in the third position to differentiate between day and month
        if birthDate.count == 3 {
            let startIndex = birthDate.startIndex
            let thirdPosition = birthDate.index(startIndex, offsetBy: 2)
            let thirdPositionChar = birthDate[thirdPosition]
            if thirdPositionChar != "/" {
                birthDate.insert("/", at: thirdPosition)
            }
        }

        /// Inserting a slash in the sixth position to differentiate between month and year
        if birthDate.count == 6 {
            let startIndex = birthDate.startIndex
            let sixthPosition = birthDate.index(startIndex, offsetBy: 5)
            let sixthPositionChar = birthDate[sixthPosition]
            if sixthPositionChar != "/" {
                birthDate.insert("/", at: sixthPosition)
            }
        }

        /// Removing / when going back
        if birthDate.last == "/" {
            birthDate.removeLast()
        }

        /// Limiting string, including two slashes (8 + 2 = 10)
        birthDate = String(birthDate.prefix(10))
    }
}

2      

Hello. I have a version "Version 15.0 beta (15A5160n)".

Yesterday, for example, your code worked, but today it doesn’t.

2      

It worked for me!

import SwiftUI

class TextFielsPhoneViewModel: ObservableObject {
    @Published var phoneMask = PhoneMumberFormattedTest(phoneNumberTest: "")
}

struct TextFielsPhoneView: View {
    @StateObject var vm = TextFielsPhoneViewModel()

    @State var textField: String = ""

    var body: some View {
        VStack {
            TextField("", text: $vm.phoneMask.phoneNumberTest)
                .onChange(of: vm.phoneMask.phoneNumberTest) { value in
                    vm.phoneMask.formatBirthDateString()

                }
                .foregroundColor(.black)
                .border(Color.black)
        }
        .padding()
        .background(.white)
        .border(Color.black)
    }
}

#if DEBUG
struct TextFielsPhoneView_Previews: PreviewProvider {
    static var previews: some View {
        TextFielsPhoneView()
    }
}
#endif
struct PhoneMumberFormattedTest {

    var phoneNumberTest: String

    mutating func formatBirthDateString() {
        if phoneNumberTest.count <= 18 {
            print("Fill number")
            print("value - \(phoneNumberTest)")
            let removeNonNuneric = phoneNumberTest.removeNonNum()
            print("removeNonNuneric - \(removeNonNuneric)")
            let convert = removeNonNuneric.formatMaskPhone(.mobile)
            print("convert - \(convert)")
            let crop = String(convert.prefix(18))
            print("crop - \(crop)")
            phoneNumberTest = crop
        }
        if phoneNumberTest.count > 18 {
            phoneNumberTest.removeLast()

        }

    }
}
extension String {

    func removeNonNum() -> String {
        let target = "[^0-9]"
        let result = self.replacingOccurrences( of: target,
                                                 with: "",
                                                 options: .regularExpression)
        return result
    }

    func formatMaskPhone(_ mask: MaskPhone) -> String {
        let currentMask = mask.rawValue
        var result = ""
        var index = self.startIndex
        for ch in currentMask where index < self.endIndex {
            if ch == "X" {
                result.append(self[index])
                index = self.index(after: index)

            } else {
                result.append(ch)
            }
        }
        return result
    }
}

2      

I don't know as soon as I ran my initial proposed code on XCode 15 in stopped working, so I just tried to solve it the other way. Seem like something has changed in APIs, but I have not idea what ))))

2      

Hacking with Swift is sponsored by String Catalog.

SPONSORED Get accurate app localizations in minutes using AI. Choose your languages & receive translations for 40+ markets!

Localize My App

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.