Phone number format from country code on iOS - ios

I need to display phone number format as placeholder in UITextField. How can I do that?
For country selection I'm using below mentioned library and it provides me country flag and country code against user selected country.
https://github.com/NikKovIos/NKVPhonePicker
After selecting a country I need to display phone number format for that selected country and on submission of that phone number I have to validate the phone number.
I also find that third party (PhoneNumberKit) which is inspired by google's libphonenumber but it is for validating, it do not provide expected phone number format against country code. Below is the link.
https://github.com/marmelroy/PhoneNumberKit
Update 1:
Tried this and getting Generic parser error
let phoneNumberKit = PhoneNumberKit()
do {
let phoneNumber = try phoneNumberKit.parse("+921230123456")
}
catch {
print("Generic parser error")
}
Update 2:
Updated code, still getting exception
let phoneNumberKit = PhoneNumberKit()
do {
let phoneNumber = try phoneNumberKit.parse("1230123456", withRegion: "FR", ignoreType: false)
let formatedNumber = phoneNumberKit.format(phoneNumber, toType: .international)
print(formatedNumber)
}
catch {
print("Generic parser error")
}

I don't know whether this is a valid solution or not, you could try this
Say let your placeholder be 012345679 what I believe you could do is
Create a variable to store this placeholder
Parse this placeholder against the country that the user selects.
Set the parsed one as the placeholder in the textfield.

For those who wanna do the same thing, I used two different 3rd parties to achieve the functionality.
NKVPhoneNumber
SHSPhoneComponent
NKVPhoneNumber is used to select country code, i've modified it a bit a introduced phone_format in the Meta Data. Once selected a country from the list it return a Country object which includes Code, Extension, Flag and format_placeholder
SHSPhoneComponent then use that format_placeholder for validation of the format.
import SHSPhoneComponent
import NKVPhonePicker
#IBOutlet weak var phoneTF: SHSPhoneTextField!
#IBOutlet weak var phoneFlag: NKVPhonePickerTextField!
#IBOutlet weak var lblCountryCode: UILabel!
//MARK: - NKV callback delegates
func countriesViewController(_ sender: CountriesViewController, didSelectCountry country: Country) {
//
phoneTF.formatter.setDefaultOutputPattern(country.formatPattern)
phoneTF.text = ""
phoneTF.placeholder = country.formatPatternPlaceHolder
countryCode = "+\(country.phoneExtension)"
lblCountryCode.text = countryCode
}
Note: I've converted NVKPhoneNumber to Swift 4.0,

Related

How to include collections in a users document in Firebase / Swift

I am new to coding and swift and I'm trying out lots of different things and working with firebase. In my app I'm getting step data using HealthKit and using that to practise with data in swift.
 
I have made the app get the users steps and convert them into points. 1,000 steps = 2 points. In the App there is a selection of "boxes" to choose from. The aim is to fill these "boxes" up with points. However you can only work towards filling up two "boxes" at a time (haven't made code that limits user to supporting 2 boxes at a time yet).
 
I have written code so that when you tap a "box" takes you to a detailed view of the "box" with a button labelled "WorkTowards". When this button is tapped, it gets added to "workingTowardsBoxes" which is displayed in the user's profile to indicate which boxes are being worked on.
 
I want to make the "boxes" a user is working towards be stored with their other data like username, bio etc. in their document on firebase but am unsure how to do this.
 
I'm new to firebase too but I imagine there is a way to give a field two separate values and the values being a document in a different collection.
 
The "Boxes" are stored in a collection in firebase so each "Box" has it's own uid. I need a field in the users document that contains two "Boxes" titled "activelyWorkingTowardsBoxes". The values in this field should change when the user changes the "Box" they are working on.
 
At this stage I want to have the "boxes" a user wants to 'workTowards' to be stored in the user's firebase document. Then I will work on adding the points to the boxes.
The code for the UserModel:
struct UserModel {
var username : String
var pic : String
var bio: String
var uid : String
// something like this needs to be included?:
// var activelyWorkingOnBoxes: WorkingOnBoxes
}
The code for the Boxes model is:
struct Box: Identifiable {
var id: String
var box_name: String
var box_type: String
var box_profileImage: String
// To identify whether it is being supported...
var isWorkingOn: Bool = false
}
The Code For The WorkingOnBoxes is:
struct WorkingOnBoxes: Identifiable {
var id = UUID().uuidString
var box: Box
}
Here are my 'Working on' functions:
func isWorkingOn() -> Bool {
return sharedData.workingOnBoxes.contains { boxData in
return self.boxData.id == boxData.id
}
}
func addToWorkingOn() {
if let index = sharedData.workingOnBoxes.firstIndex(where: {
boxData in
return self.boxData.id == boxData.id
}){
// Remove from working on...
sharedData.workingOnBoxes.remove(at: index)
}
else {
// Add to working on...
sharedData.workingOnBoxes.append(boxData)
}
}
Any Help Would Be Much Appreciated!

Code for extracting CNContactLabels from the IOS contact store

I am trying to extract a list of available labels for phone numbers in the IOS contact store so that when the user adds a new number to a contact he/she can select a label from a table list for that number.
I have no problem with retrieving and writing contact numbers but the listing of available labels is eluding me.
What I am really trying to achieve is to extract the array of labels for phone numbers as in :
var phoneNumbers : [CNLabeledValue<CNPhoneNumber>] = []
but I can't find out where to extract values for phoneNumbers.
Please check this code for CNLabeledValue, its working for me.
for phoneNumber in contact.phoneNumbers {
if let number = phoneNumber.value as? CNPhoneNumber,
let label = phoneNumber.label {
let localizedLabel = CNLabeledValue.localizedStringForLabel(label)
print("\(localizedLabel) \(number.stringValue)")
}
}
In the end I extracted a list of label constants from the documentation and did:
let arrLab = [CNLabelPhoneNumberHomeFax, CNLabelPhoneNumberMain,CNLabelPhoneNumberMobile,CNLabelPhoneNumberOtherFax, CNLabelPhoneNumberPager, CNLabelPhoneNumberWorkFax,CNLabelPhoneNumberiPhone,CNLabelOther ]
for bod in arrLab {
let label = CNLabeledValue<NSString>.localizedString(forLabel: bod)
arr1.append(label)
}
Not ideal because if Apple decides to add a new constant the app would require maintenance. It would be better to be able to extract the constants directly from the device.
Also, if there are custom labels my code would miss those.

Retrive specific data from firebase in Swift

Hi i have this structure of firebase database:
I need to retrive the specific data: Shane/DatiUtente/Password from the database and add it into a string var
please someone can tell me how is possible.
Sorry for my english if is bad i'm italian :)
You are going to need to parse through your database and retrieve the value you want. It would be something like this:
//At the top of your class set an empty variable like this:
var pass = String()
//Say for example you want to display that password to a label on your storyboard
#IBOutlet weak var passLbl: UILabel!
//Inside your viewDidLoad function you would want to add this:
DBRef.child("Shane").child("DatiUtente").child("Password").observeSingleEvent(of: .value, with: { (snaps) in
if let dictionary = snaps.value as? [String: AnyObject] {
self.passLbl.text = dictionary["pass"] as? String }
// IF you want it to the string as you asked
replace the self.passLbl.text with the empty pass variable you created at the top.

iOS: Core Data fails to save when attribute is a double

I thought I'd ask here first before I sent my laptop flying out of the window. I am very new to iOS development and have been toying around with Core Data trying to create an expense manager app. I have a single entity named "Account" which has two non-optional attributes (name and initBalance) as follows:
I have also created an NSManagedObject subclass as follows:
//Account.swift
class Account: NSManagedObject {
override func awakeFromInsert() {
super.awakeFromInsert()
initBalance = NSNumber(double: 0.0)
name = ""
}
}
//Account+CoreDataProperties.swift
extension Account {
#NSManaged var initBalance: NSNumber
#NSManaged var name: String
}
The Account entities are presented in the AccountsViewController (a subclass of UITableViewController conforming to the NSFetchedResultsControllerDelegate protocol) using an NSFetchedResultsController. To add a new Account I use a segue from AccountsViewController to direct me to the AccountInfoViewController (shown below) which has two textFields, one for the name and one for the balance of the account. When the latter is about to disappear a new Account is inserted in the context with the name and balance derived from the textFields. Once the parent controller appears (AccountsViewController) it tries to save the changes and updates the tableView.
Now, if I insert a new Account for which the balance is an integer number life is good; the context is able to save the changes, tableView updates its rows by showing the newly inserted account, and I am happy. When I try to insert an Account for which the balance is a decimal number, the app crashes at the point where the context tries to save the changes. I get no useful error at all as to why it happens. Here is the code for the controller managing the textFields:
class AccountInfoViewController: UIViewController {
#IBOutlet weak var nameField: UITextField!
#IBOutlet weak var balanceField: UITextField!
var store: DataStore! // set by the parent viewController everytime this controller appears
let numberFormatter = MyFormatter()
// insert the new account into the context before the controller disappears
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
store.insertAccount(nameField.text!, balance: numberFormatter.numberFromString(balanceField.text!)!)
}
}
The MyFormatter is this:
func MyFormatter() -> NSNumberFormatter {
let formatter = NSNumberFormatter()
formatter.numberStyle = .DecimalStyle
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 2
return formatter
}
and the DataStore shown above contains a simple Core Data Stack and is responsible for inserting into the context:
// DataStore.swift
class DataStore {
let coreDataStack = CoreDataStack(modelName: "SmartMoney")
// inserts a new account into the context
func insertAccount(name: String, balance: NSNumber) -> Account {
let account = NSEntityDescription.insertNewObjectForEntityForName("Account",
inManagedObjectContext: coreDataStack.mainQueueContext) as! Account
account.name = name
account.initBalance = balance
return account
}
}
Is there any reason why the context fails to save the changes when the balanceField contains a non-integer number? Thank you for reading and please let me know if you would like me to post any other parts of the code.
I was finally able to figure out what's going on. Changing my attribute name from initBalance to startingBalance makes everything work again. In fact, changing the attribute's name to anything that does not start with new or init works just fine. I got the idea from this post.
It seems that when using ARC, your property's name should not start with the word new. It turns out that initBalance (or newBalance for that matter) produces the same issue. Hope it helps the next poor soul running in a similar problem.

Using UIButton Text as Text Input - Swift

Hello I have a profilelbl variable as below which is a uibutton. I want the text of the button to be an input in my database (parse). But I couldn't figured it out. I tried lots of things but still getting error:
#IBOutlet weak var profileLbl: UIButton!
var notification = PFObject(className: "notifications")
notification["actionReceiverName"] = profilelbl.text /*not working*/
/* also tried
notification["actionReceiverName"] = sender.profilelbl.text
notification["actionReceiverName"] = profilelbl.title */
you can do it easy like that
if let button = profilelbl as? UIButton {
if let title = button.titleForState(.Normal) {
println(title)
notification["actionReceiverName"] = title
}
}
Using UI objects to save/load data is a very bad idea. Using user-visible strings programmatically is an even worse idea. #ÖzgürErsil answered the question you asked, but the better answer to your question is "Don't do that. Ever."
Here are 2 examples where your approach will fail:
If 6 months later you want to change your UI and rename your button,
you won't remember that the button title is used in code and your
code will break. To that you would have to alter your database to
use a different string value.
If you decide to localize your app for foreign
languages, the button titles will come up in the local language, and
your code will break. There is no clean way to fix this problem,
since each local language would use a different version of the
button title.
It would be better to put unique tag numbers on your buttons, then look up text strings using the tags and pass those strings to your database.
Say you have button tags starting at 100.
You'd use code like this:
let buttonStrings = ["button1", "button2", "button3"]
let baseButtonTag = 100;
#IBAction func handleButton(sender: UIButton)
{
let tag = sender.tag
if tag >= baseButtonTag && tag < baseButtonTag + buttonStrings.count
{
let index = sender.tag - baseButtonTag
let buttonString = buttonStrings[index];
//Now use buttonString with your database as desired.
}
}

Resources