Primary / Default ABMultiValue property? - iphone

I need a user to enter their name, phone number, and email address. To help them out, if they enter any one of the three, I want to look up that value in their Address book and populate the remaining fields. For example, if they enter their name, I'll look them up, and populate the email and phone number fields.
Email and phone numbers are ABMultivalue properties, however, and most people have more than one email and phone. Does the iPhone address book have the concept of a primary or default value for those properties that are ABMultiValue?
Thanks!

There is no primary/default value. I would simply assume that the first value is the primary/default value. It's true for most of my contacts. Otherwise if there are multiple values you could let the user choose the one they want, but you need to make a good UI to support it, so the first alternative is much simpler.

Related

Is there a way to make a field so that there can only be one yes per FK?

I am on Filemaker 18 Pro and new to Filemaker in general. I created a table of Clients and a table of Properties. One client can have multiple properties (ie One to Many relationship). I want to have a flag to indicate that the property is the Client's Primary Address. So basically the field will be:
isPrimary = "Yes" or isPrimary = "No".
There can only be one "Yes" per Client ID
There HAS to be one "Yes" value per Client ID
If you add "Yes" then it will change the existing "Yes" to "No"
Is there a best practice for doing this?
Is there a best practice for doing this?
Yes, there is. If only one property can be the client's primary address, then the identity of the primary address is an attribute of the client, and should be recorded in a field of the Client's table - e.g. a Number field storing the selected property's PropertyID.
To "flag" the primary address, use an unstored calculation, or a conditionally formatted object, using the formula:
Clients::PrimaryAddressID = PropertyID
In this arrangement, selecting a new primary address will automatically remove the flag from the previous address and place it on the newly selected one.
P.S.
It is much more convenient to use the values 0 and 1 (or empty and 1) for Boolean fields. The field itself can be formatted to display as "Yes" or "No".
You can loop the Properties portal/records and set "No" for other records.

MS Access Form and Tables

I have a specific question regarding the utilization of three tables in a database. Table 1 is called Personnel, and lists the names of the staff.
Tables 2 and 3 are identical, just listing two different types of overtime (long and short), along with the hours of the OT, Date of the OT, and Assigned to/Picked fields that are empty.
Here is the idea, I just dont know how to implement it. I would like to create a form for people to enter their OT picks, then automatically move to the next person on the list. So Rich Riphon, as an example, would be up first, would click on the link I would send, and a form would open up, showing his name, populated by the first table, and showing two drop down menus, populated from the Long OT and Short OT tables. He would select one from each (or None, which would be a option) and Submit it.
The form action would be to place his name in the Assigned field for the OT he picked, and place a Yes in the Picked field.
When the next person in the list opens the form, it has moved down to number 2 on the Personnel list, Cheryl Peterson, and shows her the remaining OT selections (excluding those that have a Yes in the Picked column).
Any suggestions or comments or better ways to do this would be appreciated.
First, I don't think ms access would be able to (easily) kick off the process based on a hyperlink. You may be able to do something by passing a macro name to a cmd prompt but it would take some mastery to get it working properly. Could you instead create a login form to get the current user? If you do that you don't really need to display the personnel list, just keep track of who has not yet responded to the OT request. Essentially at that point all you would need on your form is a listing of the available OT and a button that creates the assignment. Also it may be easier (and a better design) to only have one table for the OT listings and add a column for the type of overtime (long/short).
What if Cheryl isn't the 2nd person to get the form? Your concept goes out the window.
Instead, I would keep a table of all user names, and their security level. managers can see everything, individual users can only see their record. This would be done by using a query behind the OT Picks form, and either filtering by the current user or not filtering at all. I have done many of these types of "user control" databases and they all have worked well.
As for the actual OT tracking, I agree with Steve's post in that it should be done in one table This would be the preferred method of a concept referred to as "normalizing data". You really want to store as little data as possible to keep the size of your database down. As an example, your Login table would have the following fields:
UserID
FirstName
LastName
SecurityLevel
Address1
Address2
City
State
Phone
Etc... (whatever relevant info pertains to that person)
Your OT table would look like this:
UserID
OTDate
OTHours
OTType
Etc... (whatever else is relevant to OT)
You would then join those 2 tables on the UserID fields in both tables any time you needed to write a query to report OT hours or whatever.

Keeping a long-term reference to an IOS AddressBook entry

Given that an ABRecordID can change between cloud syncs and under other circumstances out of my control, how can I maintain a long-term reference to an IOS address book record?
Apple provides the following guidance:
"The recommended way to keep a long-term reference to a particular record is to store the first and last name, or a hash of the first and last name, in addition to the identifier. When you look up a record by ID, compare the record’s name to your stored name. If they don’t match, use the stored name to find the record, and store the new ID for the record."
But I don't understand this guidance. If the address book can have duplicate names in it AND since users can modify the name in a record how could this advice work?
For example, if the user modifies the name of an address book record my routine will fail to find it by ABRecordID so if I think search by the name hash I stored couldn't I find a duplicate name instead of the new ABRecordID for that specific record I previously referenced?
In the end, what is the BEST way to get a long-term reference to an IOS AddressBook record? And if the above advice really does work what am I missing?
The most robust (yet not completely failsafe) approach would be to come up with a priority ranking of ABRecord fields and store as much from that list as is available, along with the ABRecordID, into your own (hashed) private record format. When retrieving a private record (or at another convenient time), you can verify that the private record matches the ABRecord and work through a series of fallback checks to ensure it's accurate.
Example priority ranking:
ABRecordID
FirstName
LastName
PhoneNumber
ZipCode
When retrieving a record you can first match the ABRecordID. If that returns no results, you can do a search for FirstName + LastName. You can then match those results against PhoneNumber... etc. In this way you could potentially distinguish between 2 Bob Smiths, as they may have different phone numbers (or one may not have a phone number). Of course, depending on how long your priority list is, the more robust this mechanism will be.
The last resort would be prompting the user to distinguish between 2 Bob Smiths with brand new ABRecordID's whose records are otherwise identical -- after all, such an inconvenient prompt would be far more friendly than allowing the User to contact the wrong Bob Smith (and as I said, would be a last resort).
This solution for AB may involve some synchronization issues, however.
This is a familiar problem for anyone who has worked with the iOS Media Player. Specifically MPMediaItems in the User's Music Library have a property MPMediaItemPropertyPersistentID which the docs describe as:
The value is not guaranteed to persist across a sync/unsync/sync cycle.
In other words, the PersistentID is not guaranteed to be persistent. Solutions for this include doing similar fallback checks on MediaItem properties.
The RecordID only get changed either on delete or reset, when this is done all the new record(s) will have new createdProperty and modifiedProperty as well.
While I am reading the address book for the first time, I will save all entries of the record along with RecordID in my database.
I will save the last time the contacts synced from contacts to my database(name it something: lastSyncedTime) and store it some where.
I am done with syncing the contacts for the first time, now do the following for syncing anytime in future.
while Iterating through all records,
check createdTime(kABPersonCreationDateProperty) vs lastSyncedTime. If createdTime > lastSyncedTime, store the recordID in a "newRecords" NSArray.
If !(step 1) then check modifiedDate(kABPersonModificationDateProperty) vs lastSyncedTime. If modifiedDate > lastSyncedTime, then store the recordID in a "modifiedRecords" NSArray.
if !(1) && !(2) store all recordID in a "unModifiedRecords".
Now I will read all the contacts from my local database,
I will delete all local database records that are not find either in "modifiedRecords" or in "unModifiedRecords".
I will update all "modifiedRecords" in the local database.
I will create new records for all records in "newRecords".
Update the lastSyncedTime accordingly.
The documentation is communicating to you that you can't count on ABRecordID as a permanent identifier.
Consider this scenario: The user has a record for "Bob Smith". The user then deletes his "Bob Smith" record and then imports his contacts from his computer (creating a new ID) through iTunes sync.
So if you want to keep a permanent reference to an existing contact, you can keep a reference to the name and id as a hint that it is the same record you used before- but there is no real permanent reference.
If you keep a permanent reference to an address book contact, you must always be ready to deal with the fact that it may not be the same contact you used before.
Refer :
https://developer.apple.com/library/ios/documentation/ContactData/Conceptual/AddressBookProgrammingGuideforiPhone/Chapters/DirectInteraction.html#//apple_ref/doc/uid/TP40007744-CH6-SW2
Clearly tells you how to handle it.

What are the mandatory and optional address fields in geocode?

What are the mandatory and optional address fields in geocode?
As the address format is different for different countries throughout the world, what is the format that needs to be used in geocode .Is there a specific format for it, like mandatory fields and optional fields in address.
Please let me know.Thanks
No specific format. Just give it some data and it will try its best to discern it. I have an app that the user inputs zip/postal code and it will retreive all the relevant info (city, state/province, country).

What is the correct way to associate with a ABPerson?

In many of my apps, it requires associating some data with a contact in addressbook. What I used to do is save the record id of an ABPerson and use that id to pull information upon each app launch. However, more and more I find that this approach is wrong because many times a user will use a service like mobileme where the addressbook is wiped and resynced. This causes the record id to change and all associations are lost. The user will have to go through each one and re-link them.
What is a better approach to holding a robust pointer to addressbook entries?
You should store three values: the record ID, the first name, and the last name.
1) In the case that the record ID hasn't changed, you're golden - just use that to locate the proper record.
2) If ABAddressBookGetPersonWithRecordID() does not locate a record for your stored record ID (it returns NULL), then you'll need to search the person records for a match based on the first and last name. You can drop down to using ABAddressBookCopyPeopleWithName() potentially or write your own locating code if you already have an array with all the person records in-memory. Locating the new record is up to you. Once to locate the new record, you can update your data storage with the new record ID.
Ultimately, you end up storing the record ID to use directly incase it doesn't change (if you're lucky) plus storing some keys from the address book entry that are unlikely to change. The name of the person or organization associated with an address book entry is most likely to change. You should, of course, account for the case where you may not find a record with the stored record ID or by searching for the name. This could trivially mean that the record was deleted, or it could mean that the record was renamed. You should handle that case whichever way you decide is best for your specific application.
I know this was last year, however, I thought I might suggest a method I use. The first time I ask the user to pick a contact (in order to associate certain of my app's private data with it) I then grab the record, create my own internal record id (the initials of the app name and a sequence number usually) modify the contact by adding a new ABRelatedName (type of "pref" name of "Other") value of my own internal record id. It looks like this in the .vcf
item3.X-ABRELATEDNAMES;type=pref:BZA101
item3.X-ABLabel:_$!<Other>!$_
That way, I can simply reference that record id when i add more data about the user such as the last time the app user contacted them, etc. Seems to work for me.
Hope that helps someone.
If the address book is indeed being completely wiped and re-loaded, and the only part that doesn't change is the display name, then storing the display name as the link seems like the only option.