fetch only updated CNContacts from ContactStore swift2 xcode7 - contacts

I would like to getch all CNContact objects from Contacts Store that were updated externally so that I can refresh my list of contacts.
Xcode 7.0
ios9

This is not Possible even with the Old framework.
what i'm doing (using ABAddressBook) is to start a background operation and for all saved contacts i test the modification date of the contact with the one i saved:
NSDate *lastModicationDate = (__bridge NSDate*)ABRecordCopyValue(record, kABPersonModificationDateProperty);
but in the CNContact i can't see the modification date property, so i guess that we have to do this manually (check if there's a modification for every entries)

As I read the head file "ABPerson.h", Apple Inc. didn't give the hint of which api should use as kABPersonModificationDateProperty is deprecated as other apis.
Here is a part of the source head file.
AB_EXTERN const ABPropertyID kABPersonNoteProperty AB_DEPRECATED("use CNContact.note");// Note - kABStringPropertyType
AB_EXTERN const ABPropertyID kABPersonCreationDateProperty AB_DEPRECATED("");// Creation Date (when first saved)
AB_EXTERN const ABPropertyID kABPersonModificationDateProperty AB_DEPRECATED("");// Last saved date

Related

iOS: How to Populate CoreData with downloaded CSV

I have been working on an app where the user inputs data stored in core data everyday (two attributes an NSNumber and one as NSDate) and I wanted to improve that by allowing the user to import data from a external file such as csv or any other supported format through a button click. Any suggestions on how to proceed efficiently to do this?
Thank you.
Edit: Just adding a screenshot of the csv file as well as the output of the csv parser as NSArray. Basicly need to fetch the attribute separately and store them in core data on button click.
- The input file as csv:
- Sample csv parser output(NSarray):
I needed to achieve something similar recently.
A couple of members of my project team wanted to take our app prototype out to show potential clients, but wanted to show different data to each client. We solved this by allowing members of our project team to create their own test data before meeting with the client.
I achieved this by creating an example .csv file and distributing it to the other guys in the project team. They populate it with their own test data and use iTunes File Sharing to drop the .csv test data file on to the device.
On load, the app scans its Documents directory for a the test data file. If it exists, it parses the .csv file and persists to the database.
For the CSV parsing, I used Dave DeLong's CHCSVParser: https://github.com/davedelong/CHCSVParser
Plenty of help is available on setting up iTunes file sharing for your app. A quick Google finds this tutorial (http://www.raywenderlich.com/1948/how-integrate-itunes-file-sharing-with-your-ios-app) which should help you out, if you need it.
Edit- added help on storing data from .csv in Core Data
You stated in your original post that you store an NSNumber and NSDate. Taking that as a starting point, you might have a .csv file in the following form:
+----------------+--------------+
+ NSNumberColumn | NSDateColumn |
+----------------+--------------+
+ 1 | 2013-05-15 |
+ 2 | 2013-06-15 |
+ 3 | 2013-07-15 |
+----------------+--------------+
Assuming the output from the CSV parser is an NSArray of NSArrays, you could create the Core Data objects as follows:
I would create a couple of macros for the column numbers:
#define NSNumberColumn 0
#define NSDateColumn 1
Then iterate over the rows in the .csv file:
NSArray *rows = [NSArray arrayWithContentsOfCSVFile:pathToFile]; //CHCSVParser specific parsing method
for (NSArray *row in rows)
{
NSString *numberString = [parsedCsvRow objectAtIndex:NSNumberColumn];
NSString *dateString = [parsedCsvRow objectAtIndex:NSDateColumn];
NSNumber *number = // parse numberString to an NSNumber. Plenty of other posts on achieving this.
NSDate *date = // parse NSDate from dateString. Plenty of other posts on achieving this.
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObject *myCoreDataObject = [NSEntityDescription insertNewObjectForEntityForName:#"MyCoreDataObject" inManagedObjectContext:context];
[myCoreDataObject setValue:number forKey:#"NSNumberColumn"];
[myCoreDataObject setValue:date forKey:#"NSDateColumn"];
NSError *error;
if (![context save:&error]) {
NSLog(#"%#", [error localizedDescription]);
}
}
Note: Input validation and null checks have been ommited for brevity. I have also taken the liberty of making up your NSManagedObject property names, this will need updating. The above code should be separated in to a more suitable class structure.
I'm not at a Mac right now, so unfortunately I can't check if this works.
Hope that helps.
Try to use plist or json, they are already supported on iOS instead of CSV. CSV would require an third party parser. Using json or plist you will only need to loop throught the elemnts of the collections to create you persistent store. If you have just the CSV you can do a mid conversion using different free tools that you can find for free on the internet and later add to your bundle or publish to your site.
Here's what you do when you already have your CSV file parsed and data is ready to use in Objective-C.
Create a separate context for the import. You don't know how big the data can be, so you probably don't want to block one of your existing contexts while importing.
Iterate through the entries in the parsed data and insert new managed objects configured from each entry.
Every 200, 500, or 1000 entries (different for everybody, you'll need to test what's working best for you) save the context and, if needed, post a notification that a batch has been imported.
To keep the memory low, reset the context and forget all the objects that you created in this import context.
After the loop is finished, don't forget to save the last time.
Now how do you bring the data into another context, say, UI context?
This depends on the way you organized your Core Data stack. For example, import context can be configured as a child of the UI context. In this case, after each save to the import context the changes will be pushed to the UI context (and don't forget to save the UI context as well to push changes further).
But this is not the most efficient approach, because UI context, which is a context on the main thread, is involved in the import, and additional work is done on the UI thread that blocks it. I recommend creating the import context not as a child, but connected to the persistent store coordinator directly. To bring changes to the UI context in this case you either need to call mergeChangesFromContextDidSaveNotification: method after each save or you just refetch in the UI context after each save and in the end. The latter is easier on the UI context and particularly on NSFetchedResultsController, if you use it, because it doesn't need to replay changes to the updated objects one-by-one.

iPhone calendar EKEvent

I am currently trying to create an iPhone calendar app. In order to make sure it syncs with the existing iPhone calendars, I am using the EKEvent toolkit.
However, the events I will be storing will have more properties than the ones EKEvent allows for- e.g., my events will not just have title, details and the few other categories that are allowed for; they will also have themes, priorities...
Thus, when I load the EKEventStore every time my calendar starts up, this information will not be contained in the EKEvents that are loaded.
How can I associate this information to the existing EKEvents so that whenever my calendar is loaded, these additional properties are also loaded?
I would use the eventIdentifier but the iPhone documentation says that "If the calendar of an event changes, its identifier most likely changes as well." If I am reading this correctly, this means that I cannot consistently use eventIdentifier to identify an event..
I would use the notes property and set a string which you can parse later.
Since EKCalendarItem is EKEvent's superclass some of the properties of EKEvent are inherited from EKCalendarItem. (documentation here)
However, you can still 'set' notes on an EKEvent, even though notes is not a property of EKEvent anymore. (go figure)
So, from your question, I might set an integer for each of your additional (custom) properties, like so..
In the view controller code that creates the event:
- set an integer for each of you custom options. (priority, theme, etc.)
int priority = 0;
EKEvent *newEvent = [EKEvent eventWithEventStore:yourEventStore];
[newEvent setCalendar:yourCalendar];
if (priority == 0) {
newEvent.notes = #"0"
}
newEvent.title = #"YourTitle";
newEvent.startDate = yourStartDate;
newEvent.endDate = yourEndDate;
[youreventStore saveEvent:newEvent span:EKSpanThisEvent commit:YES error:nil];
Then if you want to check/convert the custom property, just check the notes of the event whenever you fetch them either using characterAtIndex or make a subString from the notes and compare that to another string.

iOS/iPhone programming. Address book. Extra property for user/contact

I'm developing an iPhone application which uses standard iPhone address book (database) of contacts. I need to add some extra property to contacts but as I see iOS API does not permit addition of extra/custom properties to contacts.
Questions:
1. Is there an ability to deal with extra properties in iOS adressbook API?
2. I need expert's advice about standard approaches of how to store extra data for users/contacts: using SQLite, XML or maybe there is some data store dedicated for every application?
It isn't possible to append custom fields to Address Book records. You should consider looking into Core Data where you can store your custom fields mapped to a record ID.
Add custom property to address book.
The following code listing adds a custom property, and then removes
it:
NSNumber* stringProperty = [NSNumber numberWithInteger:kABStringProperty];
NSString* testProperty = #"com.example.myProperty";
NSDictionary* dict = [NSDictionary dictionaryWithObject:stringProperty
forKey:testProperty];
NSInteger result = [ABPerson addPropertiesAndTypes:dict];
NSLog(#"Added %d properties.", result);
result = [ABPerson removeProperties:[NSArray arrayWithObject:testProperty]];
NSLog(#"Removed %d properties.", result);
More info:
https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AddressBook/Tasks/AddingProperties.html

For anyone familiar with the "TableViewSuite" sample code in apple dev center

In the "sample code" in iOS Dev Center there is a TableViewSuite.
In the first example SimpleTableView the simulator provides a list of time zones by country.
I can not find the list they are pulling from!
it appears to be an array but I can't find the actual words that are coming up on the simulator screen in Xcode.
I've learned about plists and dictionarys and Arrays and simply can't find where the names are coming from.
I found this line:
// Retrieve the array of known time zone names, then sort the array and pass it to the root view controller.
NSArray *timeZones = [NSTimeZone knownTimeZoneNames];
rootViewController.timeZoneNames = [timeZones sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
Again, where is it retrieving the information from?
Thanks again.
They're coming from this message:
[NSTimeZone knownTimeZoneNames]
Which is documented as such:
Returns an array of strings listing the IDs of all the time zones known to the system.
So essentially they're predefined somewhere in iOS and the names are simply being queried off the system.
+[NSTimeZone knownTimeZoneNames] gets the list of time zones from the system itself. There is no list in the project.

How to get the time and date details from pasteboard

when i copy the content in iphone the content is available in the pastebpard ,how do i get the time and date from the pasteboard
By putting a date and time on the pasteboard in the first place?
Your comment fills in some rather critical missing information. I suggest that you edit your question to include the missing information.
(1) if there is a date & time in what is copied, you'll need to detect it and parse it. How you do that is entirely dependent on what is being copied.
(2) If you want the date/time of when the pasteboard was taken, then you would want to look to the UIPasteboard's API. There isn't anything that captures the date of when a pasteboard was created, though.
Now, if you are looking to see if the pasteboard has changed since the last time you looked, use the [changeCount][2].