SwiftUI custom number formatter as phone - ios

I'm trying to create a custom phone formatter. I found PhoneNumberKit that could work for my particular case, the problem with this is that when I tried it there are multiple issues like:
If using .international the program enters in a loop and becomes irresponsive
It requires the number to contain the country's phone-code inside the text to be able to format it correctly, but as I have already done this part in a Button with a flag + phone code on the left, it's not necessary.
So, what I'm trying to do is to create my own PhoneFormatter, something like: (###) ###-####, currently this might suffice as we're only targeting a single country and this is the most common format used here.
I'm following the code from this site to get an idea of how to do it, but here they are working with dates:
struct ContentView: View {
static let taskDateFormat: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .long
return formatter
}()
var dueDate = Date()
var body: some View {
Text("Task due date: \(dueDate, formatter: Self.taskDateFormat)")
}
}
Someone asked something similar 2 years ago on Apple's Developer Forums but I believe it was for UIKit rather than SwiftUI and there's no code shown there.
I'm trying to attach my formatter directly to my own TextField, I've tried looking for something similar with SwiftUI and I haven't found anything, and still can't find myself how to create my own custom formatter using something like formatter.numberStyle = "(###) ###-####"
Could anyone point me in the right direction?

Related

how to get current displaying page month in string in Fscalender in swift

I know how to get the month of current page but I want to know how to get the month of current page in string in fscalender please help me I'm new to iOS.
let values = Calendar.current.dateComponents([Calendar.Component.month, Calendar.Component.year], from: self.fscalenderobj.currentPage)
var CURRENT_MONTH = values.month
it's in integer form like in today month -> 5 ,I want it in name like May.
It's pretty simple.
let monthSymbols = Calendar.current.shortMonthSymbols (or monthSymbols dependeing upon what you need)
You can refer this
https://developer.apple.com/documentation/foundation/calendar/2293753-shortmonthsymbols

How to get te text of a textfield from inside a function?

I want to make an app that has 2 textfields, 4 buttons and a Text view. 1 button that clears the content of the first textfield and another button that inputs the current time rounded to the nearest 4 and the Text view to display the total time in minutes. Same with the other textfield. It's an app to calculate the total time spent on something in minutes.
I also want to limit the amount of possible insertable characters to 5 as a time has a maximum of 5 characters as in "15:00". I have been able to make an observable object:
class TextFieldManager: ObservableObject {
let characterLimit = 5
#Published var userInput = "" {
didSet {
// Limit the max length of the field
if userInput.count > characterLimit {
userInput = String(userInput.prefix(characterLimit))
} else if userInput.count >= 4 {
// call the setTotalTime func or something to set totalTime
}
}
}
}
which works really well.
I am also able to clear the textfield and set the current time rounded to the nearest 5, but i am unable to limit the characters to 5 AND have the buttons do something at the same time.
So right now it's either being able to:
- Limit characters to a maximum of 5
OR being able to:
clear textfield with a button
input time now rounded to nearest 5 into textfield with a button.
If i go with the observable object method, when i have this above the body block of my ContentView:
#ObservedObject var startTimeManager = TextFieldManager()
#ObservedObject var endTimeManager = TextFieldManager()
and this inside the body for the textfields:
TextField("hh:mm", text: $startTimeManager.userInput)
TextField("hh:mm", text: $endTimeManager.userInput)
and the TextFieldManager class as shown above, than now i don't know how to get the value of the Textfield anymore.
If inside the input the current time button i try to set the time by doing
$startTimeManager.userInput = "whatever the current time is"
i get an error saying that i can't change the value of a binding<String> type something something. Likewise i also can't clear the textfield in the same way.
Also i would like to call a function inside this part:
} else if userInput.count >= characterLimit {
// call the setTotalTime func or something to set totalTime
}
I have a Functions.swift file where both the TextFieldManager class is and my function that i want to call, but if i try to call a function inside here, it says that the function doesn't exist? And inside the function i again would like to have access to the textfield values at the time of the call, but i don't know how to read the value of the textfields from inside the function.
I hope i am making sense and that someone is able to help me, or point me in the right direction. I made the same app for android (android studio), windows (python3) and Mac (python3), but this iphone and Xcode thing really doesn't want to work. I have watched a bunch of tutorial videos and guides, but none are trying to do what i am trying to do. Like i said i can get either to work, but never together and in both cases i am unable to somehow access the textfield values inside the function. I feel like i should be so close, but something is not coming together for me in my head.
Also while i'm at it, in Python 3 to catch all errors and let them pass silently i can do:
Try:
break_my_stuff = int("Break my stuff)"
ignore_some_more_stuff = int("ignore some more stuff)"
etc.
etc.
except Exception:
# catch silently and do nothing
pass
Is there something similar in swift, because
do {
breakMyStuff = whatever might make something break in swift
ignoreSomeMoreStuff = whatever might make something break in swift
etc.
etc.
} catch {
// do nothing and pass silently
}
doesn't work because it needs something to try and i wasn't able to try a complete section like i can with Python.
If inside the input the current time button i try to set the time by doing
$startTimeManager.userInput = "whatever the current time is"
you don't need binding in this case, just assign property in regular way
self.startTimeManager.userInput = "whatever the current time is"

Extraneous argument label 'localeID' in call (SwiftDate)

I am developing an iOs application with Swift and a total novice in application development. I use SwiftDate external library to deal with dates. SwiftDate is installed with CocoaPods and it is imported correctly in the project.
But I can't figure out why I get this error when I compile my project :
Extraneous argument label 'localeID' in call
For this code :
let now = NSDate()
let nowHere = now.toString() // E.g. 21-Dec-15 12:00 CET
let nowInFrench = now.inRegion(localeID: "fr_FR").toString()
I understand that's because the parameters are not formatted correctly, but this an exemple from the documentation so I am a little bit lost for this problem.
Thank's.
As Oliver mentioned, the first problem is the argument label in
let nowInFrench = now.inRegion(localeID: "fr_FR").toString()
to fix your
Extraneous argument label 'localeID' in call
error write it like this
let nowInFrench = now.inRegion("fr_FR").toString()
then you will come to the
Cannot convert value of type string to expect argument type Region
Error. This means you cannot simply give the function inRegion a String object. It wants a Region objects. The documentation says use create a region
let paris = DateRegion(timeZoneID: "CEST", localeID: "fr_FR")
let nowInFrench = now.inRegion(paris).toString()
The error is being flagged up because for the first argument in a function the label doesn't need to be written, only the ones after that.
If you just write:
let nowInFrench = now.inRegion("fr_FR").toString()
The error should go away.
I don't know why the example is written that way, maybe just for clarity.
Edit: having looked at the documentation I do think they have just included the labels to be clear as to what type they are using as an argument.

how do you iterate through elements in UI testing in Swift/iOS?

I understand how I could, for example look at one element in a table, but what's the correct way to simply iterate through all the elements, however many are found, to for example tap on them?
let indexFromTheQuery = tables.staticTexts.elementBoundByIndex(2)
Okay I succeeded in figuring out the simple syntax. I have just started working with Swift and so it took me sleeping on it to think of the answer.
This code works:
var elementLabels = [String]()
for i in 0..<tables.staticTexts.count {
elementLabels.append (tables.staticTexts.elementBoundByIndex(i).label)
}
print (elementLabels)
My guess is the answer is there is no way to do so.
The reason is because of my experience with one of the critical iOS components while making a number of UI tests: UIDatePicker.
If you record a test where you get the page up and then you spin the picker, you will notice that the commands are all non-specific and are screen related. In the case of the picker, however, community requests resulted in the addition of a method for doing tests: How to select a picker view item in an iOS UI test in Xcode?.
Maybe you can add a helper method to whatever controller contains this table. Also, keep in mind that you can easily add methods without polluting the class interface by defining them as extensions that are in test scope only.
For Xcode 11.2.1, SwiftUI and swift 5 based app, the following code works for testing a list, each element in this case appears as a button in the test code. The table is set up like this (for each row) :
NavigationLink(destination: TopicDetail(name: "Topic name", longDesc: "A description")) {
TopicRow(thisTopic: top).accessibility(identifier: "newTopicRow_\(top.name!)")
}
Then I catch the members of the table by getting the buttons into an array:
let myTable = app.tables.matching(identifier: "newTopicTable")
var elementLabels = [String]()
for i in 0..<myTable.buttons.count {
elementLabels.append (tablesQuery.buttons.element(boundBy: i).label)
}
print (elementLabels)
Finally, I deleted each member of the table by selecting the detail view where I have a delete button, again with
.accessibility(identifier: "deleteTopic"
I wanted to delete all members of the table:
for topicLabel in elementLabels {
let myButton = app.buttons[topicLabel]
myButton.firstMatch.tap()
app.buttons["deleteTopic"].tap()
}

Make a calculator that calculates multiple times

I am relatively new to swift. I made a simple text-based calculator in swift using NSExpression. I have a problem, however: this text-based calculator calculates the first expression typed into it perfectly every time (expressions from 2+4 to 9*7-1/3*2+1), but the second time, the outputted result is always just the same result as the first one (it won't calculate again). Here is the basics of my code:
I call it from a view controller and make a result label's text equal to the result found in the swift file far below:
x.savetextfinal = calculatortextfield.text! // Variable x.savetextfinal, created elsewhere in a struct, is assigned to the user's input.
// Now the magic happens in calculatormath.swift (see below)
print("this is the result \(z.nsexpress2)")
equalsresultlabel.text = "Result is (z.nsexpress2)."
Then this block of code, found in a separate swift file, seems to me to occur. It uses NSExpression to convert the expression from a string to an NSExpression, then creates a variable and assigns the result "result" of the NSExpression "mathExpression" to it as a string.
import Foundation
var nsexpress:String = String(x.savetextfinal)
var mathExpression = NSExpression(format: nsexpress)
var result:Float = Float((mathExpression.expressionValueWithObject(nil, context: nil) as? NSNumber)!)
struct calculatoranswer {
var nsexpress2:String = String(result)
}
var z = calculatoranswer()
Any ideas why this calculator will not calculate an expression twice will be much appreciated! Thanks.
All I had to do was put all of my calculating code in a function and call it in my view controller. Everything in my calculating swift file was put in a function, which I put inside a struct, and I called the function. Everything worked as planned, and I had my calculator. Structs and functions, not too hard even for beginners like me.

Resources