I am trying to activate APNS. Because uniqueIdentifier is deprecated, I'm trying to use CFUUIDCreate with the following code:
UIDevice *dev = [UIDevice currentDevice];
NSString *deviceUuid;
if ([dev respondsToSelector:#selector(uniqueIdentifier)])
deviceUuid = dev.uniqueIdentifier;
else {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
id uuid = [defaults objectForKey:#"deviceUuid"];
if (uuid)
deviceUuid = (NSString *)uuid;
else {
CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
deviceUuid = (__bridge NSString *)cfUuid;
CFRelease(cfUuid);
[defaults setObject:deviceUuid forKey:#"deviceUuid"];
}
}
How can I replace uniqueIdentifier with CFUUIDCreate?
iOS < 6.0
// Create universally unique identifier (object)
CFUUIDRef uuidObject = CFUUIDCreate(kCFAllocatorDefault);
// Get the string representation of CFUUID object.
NSString *uuidStr = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuidObject);
CFRelease(uuidObject);
iOS >= 6.0
NSString* UDID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
Related
This question already has answers here:
Potential leak of an object stored into 'string' [duplicate]
(3 answers)
Closed 6 years ago.
When i do "Build and analyze" XCode gives me the following warning:
Potential leak of an object stored into 'string'
- (NSString *)getUUID
{
NSString *UUID = [EA_APP_CONSTANT getUserDefaultsValueForKey:#"uniqueID"];
if (!UUID) {
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
UUID = [(__bridge NSString*)string stringByReplacingOccurrencesOfString:#"-"withString:#""];
[EA_APP_CONSTANT setUserDefaultsValue:UUID forKey:#"uniqueID"];
}
return UUID;
}
How can i resolve this Problem?
You need call CFRelease(string);
- (NSString *)getUUID
{
NSString *UUID = [EA_APP_CONSTANT getUserDefaultsValueForKey:#"uniqueID"];
if (!UUID) {
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
UUID = [(__bridge NSString*)string stringByReplacingOccurrencesOfString:#"-"withString:#""];
[EA_APP_CONSTANT setUserDefaultsValue:UUID forKey:#"uniqueID"];
CFRelease(string);
}
return UUID;
}
Need one unique id for my app. That unique id should never change. When the user uninstalls the app or kills the app it should not be changed. I have searched for something, but I don't need a UUID. I have decided to get the device token using this code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
else
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeNewsstandContentAvailability| UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}
return YES;
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings // NS_AVAILABLE_IOS(8_0);
{
[application registerForRemoteNotifications];
}
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken{
NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:#"<>"]];
token = [token stringByReplacingOccurrencesOfString:#" " withString:#""];
NSLog(#"content---%#", token);
}
There is one problem. In iOS 7 I got the device token constant, uninstalled the app and killed the app, and got the device token constant. But in iOS 8 and above the device token is not constant. When user kills the app, the device token changes. I need one unique device token for my app, or any other way to get the unique id. How can I fix this issue? Help me. Thanks advance.
You have to store the value in KeyChain like this.
Import "KeychainItemWrapper.h" in your AppDelegate.m file
Add these code in
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
//+++++++++++++++for unique identifier of the app++++++++++++++++
[[NSUserDefaults standardUserDefaults] setObject:#"" forKey:#"uniqueIdentifier"];
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:#"MyUniqueId" accessGroup:nil];
NSString *strIdent;
if ([[keychainItem objectForKey:(id)kSecAttrAccount] isEqualToString:#""]) {
NSString *uniqueIdentifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
NSLog(#"uniqueIdentifier=%#",uniqueIdentifier);
[keychainItem setObject:uniqueIdentifier forKey:(id)kSecAttrAccount];
strIdent = [keychainItem objectForKey:(id)kSecAttrAccount];
[[NSUserDefaults standardUserDefaults] setObject:strIdent forKey:#"uniqueIdentifier"];
}else{
strIdent=[keychainItem objectForKey:(id)kSecAttrAccount];
[[NSUserDefaults standardUserDefaults] setObject:strIdent forKey:#"uniqueIdentifier"];
}
NSLog(#"strIdent=%#",strIdent);
[[NSUserDefaults standardUserDefaults] synchronize];
//[keychainItem resetKeychainItem]; // to reset the keychain
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
KeychainItemWrapper.h
+++++++++++++++++++
#import <UIKit/UIKit.h>
#interface KeychainItemWrapper : NSObject
// Designated initializer.
- (id)initWithIdentifier: (NSString *)identifier accessGroup:(NSString *)accessGroup;
- (void)setObject:(id)inObject forKey:(id)key;
- (id)objectForKey:(id)key;
// Initializes and resets the default generic keychain item data.
- (void)resetKeychainItem;
#end
+++++++++++++++++++++++++++++++
KeychainItemWrapper.m
+++++++++++++++++++++++++++++++
#define PASSWORD_USES_DATA
#import "KeychainItemWrapper.h"
#import <Security/Security.h>
#interface KeychainItemWrapper (PrivateMethods)
- (NSMutableDictionary *)secItemFormatToDictionary:(NSDictionary *)dictionaryToConvert;
- (NSMutableDictionary *)dictionaryToSecItemFormat:(NSDictionary *)dictionaryToConvert;
- (void)writeToKeychain;
#end
#implementation KeychainItemWrapper
{
NSMutableDictionary *keychainItemData; // The actual keychain item data backing store.
NSMutableDictionary *genericPasswordQuery; // A placeholder for the generic keychain item query used to locate the item.
}
- (id)initWithIdentifier: (NSString *)identifier accessGroup:(NSString *) accessGroup;
{
if (self = [super init])
{
genericPasswordQuery = [[NSMutableDictionary alloc] init];
[genericPasswordQuery setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
[genericPasswordQuery setObject:identifier forKey:(__bridge id)kSecAttrGeneric];
if (accessGroup != nil)
{
#if TARGET_IPHONE_SIMULATOR
// Ignore the access group if running on the iPhone simulator.
//
// Apps that are built for the simulator aren't signed, so there's no keychain access group
// for the simulator to check. This means that all apps can see all keychain items when run
// on the simulator.
//
// If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
// simulator will return -25243 (errSecNoAccessForItem).
#else
[genericPasswordQuery setObject:accessGroup forKey:(__bridge id)kSecAttrAccessGroup];
#endif
}
// Use the proper search constants, return only the attributes of the first match.
[genericPasswordQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
[genericPasswordQuery setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnAttributes];
NSDictionary *tempQuery = [NSDictionary dictionaryWithDictionary:genericPasswordQuery];
CFMutableDictionaryRef outDictionary = NULL;
if (!(SecItemCopyMatching((__bridge CFDictionaryRef)tempQuery, (CFTypeRef *)&outDictionary) == noErr))
{
// Stick these default values into keychain item if nothing found.
[self resetKeychainItem];
// Add the generic attribute and the keychain access group.
[keychainItemData setObject:identifier forKey:(__bridge id)kSecAttrGeneric];
if (accessGroup != nil)
{
#if TARGET_IPHONE_SIMULATOR
// Ignore the access group if running on the iPhone simulator.
//
// Apps that are built for the simulator aren't signed, so there's no keychain access group
// for the simulator to check. This means that all apps can see all keychain items when run
// on the simulator.
//
// If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
// simulator will return -25243 (errSecNoAccessForItem).
#else
[keychainItemData setObject:accessGroup forKey:(__bridge id)kSecAttrAccessGroup];
#endif
}
}
else
{
// load the saved data from Keychain.
keychainItemData = [self secItemFormatToDictionary:(__bridge NSDictionary *)outDictionary];
}
if(outDictionary) CFRelease(outDictionary);
}
return self;
}
- (void)setObject:(id)inObject forKey:(id)key
{
if (inObject == nil) return;
id currentObject = [keychainItemData objectForKey:key];
if (![currentObject isEqual:inObject])
{
[keychainItemData setObject:inObject forKey:key];
[self writeToKeychain];
}
}
- (id)objectForKey:(id)key
{
return [keychainItemData objectForKey:key];
}
- (void)resetKeychainItem
{
if (!keychainItemData)
{
keychainItemData = [[NSMutableDictionary alloc] init];
}
else if (keychainItemData)
{
NSMutableDictionary *tempDictionary = [self dictionaryToSecItemFormat:keychainItemData];
#ifndef NS_BLOCK_ASSERTIONS
OSStatus junk =
#endif
SecItemDelete((__bridge CFDictionaryRef)tempDictionary);
NSAssert( junk == noErr || junk == errSecItemNotFound, #"Problem deleting current dictionary." );
}
// Default attributes for keychain item.
[keychainItemData setObject:#"" forKey:(__bridge id)kSecAttrAccount];
[keychainItemData setObject:#"" forKey:(__bridge id)kSecAttrLabel];
[keychainItemData setObject:#"" forKey:(__bridge id)kSecAttrDescription];
// Default data for keychain item.
#ifndef PASSWORD_USES_DATA
[keychainItemData setObject:#"" forKey:(__bridge id)kSecValueData];
#else
[keychainItemData setObject:[NSData data] forKey:(__bridge id)kSecValueData];
#endif
}
- (NSMutableDictionary *)dictionaryToSecItemFormat:(NSDictionary *)dictionaryToConvert
{
// The assumption is that this method will be called with a properly populated dictionary
// containing all the right key/value pairs for a SecItem.
// Create a dictionary to return populated with the attributes and data.
NSMutableDictionary *returnDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];
// Add the Generic Password keychain item class attribute.
[returnDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
// Convert the NSString to NSData to meet the requirements for the value type kSecValueData.
// This is where to store sensitive data that should be encrypted.
#ifndef PASSWORD_USES_DATA
// orig
NSString *passwordString = [dictionaryToConvert objectForKey:(__bridge id)kSecValueData];
[returnDictionary setObject:[passwordString dataUsingEncoding:NSUTF8StringEncoding] forKey:(__bridge id)kSecValueData];
#else
// DFH
id val = [dictionaryToConvert objectForKey:(__bridge id)kSecValueData];
if([val isKindOfClass:[NSString class]]) {
val = [(NSString *)val dataUsingEncoding:NSUTF8StringEncoding];
}
[returnDictionary setObject:val forKey:(__bridge id)kSecValueData];
#endif
return returnDictionary;
}
- (NSMutableDictionary *)secItemFormatToDictionary:(NSDictionary *)dictionaryToConvert
{
// The assumption is that this method will be called with a properly populated dictionary
// containing all the right key/value pairs for the UI element.
// Create a dictionary to return populated with the attributes and data.
NSMutableDictionary *returnDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];
// Add the proper search key and class attribute.
[returnDictionary setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
[returnDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
// Acquire the password data from the attributes.
CFDataRef passwordData = NULL;
if (SecItemCopyMatching((__bridge CFDictionaryRef)returnDictionary, (CFTypeRef *)&passwordData) == noErr)
{
// Remove the search, class, and identifier key/value, we don't need them anymore.
[returnDictionary removeObjectForKey:(__bridge id)kSecReturnData];
#ifndef PASSWORD_USES_DATA
// Add the password to the dictionary, converting from NSData to NSString.
NSString *password = [[NSString alloc] initWithBytes:[(__bridge NSData *)passwordData bytes] length:[(__bridge NSData *)passwordData length]
encoding:NSUTF8StringEncoding];
#else
NSData *password = (__bridge_transfer NSData *)passwordData;
passwordData = NULL;
#endif
[returnDictionary setObject:password forKey:(__bridge id)kSecValueData];
}
else
{
// Don't do anything if nothing is found.
NSAssert(NO, #"Serious error, no matching item found in the keychain.\n");
}
if(passwordData) CFRelease(passwordData);
return returnDictionary;
}
- (void)writeToKeychain
{
CFDictionaryRef attributes = NULL;
NSMutableDictionary *updateItem = nil;
OSStatus result;
if (SecItemCopyMatching((__bridge CFDictionaryRef)genericPasswordQuery, (CFTypeRef *)&attributes) == noErr)
{
// First we need the attributes from the Keychain.
updateItem = [NSMutableDictionary dictionaryWithDictionary:(__bridge NSDictionary *)attributes];
// Second we need to add the appropriate search key/values.
[updateItem setObject:[genericPasswordQuery objectForKey:(__bridge id)kSecClass] forKey:(__bridge id)kSecClass];
// Lastly, we need to set up the updated attribute list being careful to remove the class.
NSMutableDictionary *tempCheck = [self dictionaryToSecItemFormat:keychainItemData];
[tempCheck removeObjectForKey:(__bridge id)kSecClass];
#if TARGET_IPHONE_SIMULATOR
// Remove the access group if running on the iPhone simulator.
//
// Apps that are built for the simulator aren't signed, so there's no keychain access group
// for the simulator to check. This means that all apps can see all keychain items when run
// on the simulator.
//
// If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
// simulator will return -25243 (errSecNoAccessForItem).
//
// The access group attribute will be included in items returned by SecItemCopyMatching,
// which is why we need to remove it before updating the item.
[tempCheck removeObjectForKey:(__bridge id)kSecAttrAccessGroup];
#endif
// An implicit assumption is that you can only update a single item at a time.
#ifndef NDEBUG
result =
#endif
SecItemUpdate((__bridge CFDictionaryRef)updateItem, (__bridge CFDictionaryRef)tempCheck);
NSAssert( result == noErr, #"Couldn't update the Keychain Item." );
}
else
{
// No previous item found; add the new one.
result = SecItemAdd((__bridge CFDictionaryRef)[self dictionaryToSecItemFormat:keychainItemData], NULL);
NSAssert( result == noErr, #"Couldn't add the Keychain Item." );
}
if(attributes) CFRelease(attributes);
}
#end
Try this I hope it would be helpful!!
NSString* Identifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
NSLog(#"output is : %#", Identifier);
IN other ways you can do this!!
NSString *udid = [[UIDevice currentDevice] uniqueIdentifier];
Try with other Options!!
create your own unique ID and save it in the keychain.
use the vendor ID, which will be reset if all the app by the same vendor are removed from the device.
i am newbie in iOS Development and i want to store my Application UUID in KeyChain so For any Time my Application UUID remaining same i do R&D on it and Find a code from this Site i mess StackOver Flow the Code is like as
+(NSUUID *)persistentIdentifierForVendor
{
static NSString * const kKeyChainVendorID = #"co.cwbrn.PersistentIdentifier";
static NSString * const kKeyChainVendorIDAccessGroup = #"<AppIdentifier>.<keychain-access-group-identifier>";
// First, check NSUserDefaults so that we're not hitting the KeyChain every single time
NSString *uuidString = [[NSUserDefaults standardUserDefaults] stringForKey:kKeyChainVendorIDGroup];
BOOL vendorIDMissingFromUserDefaults = (uuidString == nil || uuidString.length == 0);
if (vendorIDMissingFromUserDefaults) {
// Check to see if a UUID is stored in the KeyChain
NSDictionary *query = #{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrAccount: kKeyChainVendorID,
(__bridge id)kSecAttrService: kKeyChainVendorID,
(__bridge id)kSecAttrAccessGroup: kKeyChainVendorIDAccessGroup,
(__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitOne,
(__bridge id)kSecReturnAttributes: (__bridge id)kCFBooleanTrue
};
CFTypeRef attributesRef = NULL;
OSStatus result = SecItemCopyMatching((__bridge CFDictionaryRef)query, &attributesRef);
if (result == noErr) {
// There is a UUID, so try to retrieve it
NSDictionary *attributes = (__bridge_transfer NSDictionary *)attributesRef;
NSMutableDictionary *valueQuery = [NSMutableDictionary dictionaryWithDictionary:attributes];
[valueQuery setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
[valueQuery setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
CFTypeRef passwordDataRef = NULL;
OSStatus result = SecItemCopyMatching((__bridge CFDictionaryRef)valueQuery, &passwordDataRef);
if (result == noErr) {
NSData *passwordData = (__bridge_transfer NSData *)passwordDataRef;
uuidString = [[NSString alloc] initWithBytes:[passwordData bytes]
length:[passwordData length]
encoding:NSUTF8StringEncoding];
}
}
}
// Failed to read the UUID from the KeyChain, so create a new UUID and store it
if (uuidString == nil || uuidString.length == 0) {
// Generate the new UIID
CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
uuidString = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
CFRelease(uuidRef);
// Now store it in the KeyChain
NSDictionary *query = #{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrAccount: kKeyChainVendorID,
(__bridge id)kSecAttrService: kKeyChainVendorID,
(__bridge id)kSecAttrAccessGroup: kKeyChainVendorIDAccessGroup,
(__bridge id)kSecAttrLabel: #"",
(__bridge id)kSecAttrDescription: #"",
(__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleAfterFirstUnlock,
(__bridge id)kSecValueData: [uuidString dataUsingEncoding:NSUTF8StringEncoding]
};
OSStatus result = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
if (result != noErr) {
NSLog(#"ERROR: Couldn't add to the Keychain. Result = %ld; Query = %#", result, query);
return nil;
}
}
// Save UUID to NSUserDefaults so that we can avoid the KeyChain next time
if (vendorIDMissingFromUserDefaults) {
[[NSUserDefaults standardUserDefaults] setObject:uuidString forKey:kKeyChainVendorIDGroup];
}
return [[NSUUID alloc] initWithUUIDString:uuidString];
}
But i want to Know that here What is kKeyChainVendorID and kKeyChainVendorIDAccessGroup here it use is like as
static NSString * const kKeyChainVendorID = #"co.cwbrn.PersistentIdentifier";
static NSString * const kKeyChainVendorIDAccessGroup = #"<AppIdentifier>.<keychain-access-group-identifier>";
For My application how i Get two Value like as kKeyChainVendorID and kKeyChainVendorIDAccessGroup??Please Give me Solution for that and in my Xcode 5.0 Version error are Occurred in line
NSString *uuidString = [[NSUserDefaults standardUserDefaults] stringForKey:kKeyChainVendorIDGroup];
Erro is:- Replace kKeyChainVendorIDGroup with kKeyChainVendorID. Can i replace it then it is Work or not Please Give me Solution For my Both Question
Thanks in advance. and thanks to nelico that post answer in stack overflow.
Here i Post My Own Answer. I get answer From this Link
http://objectivecwithsuraj.blogspot.in/2014/01/unique-identifier-uuid-ios.html
i use FDKeyChain and Write Following Code to Save UUID In KeyChain
Just Define Two String like as
static NSString * const KeychainItem_Service = #"FDKeychain";
static NSString * const KeychainItem_UUID = #"Local";
and For Get UUID I write as
uniqueIdentifier=[self generateUUID];
-(NSString *)generateUUID {
NSString *CFUUID = nil;
if (![FDKeychain itemForKey: KeychainItem_UUID
forService: KeychainItem_Service
error: nil]) {
CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
CFUUID = (NSString *)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuid));
[FDKeychain saveItem: CFUUID
forKey: KeychainItem_UUID
forService: KeychainItem_Service
error: nil];
} else {
CFUUID = [FDKeychain itemForKey: KeychainItem_UUID
forService: KeychainItem_Service
error: nil];
}
return CFUUID;
}
Hope it Help to SomeOne. and if i do some fault in my answer then please give me solution. Thanks For reply.
I'm a starter in obj-c programming and I need to know how to display device info ( name, device type, ios version )
I you know the answer, please tell me and keep in mind i'm a starter with xcode ;)
I've used these information in an App that I developed so I did the following code. I think this may help you. I just didn't understand what you mean with device type.
To get the device model:
// get model from UIDevice
NSString *modelDevice = [UIDevice currentDevice].model;
To get the iOS Version:
//get the iOS version
NSString *systemVersion = [[UIDevice currentDevice] systemVersion];
To get the device name:
/** Method responsible to get the device name
*
* #return device Name
*/
+ (NSString *)deviceName
{
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *machine = malloc(size);
sysctlbyname("hw.machine", machine, &size, NULL, 0);
NSString *platform = [NSString stringWithUTF8String:machine];
free(machine);
return platform;
}
You may try something like this: I use this for in-app support emailing from users.
#import <sys/utsname.h>
- (void)yourMethod
{
struct utsname systemInfo;
uname(&systemInfo);
NSString *appVersion = [NSBundle mainBundle].infoDictionary[#"CFBundleVersion"];
NSString *osVersion = [[UIDevice currentDevice] systemVersion];
NSString *machine = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
}
NSLog(#"uniqueIdentifier: %#", [[UIDevice currentDevice] uniqueIdentifier]);
NSLog(#"name: %#", [[UIDevice currentDevice] name]);
NSLog(#"systemName: %#", [[UIDevice currentDevice] systemName]);
NSLog(#"systemVersion: %#", [[UIDevice currentDevice] systemVersion]);
NSLog(#"model: %#", [[UIDevice currentDevice] model]);
NSLog(#"localizedModel: %#", [[UIDevice currentDevice] localizedModel])
;
Please refer to UIDevice Class. It has all accessible system information properties. This is a singleton class. You can access this class instance like this : [UIDevice currentDevice]
For example if you want to access device model, you can access like this :
[UIDevice currentDevice]. model
Please refer this link to get information about all properties : https://developer.apple.com/library/ios/documentation/uikit/reference/UIDevice_Class/Reference/UIDevice.html
Now i ve got this code:
-(void)getContacts{
ABAddressBookRef currentAddressBook = ABAddressBookCreate();
if (currentAddressBook) {
CFArrayRef allBook = ABAddressBookCopyArrayOfAllPeople(currentAddressBook);
if (allBook) {
for (int index=0; index < CFArrayGetCount(allBook); index++){
ABRecordRef currentPerson = CFArrayGetValueAtIndex(allBook, index);
NSString *firstName = (__bridge NSString *)ABRecordCopyValue(currentPerson, kABPersonFirstNameProperty);
NSString *lastName = (__bridge NSString *)ABRecordCopyValue(currentPerson, kABPersonLastNameProperty);
NSData *imageData = (__bridge NSData*)ABPersonCopyImageDataWithFormat(currentPerson, kABPersonImageFormatThumbnail);
NSMutableArray *tempArrayForPhones = [[NSMutableArray alloc] init];
ABMultiValueRef phoneNumbersMultiValue = ABRecordCopyValue(currentPerson, kABPersonPhoneProperty);
for(CFIndex counter = 0; counter < ABMultiValueGetCount(phoneNumbersMultiValue); counter++){
CFStringRef currentLabel = ABMultiValueCopyLabelAtIndex(phoneNumbersMultiValue, counter);
NSString *phoneLabel =(__bridge NSString*) ABAddressBookCopyLocalizedLabel(currentLabel);
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phoneNumbersMultiValue, counter);
currentLabel = ABMultiValueCopyLabelAtIndex(phoneNumbersMultiValue, counter);
phoneLabel =(__bridge NSString*) ABAddressBookCopyLocalizedLabel(currentLabel);
NSString *phoneNumber = (__bridge NSString *)phoneNumberRef;
CFRelease(phoneNumberRef);
CFRelease(currentLabel);
NSDictionary *tempDictForPhonew = [NSDictionary dictionaryWithObjectsAndKeys:phoneNumber,#"number",
phoneLabel,#"label",
nil];
[tempArrayForPhones addObject:tempDictForPhonew];
}
NSDictionary *dictionaryWithAddressBook = [NSDictionary dictionaryWithObjectsAndKeys:firstName,#"firstName",
lastName,#"lastName",
imageData,#"image",
tempArrayForPhones,#"phones",
nil];
tempArrayForPhones = nil;
[dataArray addObject:dictionaryWithAddressBook];
CFRelease(phoneNumbersMultiValue);
}
CFRelease(allBook);
}
CFRelease(currentAddressBook);
}
}
all works fine on simulator, i get array with dictionary, which contains all fields i need. But when i run code on real device(iOS 5.1) dictionary got only first name and last name.
I tried to do some nslog around initializing dictionary, and temp dictionary with phones and image data existed, but not in final dataArray. Whats wrong?
Problem solved; It was a mistake in parsing address book; I forgot to handle contacts without first name.