iOS Error Creating Contact - contacts

I'm using the following code to create a contact:
CNContactRelation *rel = [[CNContactRelation alloc] initWithName:#"John"];
CNLabeledValue *lv = [[CNLabeledValue alloc] labeledValueBySettingLabel:#"_$!<Friend>!$_" value:rel];
NSMutableArray *arr = [NSMutableArray new];
[arr addObject:lv];
CNMutableContact *contact = [[CNMutableContact alloc] init];
contact.givenName = #"Joe";
[contact setContactRelations:arr];
CNSaveRequest *request = [[CNSaveRequest alloc] init];
[request addContact:contact toContainerWithIdentifier:nil];
NSError *saveError;
if (![store executeSaveRequest:request error:&saveError])
NSLog(#"error = %#", saveError);
I get this error on saving:
error = Error Domain=CNErrorDomain Code=2 "(null)" UserInfo={CNKeyPaths=(
contactRelations)}
If I remove the line that sets the contact relation ([contact setContactRelations:arr]), then the contact is created just fine.
Would anyone know what's wrong with the contact relations array, or is setting this not allowed?

Try this. It worked for me. Swift 3.1. Must import 'Contacts'
let store = CNContactStore()
let contact = CNMutableContact()
contact.givenName = "first Name"
contact.familyName = "Last Name"
let workEmail = CNLabeledValue(label:CNLabelWork, value:"EMAIL" as NSString)
contact.emailAddresses = [workEmail]
let homePhone = CNLabeledValue(label: CNLabelWork, value: CNPhoneNumber(stringValue :NUMBER ))
contact.phoneNumbers = [homePhone]
let saveRequest = CNSaveRequest()
saveRequest.add(contact, toContainerWithIdentifier:nil)
try! store.execute(saveRequest)

Related

Error while sending email in iOS 5

I m using SKPSMTPMessage files to send the mails but it is showing the following error while sending the email
Error Domain=SKPSMTPMessageError
Code=535 "Invalid username or password."
UserInfo=0xaa2de20 {NSLocalizedRecoverySuggestion=Go to Email Preferences in the application and re-enter your username and password.,
NSLocalizedDescription=Invalid username or password.}
Where should I change the user name and password? The code is as follows:
SKPSMTPMessage *msg = [[SKPSMTPMessage alloc] init];
msg.fromEmail = #"123456789s#gmail.com";
msg.toEmail = to;
msg.relayHost = #"smtp.gmail.com";
msg.requiresAuth = YES;
msg.login = #"123456789#gmail.com";
msg.pass = #"123456789//";
msg.wantsSecure = YES; // smtp.gmail.com doesn't work without TLS!
msg.subject = [NSString stringWithFormat:#"Check Out %# by Docstoc", self.navigationItem.title];
msg.delegate = self;
NSMutableArray *msg_parts = [NSMutableArray array];
NSDictionary *plain_text_part = [NSDictionary dictionaryWithObjectsAndKeys:
#"text/html\r\n\tcharset=UTF-8;\r\n\tformat=flowed", kSKPSMTPPartContentTypeKey,
[message stringByAppendingString:#"\n"], kSKPSMTPPartMessageKey,
nil];
[msg_parts addObject:plain_text_part];
msg.parts = msg_parts;
[msg send];
Note: This is perfectly working code. Since last week it is showing the error.
try
NSMutableArray *msg_parts = [[NSMutableArray alloc]initWithArray:array];
instead of NSMutableArray *msg_parts = [NSMutableArray array];
Please check your below details are valid or not,
msg.login = #"123456789#gmail.com";
msg.pass = #"123456789//";

Manually load objects using RestKit into Core Data using JSON string

Using the development branch of restkit (0.20), is there a way to perform mapping on a JSON string into the core data object store?
I know in 0.10, the method described at the bottom of this page worked but how is this operation performed in restkit 0.20? Any guidance appreciated! Thanks!
id<RKParser> parser = [[RKParserRegistry sharedRegistry] parserForMIMEType:MIMEType];
id parsedData = [parser objectFromString:JSONString error:&error];
RKObjectMappingProvider* mappingProvider = [RKObjectManager sharedManager].mappingProvider;
RKObjectMapper* mapper = [RKObjectMapper mapperWithObject:parsedData mappingProvider:mappingProvider];
RKObjectMappingResult* result = [mapper performMapping];
I installed RESTKit v0.20.0pre4 yesterday and had the same need for one particular case.
Here is an example of the JSON String I want to map:
{"info":"the sun is shining","detail":"in Bordeaux ~ 29 °C"}
This is how I perform the mapping.
- (InfoRESTMapped *)mapInfoFromJSONString:(NSString *) JSONString{
NSString* MIMEType = #"application/json";
NSError* error;
NSData *data = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
id parsedData = [RKMIMETypeSerialization objectFromData:data MIMEType:MIMEType error:&error];
if (parsedData == nil && error) {
//deal with error
}
RKObjectMapping *infoMapping = [RKObjectMapping requestMapping];
[infoMapping addAttributeMappingsFromDictionary:#{
#"info": #"myInfo",
#"detail": #"myDetail",
}];
InfoRESTMapped *infoMapped = [[InfoRESTMapped alloc] init];
RKMappingOperation* mapper = [[RKMappingOperation alloc] initWithSourceObject:parsedData destinationObject:infoMapped mapping:infoMapping];
[mapper performMapping:&error];
return infoMapped;
}
These posts led me to the solution I have suggested:
https://github.com/RestKit/RestKit/issues/999
https://groups.google.com/d/topic/restkit/M1d7WwcFBDA/discussion
I hope it helps. I guess some other will give better solutions when the final version will be released (with better documentation too...).
For Restkit 0.22, You can use this code. This returns an RKMappingResult wherein you can enumerate the objects after mapping using the property .array.
- (RKMappingResult *)mapJSONStringWithString:(NSString *)jsonString
{
RKMappingResult *result = nil;
NSError* error;
NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
id parsedData = [RKMIMETypeSerialization objectFromData:data MIMEType:RKMIMETypeJSON error:&error];
if (parsedData == nil && error) {
NSLog(#"json mapping error");
}
NSDictionary *mappingsDictionary = #{#"":[CustomMappingClass getMappingForUsers]};
ObjectClass *obj = [ObjectClass new];
RKMapperOperation *mapper = [[RKMapperOperation alloc] initWithRepresentation:parsedData mappingsDictionary:mappingsDictionary];
NSError *mappingError = nil;
mapper.targetObject = obj;
BOOL isMapped = [mapper execute:&mappingError];
if (isMapped && !mappingError) {
result = [mapper mappingResult];
}
return result;
}
The most straightforward way to import JSON into your Core Data store using RestKit is documented in the Read Me "Generate a Seed Database"
Here is what I wrote in Swift:
if let persistentStore = RKManagedObjectStore.default().persistentStoreCoordinator.persistentStores.first {
if let objectImporter = RKManagedObjectImporter.init(persistentStore: persistentStore) {
let path = Bundle.main.path(forResource: jsonFile, ofType: "json")
let mapping = SLTour.responseMapping()
var error:NSError?
objectImporter.importObjectsFromItem(atPath: path, with: mapping, keyPath: "data", error: &error)
try objectImporter.finishImporting()
objectImporter.logSeedingInfo()
}
}
Hopefully, this will save somebody from several hours of trying to solve this in the future.

Core Data - How to fetch an entity with max value property

I have a entity Person with a property personId (personId is unique)
How can I fetch the Person with the max personId?
(I want to fetch the person itself not the value of the property)
You set the fetchLimit to 1 and sort by personId in descending order. E.g.:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Person"];
fetchRequest.fetchLimit = 1;
fetchRequest.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"personId" ascending:NO]];
NSError *error = nil;
id person = [managedObjectContext executeFetchRequest:fetchRequest error:&error].firstObject;
You need to use a NSFetchRequest with a NSPredicate to specify your query...
Adapted from Apple's Predicate Progamming Guide :
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Person"
inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
request.predicate = [NSPredicate predicateWithFormat:#"personId==max(personId)"];
request.sortDescriptors = [NSArray array];
NSError *error = nil;
NSArray *array = [managedObjectContext executeFetchRequest:request error:&error];
The recommended way is to use Apple Recommended Method NSExpression. I would expect that this would be less expensive than using a sort.If you think about it, with a sort you would have to take all the records sort them and keep the maximum one. With an expression you would just have to read through the list and keep in memory the maximum.
Here is an example I use with NSDate
- (NSDate *)lastSync:(PHAssetMediaType)mediaType {
NSEntityDescription *entity = [NSEntityDescription entityForName:kMediaItemEntity inManagedObjectContext:self.managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
fetchRequest.entity = entity;
fetchRequest.resultType = NSDictionaryResultType;
NSMutableArray *predicates = [NSMutableArray array];
[predicates addObject:[NSPredicate predicateWithFormat:#"%K=%d", kMediaType,mediaType]];
[predicates addObject:[NSPredicate predicateWithFormat:#"%K=%d", kMediaProviderType,self.mediaProviderType]];
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates: predicates];
fetchRequest.predicate = predicate;
// Create an expression for the key path.
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:kSyncTime];
// Create an expression to represent the function you want to apply
NSExpression *maxExpression = [NSExpression expressionForFunction:#"max:"
arguments:#[keyPathExpression]];
// Create an expression description using the maxExpression and returning a date.
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:#"maxDate"];
[expressionDescription setExpression:maxExpression];
[expressionDescription setExpressionResultType:NSDateAttributeType];
// Set the request's properties to fetch just the property represented by the expressions.
fetchRequest.propertiesToFetch = #[expressionDescription] ; // #[kSyncTime];
NSError *fetchError = nil;
id requestedValue = nil;
// fetch stored media
NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&fetchError];
if (fetchError || results == nil || results.count == 0) {
return [NSDate dateWithTimeIntervalSince1970:0];
}
requestedValue = [[results objectAtIndex:0] valueForKey:#"maxDate"];
if (![requestedValue isKindOfClass:[NSDate class]]) {
return [NSDate dateWithTimeIntervalSince1970:0];
}
DDLogDebug(#"sync date %#",requestedValue);
return (NSDate *)requestedValue;
}
The answer given above using NSExpression is correct. Here is the Swift version.
private func getLastSyncTimestamp() -> Int64? {
let request: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest()
request.entity = NSEntityDescription.entity(forEntityName: "EntityName", in: self.moc)
request.resultType = NSFetchRequestResultType.dictionaryResultType
let keypathExpression = NSExpression(forKeyPath: "timestamp")
let maxExpression = NSExpression(forFunction: "max:", arguments: [keypathExpression])
let key = "maxTimestamp"
let expressionDescription = NSExpressionDescription()
expressionDescription.name = key
expressionDescription.expression = maxExpression
expressionDescription.expressionResultType = .integer64AttributeType
request.propertiesToFetch = [expressionDescription]
var maxTimestamp: Int64? = nil
do {
if let result = try self.moc.fetch(request) as? [[String: Int64]], let dict = result.first {
maxTimestamp = dict[key]
}
} catch {
assertionFailure("Failed to fetch max timestamp with error = \(error)")
return nil
}
return maxTimestamp
}
where moc is a NSManagedObjectContext.
Swift 3
let request:NSFetchRequest = Person.fetchRequest()
let sortDescriptor1 = NSSortDescriptor(key: "personId", ascending: false)
request.sortDescriptors = [sortDescriptor1]
request.fetchLimit = 1
do {
let persons = try context.fetch(request)
return persons.first?.personId
} catch {
print(error.localizedDescription)
}
SWIFT 4
let request: NSFetchRequest<Person> = Person.fetchRequest()
request.fetchLimit = 1
let predicate = NSPredicate(format: "personId ==max(personId)")
request.predicate = predicate
var maxValue: Int64? = nil
do {
let result = try self.context.fetch(request).first
maxValue = result?.personId
} catch {
print("Unresolved error in retrieving max personId value \(error)")
}
In addition to Ryan's answer, in Swift today, NSManagedObject's execute(_:) returns a NSPersistentStoreResult object, which need some extra code to retrieve the value:
// Cast `NSPersistentStoreResult` to `NSAsynchronousFetchResult<NSDictionary>`
let fetchResult = moc.execute(request) as! NSAsynchronousFetchResult<NSDictionary>
// Retrieve array of dictionary result
let dictsResult = fetchResult.finalResult
// Retrieve and cast the real result
let key = /* `expressionDescription.name` */
let result = dictsResult.first!.object(forKey: key) as! /* Your type, depending on `expressionDescription.expressionResultType` */
Note: Force unsafe type cast are used above to simplify code, in real case scenario, you should always avoid this.

How to get street address from ABPeoplePickerNavigationController

I need a contact's street address. I know how to get the single value properties, but the street address is a multivalue property. Apple's documentation shows how to set it, but not retrieve it. Any help?
PS: this does not work:
ABRecordCopyValue(person, kABPersonAddressStreetKey);
I just figured it out:
ABMultiValueRef st = ABRecordCopyValue(person, kABPersonAddressProperty);
if (ABMultiValueGetCount(st) > 0) {
CFDictionaryRef dict = ABMultiValueCopyValueAtIndex(st, 0);
self.street.text = CFDictionaryGetValue(dict, kABPersonAddressStreetKey);
}
Swift version :
if let addresses : ABMultiValueRef = ABRecordCopyValue(person, kABPersonAddressProperty)?.takeRetainedValue() as ABMultiValueRef? where ABMultiValueGetCount(addresses) > 0 {
for index in 0..<ABMultiValueGetCount(addresses){
if let address = ABMultiValueCopyValueAtIndex(addresses, index)?.takeRetainedValue() as? [String:String],
label = ABMultiValueCopyLabelAtIndex(addresses, index)?.takeRetainedValue() as? String{
print("\(label): \(address) \n")
}
}
}
You can access individual field of address by providing corresponding key :
let street = address[kABPersonAddressStreetKey as String]
let city = address[kABPersonAddressCityKey as String]
let state = address[kABPersonAddressStateKey as String]
let zip = address[kABPersonAddressZIPKey as String]
let country = address[kABPersonAddressCountryKey as String]
let code = address[kABPersonAddressCountryCodeKey as String]
Swift 3.0
//Extract billing address from ABRecord format and assign accordingly
let addressProperty: ABMultiValue = ABRecordCopyValue(billingAddress, kABPersonAddressProperty).takeUnretainedValue() as ABMultiValue
if let dict: NSDictionary = ABMultiValueCopyValueAtIndex(addressProperty, 0).takeUnretainedValue() as? NSDictionary {
print(dict[String(kABPersonAddressStreetKey)] as? String)
print(dict[String(kABPersonAddressCityKey)] as? String)
print(dict[String(kABPersonAddressStateKey)] as? String)
print(dict[String(kABPersonAddressZIPKey)] as? String)
print(dict[String(kABPersonAddressCountryKey)] as? String) //"United States"
}
If the user has multiple addressed defined - work, home, etc, you will need to use the identifier attribute to distinguish between them. What I have arrive at, culled from similar posts on email addresses, is:
#pragma mark - ABPeoplePickerNavigationControllerDelegate
- (IBAction)chooseContact:(id)sender
{
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
[self presentViewController:picker animated:YES completion:nil];
// [self dismissViewControllerAnimated:YES completion:nil];
}
- (void) peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
return YES;
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier
{
if (property == kABPersonAddressProperty)
{
ABMultiValueRef addresses = ABRecordCopyValue(person, property);
CFIndex addressIndex = ABMultiValueGetIndexForIdentifier(addresses, identifier);
CFDictionaryRef address = ABMultiValueCopyValueAtIndex(addresses, addressIndex);
// create address string to lookup
NSString *street = (NSString*) CFDictionaryGetValue(address, kABPersonAddressStreetKey);
NSString *city = (NSString*) CFDictionaryGetValue(address, kABPersonAddressCityKey);
NSString *state = (NSString*) CFDictionaryGetValue(address, kABPersonAddressStateKey);
NSString *postal = (NSString*) CFDictionaryGetValue(address, kABPersonAddressZIPKey);
NSString *country = (NSString*) CFDictionaryGetValue(address, kABPersonAddressCountryKey);
CFRelease(address);
CFRelease(addresses);
[self dismissViewControllerAnimated:YES completion:nil];
return NO;
}
return YES;
}
.
I suppose it should work like this (derived from the documentation, not tested):
ABMultiValueRef addressMultiValue = ABRecordCopyValue(person, kABPersonAddressProperty);
CFArrayRef allAddresses = ABMultiValueCopyArrayOfAllValues(addressMultiValue);
CFDictionaryRef firstAddress = CFArrayGetValueAtIndex(allAddresses, 0);
CFStringRef street = CFDictionaryGetValue(firstAddress, kABPersonAddressStreetKey);
NSLog(#"%#", (__bridge NSString *)street);
CFRelease(allAddresses);
CFRelease(addressMultiValue);
The Address Book UI framework is deprecated in iOS 9. Use the APIs defined in the ContactsUI framework instead. To learn more, see ContactsUI.

how to post with json

Hello I want to set following key Values for Dictionary
{
application = {
id = 136664723060869;
name = Iphoneapp;
};
caption = "bit.ly";
comments = {
count = 2;
data = (
{
"created_time" = "2011-06-14T07:39:45+0000";
from = {
id = 100001507678574;
name = "Widevision Dev";
};
id = "100001507678574_164163733643881_1822049";
likes = 1;
message = hi;
},
{
"created_time" = "2011-06-14T08:17:31+0000";
from = {
id = 100001507678574;
name = "Widevision Dev";
};
id = "100001507678574_164163733643881_1822143";
message = hmmm;
}
);
};
I want to post comments ={ data ={ id = , name = }}
I used following code for this
NSMutableDictionary *variables = [NSMutableDictionary dictionaryWithCapacity:4];
[variables setObject:#"Good Afternoon" forKey:#"message"];
NSLog(#"%#",variables);
FbGraphResponse *fb_graph_response = [fbGraph doGraphPost:#"id/comments" withPostVars:variables];
NSLog(#"postMeFeedButtonPressed: %#", fb_graph_response.htmlResponse);
But this not working....How can I post message in comment object
Please check the code below:
NSMutableDictionary *comments = [[NSMutableDictionary alloc] init];
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
NSMutableDictionary *from = [[NSMutableDictionary alloc] init];
[from setObject:#"100001507678574" forKey:#"id"];
[from setObject:#"Widevision Dev" forKey:#"name"];
[data setObject:from forKey:#"from"];
[comments setObject:data forKey:#"comments"];
NSLog(#"%#",comments);
FbGraphResponse *fb_graph_response = [fbGraph doGraphPost:#"id/comments" withPostVars:comments];