Update existing 'Contacts' Phone number? - ios

I have code to fetch and display User data from Contacts (various Name properties plus the array of Phone numbers). By making a CNMutableContact, I can update any of the Name properties. But I can only display Phone numbers (from CNLabeledValue via ".digits"). Is it possible to also update Phone numbers? I can't change "digits" in the CNMutableContact because it is 'read-only'. I have seen and understand cautions on accessing CNLabeledValue "digits", but would still like to proceed.
Suggestions?

Maybe is a little late to answer this question. However, on the given exemple, you can only add phone numbers. So, to update phone you would, at best, replace removing phone numbers and add new ones.
Replacing a phonenumber entry in this approach would result in changing the phonenumber's identifier.
This should be not the behaviour you are expecting, since you are changing a phone number of an existing entry. And we want to keep the phone identifier intact.
You should use settingValue from CNLabeledValue see: Apple Documentation
// Clone to a mutable contact
let mutableContact = contact.mutableCopy() as! CNMutableContact
// Here's the catch
let updatedPhone = mutableContact.phoneNumbers[0].settingValue(CNPhoneNumber(stringValue: "newPhone"))
// Be aware that in this example, I only have on phone number. For multiple phones, would need to handle multiple phones properly in the array.
mutableContact.phoneNumbers = [updatedPhone]

Related

Uniquely identify MSConversation in iMessage

What would be the best way to uniquely identify an MSConversation when developing an iMessages application?
In my case I want to give to a game object an ID of the conversation where it belongs to.
Take the localParticipant ID, add to it the remoteParticipants ID ;)
Something like that :
var conversationID = yourConversation.localParticipantIdentifier
for participant in yourConversation.remoteParticipantIdentifiers {
conversationID += participant
}
EDIT:
As noticed in comments, by doing so, you could end up with a very long ID. So the idea is to apply an hash to it, to have a constant size (MD5 is suffisant, we don't need something secure here). If it is still too long, you could crop that hash, but be aware that in that case there is a small probability for two conversations to have the same ID (depending on how much your crop).
The current top answer has a corruption issue in that if a new person is added to a group chat (or if someone is removed) your hashed ID will change.
A more elegant solution in my opinion is to just create your own serial number at the time of the first message being created and add it as meta-data to your message itself. (Using NSURLComponents of course). Then just grab that anytime a message is opened (thus launching your message app) and use that ID. Just keep it in the header of any message sent/received.
But, it depends on what you are trying to do really. The solution I've provided is great for turn-based multi-player games. It might not be good for other scenarios.

Firebase fetch multiple results

I was wondering if there is any way with swift and firebase, to get multiple numbers from the same child? and average all the numbers.
Example,
Every authorized user saves a number to the database. Then when they look at there number in a saved section it averages all other users numbers and compares it against theres.
I can get all the data to save, and I can get the data to send back info, but it only sends one number from the list
I have tried different ways but I can't get it to work. Any help would be awesome.
I would post some code but none of it is working real well
Thanks again in advance
For your example, you would use childByAutoID to create a random unique identifier for your user. To get multiple values from one child you would use a comma, when setting the childs value. Like this,
struct getInput {
var inputType: String!
}
//copying and pasting this code into your code will not work, however
//you should be able to understand why and how this works.
let getUsername = getInput(inputType: usernameTextField.text!)
let getPassword = getInput(inputType: passwordTextField.text!)
let userReference = database.reference().child("users")
userReference.setValue(getUsername.inputType)
let childByAutoID = userReference.childByAutoId()
childByAutoID.setValue(["username": getUsername.inputType, "password": getPassword.inputType])

Obtaining CNContact from CNContactRelation

I am trying to obtain all related contacts to a selected contact. The way to do this seems to be via mycontact.contactRelations. This gives an array of CNLabeledValue with each of those containing a CNContactRelation as their value. There is then a name property, but it appears nothing else.
The Xamarin documentation for CNContact.ContractRelations seems to suggest I should be able to obtain the corresponding CNContact from a CNContactRelation but I can see no way to do this in objc, other than searching for a contact with a matching name. This may or may not be the contact I'm after, even if they also have a relationship to a contact with the same name as mycontact.
The identifier on the CNLabeledValue seems to refer to the label rather than the related contact, or at least doesn't seem to match the identifier if I select that contact from a CNContactPickerViewController.
Is there a way to obtain the CNContact for the related contact in objc ?
The related names field in Contacts doesn't store linkages, just names. You'll notice this from a user perspective if you go to edit related names in the iOS or OS X Contacts app — it's just a freeform text field. Those apps (and other system apps) will recognize when a related name matches that of another contact (which is why you can ask Siri to call your mother, etc), but they also let you put down names for people you don't have contact info for.
So a CNContactRelation just contains a string, and the only way to find (if there are any) contacts matching a related name is to search the contact store. Use unifiedContactsMatchingPredicate:keysToFetch:error: to search, with a predicate constructed by calling predicateForContactsMatchingName:.

phone number predicate on CNContactStore

I am building an app in Swift. I would like to make predicate using a phoneNumber (as String) and retrieve the name of that contact -if it exists- from the CNContactStore. I can make a name predicate fairly easily by :
let pred = CNContact.predicateForContactsMatchingName(name: String)
But is there a way to do the same for a PhoneNumber. I can of course fetch the entire CNContactStore, loop through it and retrieve the contact. But I was wondering if there was any better way.
For anyone who sees this post.
In iOS11, Apple introduced this new method to fetch contact with phone number.
https://developer.apple.com/documentation/contacts/cncontact/3020511-predicateforcontacts
See:
https://nshipster.com/ios-12/
In short: you can't create a predicate to filter based on phone number. You have to pull all of the contacts and iterate. NOTE: For any given phone number, it 1) may not exist in contacts, or 2) exist more than once.
Check out this post:
https://forums.developer.apple.com/thread/19329

Retrieving a country telephone code for a specific country in iOS

I'm quite new to iOS development and I'm currently building my first app.
I'm trying to get a text field to automatically populate the telephone country code for a specific country.
So if for example the user picks "UK" he gets "+44" inserted automatically into that text field.
Currently I'm struggling a way to find how to get the exact country telephone code for the country.
I could create an NSDictionary with all of the countries and country telephone code but I thought there might be a better way.
If your goal is to get the dialling code of the user's current location then you should use HMDiallingCode.
It uses CoreLocation and reverse geocoding to get current country of the user and then retrieve it's dialling code.
I think, you can only get country code for the current Carrier using CoreTelephony framework:
CTTelephonyNetworkInfo *info = [CTTelephonyNetworkInfo new];
CTCarrier *carrier = info.subscriberCellularProvider;
NSLog(#"country code is: %#", carrier.mobileCountryCode);
If you need a full list of codes for all countries, you need to use some online service for querying it.
I'm afraid there is not a better way. My app include a .plist file with the array of countries with name, code, phone code, trunk code, etc for each. You will not get all that info from iOS API.
If you only need the international phone code for a country code, here you are a link with a complete table.

Resources