In my previous app,I was using the below mentioned code to generate unique deviceId for iOS devices.But the problem is that it will generate a new code everytime when the app is reinstalled.How can i do this properly?
-(NSString*)uniqueIDForDevice //new..
{
NSString* uniqueIdentifier = nil;
if( [UIDevice instancesRespondToSelector:#selector(identifierForVendor)] ) { // >=iOS 7
uniqueIdentifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
}
else
{ //<=iOS6, Use UDID of Device
CFUUIDRef uuid = CFUUIDCreate(NULL);
//uniqueIdentifier = ( NSString*)CFUUIDCreateString(NULL, uuid);- for non- ARC
uniqueIdentifier = ( NSString*)CFBridgingRelease(CFUUIDCreateString(NULL, uuid));// for ARC
CFRelease(uuid);
}
return uniqueIdentifier;
}
You can use the below
+ (NSString *)deviceUUID
{
if([[NSUserDefaults standardUserDefaults] objectForKey:[[NSBundle mainBundle] bundleIdentifier]])
return [[NSUserDefaults standardUserDefaults] objectForKey:[[NSBundle mainBundle] bundleIdentifier]];
#autoreleasepool {
CFUUIDRef uuidReference = CFUUIDCreate(nil);
CFStringRef stringReference = CFUUIDCreateString(nil, uuidReference);
NSString *uuidString = (__bridge NSString *)(stringReference);
[[NSUserDefaults standardUserDefaults] setObject:uuidString forKey:[[NSBundle mainBundle] bundleIdentifier]];
[[NSUserDefaults standardUserDefaults] synchronize];
CFRelease(uuidReference);
CFRelease(stringReference);
return uuidString;
}
}
first of all get vendorId(uniqueID) than store it to keychain
// Fetch vendorID from keychain first, if it exists then use it or fetch vendorID
//if user delete app and again install app than he get vendorID from keychain(if he hasn't cleared it)
NSString *vendorID = [UICKeyChainStore stringForKey:#"KEY TO SAVE TO Keychain" service:nil];
NSLog(#"VendorID from Keychain - %#",vendorID);
//if vandorid from keychain is not nil
if (vendorID)
{
[[NSUserDefaults standardUserDefaults] setObject:vendorID forKey:#"vendorId"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
//else it goes for new vendorid and then stored it to keychan
else
{
vendorID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
[UICKeyChainStore setString:vendorID forKey:#"KEY TO SAVE TO Keychain" service:nil];
[[NSUserDefaults standardUserDefaults] setObject:vendorID forKey:#"vendorId"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"VendorID Local - %#",vendorID);
}
i use this class to save and retrive vendorID from keyChain!
just take one look at this.hope it will help you
use This link to UICKeyChainStore . I have added the following method call
[self getDeviceIdFromKeychain]; in appDelegate applicationdidFinishLaunchingWithOptions
-(void)getDeviceIdFromKeychain
{
NSString *deviceID = [UICKeyChainStore stringForKey:DEVICE_ID_FROM_KEYCHAIN_REFERENCE_APP service:nil];
NSLog(#"deviceID from Keychain = (%#)",deviceID);
//if vandorid from keychain is not nil
if (deviceID)
{
[[NSUserDefaults standardUserDefaults] setObject:deviceID forKey:DEVICE_ID];
[[NSUserDefaults standardUserDefaults] synchronize];
}
//else it goes for new vendorid and then stored it to keychan
else if (deviceID == (id)[NSNull null] || deviceID.length == 0 )
{
NSString *newDeviceId;
newDeviceId=[[self class] deviceUUID];
[[NSUserDefaults standardUserDefaults] setObject:newDeviceId forKey:DEVICE_ID];
[[NSUserDefaults standardUserDefaults] synchronize];
[UICKeyChainStore setString:newDeviceId forKey:DEVICE_ID_FROM_KEYCHAIN_REFERENCE_APP service:nil];
NSLog(#"new deviceID = (%#)",newDeviceId);
}
}
+ (NSString *)deviceUUID
{
if([[NSUserDefaults standardUserDefaults] objectForKey:[[NSBundle mainBundle] bundleIdentifier]])
return [[NSUserDefaults standardUserDefaults] objectForKey:[[NSBundle mainBundle] bundleIdentifier]];
#autoreleasepool {
CFUUIDRef uuidReference = CFUUIDCreate(nil);
CFStringRef stringReference = CFUUI
DCreateString(nil, uuidReference);
NSString *uuidString = (__bridge NSString *)(stringReference);
[[NSUserDefaults standardUserDefaults] setObject:uuidString forKey:[[NSBundle mainBundle] bundleIdentifier]];
[[NSUserDefaults standardUserDefaults] synchronize];
CFRelease(uuidReference);
CFRelease(stringReference);
return uuidString;
}
}
And i use them like this...(in my signinViewcontroller)
NSString *deviceIDfromNSUserDefaults = [[NSUserDefaults standardUserDefaults]valueForKey:DEVICE_ID ];
NSLog(#"deviceID from NSUserDefaults = (%#)",deviceIDfromNSUserDefaults);
I am using UUID to generate unique number. I doubt whether it is allowed to use vender ID if we are not using iAds in app.
I have achieved this by generating UUID and then storing into the keychain.
Keychain will store your UUID till user will not do Hard reset which is rare case.
As no API is provided by Apple to get unique device ID we have to find ways like this.
Related
When I choose a language from language selection list in my app then it shows that language which I selected previously. If I clear the app from my simulator stack or clear it from xcode then run the project, after that it goes ok, and if I want to change the language again then I faced same problem. My code is given below:
- (IBAction)English:(id)sender {
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
[userDefault setObject:[NSArray arrayWithObjects:#"en", nil] forKey:#"AppleLanguages"];
[userDefault synchronize];
ChooseItemVC *civc = (ChooseItemVC*)[self.storyboard instantiateViewControllerWithIdentifier:#"ChooseItemVC"];
[self.navigationController pushViewController:civc animated:YES];
}
Another language selection code:
- (IBAction)Arabic:(id)sender {
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
[userDefault setObject:[NSArray arrayWithObjects:#"ar", nil] forKey:#"AppleLanguages"];
[userDefault synchronize];
ChooseItemVC *civc = (ChooseItemVC*)[self.storyboard instantiateViewControllerWithIdentifier:#"ChooseItemVC"];
[self.navigationController pushViewController:civc animated:YES];
}
The best way to remove all user default vlaues are as follows :
Swift code:
UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)
UserDefaults.standard.synchronize()
Objective C
NSString *strIdentifier = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:strIdentifier];;
[[NSUserDefaults standardUserDefaults] synchronize];
Use following code to remove all existing data in user defaults, i am posting swift code, convert this to objective-c.
if let bundleID = Bundle.main.bundleIdentifier {
UserDefaults.standard.removePersistentDomain(forName: bundleID)
}
To remove use this
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
[[NSUserDefaults standardUserDefaults] synchronize];
To remove you data from NSUserDefaults
[[NSUserDefaults standardUserDefaults] removeObjectForKey:#"AppleLanguages"];
For remove data from NSUserDefaults Try this:
NSString *AppDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:AppDomain];
Before explaining the issue, I want to mention I have already tried solutions from these questions:
Xcode not building app with changes incorporated
Why can't I delete files from my XCode project?
XCode simulator is not displaying latest changes
I have archived my app and it is now submitted in the App Store, but now I cannot make the changes I need in order to provide sound updates. The app provides statistics for different topics, as well as MLA/APA citations and a web view of that source. The code is structured this way:
A TopicViewController.m holds NSString variables for each statistic, citation, and source URL. IBActions related to specific topic UIButtons, like Cybersecurity for example, set the content of each NSString variable. Finally, I save the data for all stats, citations and URLs in NSUserDefaults and synchronize them. THESE IBACTIONS ARE WHERE I ADD NEW CONTENT.
sample code (the actual number of strings is very very large):
#implementation StatsViewController
NSString *cybersecStatistic1;
NSString *cybersecStatistic2;
NSString *cybersecStatistic3;
NSString *cybersecStatistic1CitationMLA;
NSString *cybersecStatistic1CitationAPA;
NSString *cybersecStatistic2CitationMLA;
NSString *cybersecStatistic2CitationAPA;
NSString *cybersecStatistic3CitationMLA;
NSString *cybersecStatistic3CitationAPA;
NSString *cybersecStatistic1Source;
NSString *cybersecStatistic2Source;
NSString *cybersecStatistic3Source;
-(IBAction)cybersecurityGo:(id)sender {
cybersecStatistic1 = #"\"In 2015, nearly 20% of global companies implemented a cybersecurity budget between $1 million and $4.9 million.\" (PricewaterhouseCoopers survey)";
cybersecStatistic2 = #"The average annual number of cybersecurity incidents is 80-90 million. There was a 38% increase in such incidents from 2014-2015.";
cybersecStatistic3 = #"USA: Over 36% of people who share passwords have shared the password associated with their banking account.";
cybersecStatistic1CitationAPA = #"Penguin Strategies. (2016, January 17). Top Cybersecurity Statistics for 2016 - Cyber Security Marketing Blog. Retrieved April 16, 2016, from http://www.marketingcyber.com/2016-cybersecurity-statistics/";
cybersecStatistic2CitationAPA = #"Smith, C. (2016, January 20). 34 Amazing Cybersecurity Statistics. Retrieved April 16, 2016, from http://expandedramblings.com/index.php/cybersecurity-statistics/";
cybersecStatistic3CitationAPA = #"Norton by Symantec. (1995-2016). Norton Cybersecurity Insights Report. Retrieved April 16, 2016, from https://us.norton.com/cyber-security-insights";
cybersecStatistic1CitationMLA = #"\"Top Cybersecurity Statistics for 2016 - Cyber Security Marketing Blog.\"Cyber Security Marketing Blog. Penguin Strategies, 17 Jan. 2016. Web. 16 Apr. 2016.";
cybersecStatistic2CitationMLA = #"Smith, Craig. \"34 Amazing Cybersecurity Statistics.\" DMR. DMR, 20 Jan. 2016. Web. 16 Apr. 2016.";
cybersecStatistic3CitationMLA = #"\"Norton Cybersecurity Insights Report.\" 2016. Norton by Symantec, 1995-2016. Web. 16 Apr. 2016.";
cybersecStatistic1Source = #"http://www.marketingcyber.com/2016-cybersecurity-statistics/";
cybersecStatistic2Source = #"http://expandedramblings.com/index.php/cybersecurity-statistics/";
cybersecStatistic3Source = #"https://us.norton.com/cyber-security-insights";
[[NSUserDefaults standardUserDefaults] setObject: cybersecStatistic1 forKey:#"statistic1"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults] setObject: cybersecStatistic2 forKey:#"statistic2"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults] setObject: cybersecStatistic3 forKey:#"statistic3"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults] setObject: cybersecStatistic1CitationMLA forKey:#"statistic1CitationMLA"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults] setObject: cybersecStatistic1CitationAPA forKey:#"statistic1CitationAPA"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults] setObject: cybersecStatistic2CitationMLA forKey:#"statistic2CitationMLA"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults] setObject: cybersecStatistic2CitationAPA forKey:#"statistic2CitationAPA"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults] setObject: cybersecStatistic3CitationMLA forKey:#"statistic3CitationMLA"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults] setObject: cybersecStatistic3CitationAPA forKey:#"statistic3CitationAPA"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults] setObject: cybersecStatistic1Source forKey:#"statistic1Source"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults] setObject: cybersecStatistic2Source forKey:#"statistic2Source"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults] setObject: cybersecStatistic3Source forKey:#"statistic3Source"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Tapping a topic button takes you to the next screen, StatsViewController. It's implementation file receives the NSUserDefaults and displays the appropriate statistics. IBActions related to each statistic UIButton set the “route” for the next screen in order to display the correct citations. THIS IS WHERE SOMETHING SEEMS TO GO WRONG BECAUSE THE CITATIONS ARE DISPLAYED FOR THE LAST STAT I VIEWED (NEVER THE NEWLY ADDED STAT'S CITATION)--> I FIXED THIS ISSUE BEFORE BY CHANGING MY ViewDidLoad to a ViewWillLayoutSubviews in CitationViewController which I will explain next.
#implementation StatsViewController
NSString *whichStat;
NSString *strStat1;
NSString *strStat2;
NSString *strStat3;
-(IBAction)stat1Go:(id)sender {
whichStat = #"stat1Route";
[[NSUserDefaults standardUserDefaults] setObject:whichStat forKey:#"activeStat"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
-(IBAction)stat2Go:(id)sender {
whichStat = #"stat2Route";
[[NSUserDefaults standardUserDefaults] setObject:whichStat forKey:#"activeStat"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
-(IBAction)stat3Go:(id)sender {
whichStat = #"stat3Route";
[[NSUserDefaults standardUserDefaults] setObject:whichStat forKey:#"activeStat"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
-(void)viewWillAppear:(BOOL)animated {
whichStat = nil;
strStat1 = nil;
strStat2 = nil;
strStat3 = nil;
strStat1 = [[NSUserDefaults standardUserDefaults] stringForKey:#"statistic1"];
strStat2 = [[NSUserDefaults standardUserDefaults] stringForKey:#"statistic2"];
strStat3 = [[NSUserDefaults standardUserDefaults] stringForKey:#"statistic3"];
[_stat1 setTitle:strStat1 forState:UIControlStateNormal];
[_stat2 setTitle:strStat2 forState:UIControlStateNormal];
[_stat3 setTitle:strStat3 forState:UIControlStateNormal];
if ([strStat1 isEqual: #"more stats to come"]) {
_stat1.enabled = false;
}
else {
_stat1.enabled = true;
}
if ([strStat2 isEqual: #"more stats to come"]) {
_stat2.enabled = false;
}
else {
_stat2.enabled = true;
}
if ([strStat3 isEqual: #"more stats to come"]) {
_stat3.enabled = false;
}
else {
_stat3.enabled = true;
}
Tapping a statistic button take you to the CitationViewController, which displays the APA and MLA citations. THE CITATIONS FOR NEWLY ADDED STRINGS (SINCE APP STORE SUBMISSION) ARE NOT CORRECTLY LOADED IN THE ViewWillLayoutSubviews.
#implementation CiteViewController
NSString *citeStatPath;
NSString *citeUsingMLA;
NSString *citeUsingAPA;
NSString *sourceWebSite;
-(void)viewWillLayoutSubviews {
citeStatPath = [[NSUserDefaults standardUserDefaults] stringForKey:#"activeStat"];
if ([citeStatPath isEqualToString: #"stat1Route"]) {
citeUsingMLA = [[NSUserDefaults standardUserDefaults] stringForKey:#"statistic1CitationMLA"];
citeUsingAPA = [[NSUserDefaults standardUserDefaults] stringForKey:#"statistic1CitationAPA"];
[_citeMLA setTitle:citeUsingMLA forState:UIControlStateNormal];
[_citeAPA setTitle:citeUsingAPA forState:UIControlStateNormal];
}
else if ([citeStatPath isEqualToString:#"stat2Route"]) {
citeUsingMLA = [[NSUserDefaults standardUserDefaults] stringForKey:#"statistic2CitationMLA"];
citeUsingAPA = [[NSUserDefaults standardUserDefaults] stringForKey:#"statistic2CitationAPA"];
[_citeMLA setTitle:citeUsingMLA forState:UIControlStateNormal];
[_citeAPA setTitle:citeUsingAPA forState:UIControlStateNormal];
}
else {
citeUsingMLA = [[NSUserDefaults standardUserDefaults] stringForKey:#"statistic3CitationMLA"];
citeUsingAPA = [[NSUserDefaults standardUserDefaults] stringForKey:#"statistic3CitationAPA"];
[_citeMLA setTitle:citeUsingMLA forState:UIControlStateNormal];
[_citeAPA setTitle:citeUsingAPA forState:UIControlStateNormal];
}
}
Tapping a citation button takes you to the UIWebView which gets the URL from an NSUserDefault established and saved in TopicViewController.m. THE CORRECT WEBSITE ALSO DOES NOT APPEAR.
#implementation SourceViewController
NSString *srcStatPath;
NSString *webSite;
-(void)viewWillAppear:(BOOL)animated {
srcStatPath = [[NSUserDefaults standardUserDefaults] stringForKey:#"activeStat"];
if ([srcStatPath isEqualToString: #"stat1Route"]) {
webSite = [[NSUserDefaults standardUserDefaults] stringForKey:#"statistic1Source"];
}
else if ([srcStatPath isEqualToString:#"stat2Route"]) {
webSite = [[NSUserDefaults standardUserDefaults] stringForKey:#"statistic2Source"];
}
else {
webSite = [[NSUserDefaults standardUserDefaults] stringForKey:#"statistic3Source"];
}
NSURL *url = [NSURL URLWithString:webSite];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[_source loadRequest:request];
}
This issue occurs on iPhone Simulator and my own iOS device (iPhone 6- version 9.3.2).
Thank you in advance for the help. I am quite stuck!
I have aUILabel which I want to update.
If I will login with a user name then the UILabel will be updated with that user name,which it is doing correctly and storing the value.
Now I want whenever i will logout then the UILabel text should return the previous value which it stored deleting the new value.
Can you please help me with this.
After login I have updated my UiLabel text like this
-(void)updateUserName:(NSNotification*)noti
{
NSDictionary* userInfo = [noti userInfo];
self.user.firstName = [userInfo valueForKey:#"FirstName"];
self.user.lastName = [userInfo valueForKey:#"LastName"];
if (self.user.firstName != nil && self.user.firstName.length > 0 && self.user.lastName.length > 0)
{
self.userName.text = [NSString stringWithFormat:#"%# %#",self.user.firstName, self.user.lastName];
}
}
then after logout I need to retrieve the old data of UiLabel.
NSString *userName =[NSString stringWithFormat:#"%# %#",self.user.firstName, self.user.lastName];
[[NSUserDefaults standardUserDefaults] setObject:valueToSave forKey:#"preferenceName"];
[[NSUserDefaults standardUserDefaults] synchronize];
save username to NSUserdefaults
NSString *userName = [[NSUserDefaults standardUserDefaults]
stringForKey:#"preferenceName"];
Take the username whenever you want and assign it to UILabel name
whenever the user got Logout clear the NSuserdefaults
NSString *userName =#"";
[[NSUserDefaults standardUserDefaults] setObject:valueToSave forKey:#"preferenceName"];
[[NSUserDefaults standardUserDefaults] synchronize];
This question already has answers here:
Clearing NSUserDefaults
(15 answers)
Closed 7 years ago.
I am using NSUserDefaults lots of time in my app to store some values, but on "refresh button" i want to clear all stored values, Is there any way to clear all NSUserDefaults values?
You can remove all stored value using below code see here for more details
- (void)removeUserDefaults
{
NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
NSDictionary * dict = [userDefaults dictionaryRepresentation];
for (id key in dict) {
[userDefaults removeObjectForKey:key];
}
[userDefaults synchronize];
}
Or in shortest way
[[NSUserDefaults standardUserDefaults] setPersistentDomain:[NSDictionary dictionary] forName:[[NSBundle mainBundle] bundleIdentifier]];
Swift
let defaults = UserDefaults.standard
defaults.dictionaryRepresentation().keys.forEach { (key) in
defaults.removeObject(forKey: key)
}
You can clear your user defaults by using following statements -
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
You can call a selector on the refresh button and keep the above statements in it, as-
- (void) refreshUserDefaults
{
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
}
I use this code to save:
[[NSUserDefaults standardUserDefaults] setValue:#"vruch" forKey:#"nastoikaIP"];
[[NSUserDefaults standardUserDefaults] synchronize];
and this code to load:
NSString* automanual = [[NSUserDefaults standardUserDefaults]
valueForKey:#"nastroikaIP"];
if ([automanual isEqualToString:#"vruch"]) {
autovruch.selectedSegmentIndex = 1;
[self obnovittext];
}
You should not use the method setValue: (from the NSKeyValueCoding protocol) but setObject: (from the NSUserDefaults class) to store the string.
[[NSUserDefaults standardUserDefaults] setObject:#"vruch" forKey:#"nastroikaIP"];
[[NSUserDefaults standardUserDefaults] synchronize];
You can retrieve the string using the method stringForKey:
NSString* automanual = [[NSUserDefaults standardUserDefaults] stringForKey:#"nastroikaIP"];
Finally, note that it is generally better to define constants for the keys you use in NSUserDefaults to avoid any mistyping errors, which may be hard to debug when they happen.
Edit
It looks like you already did a mistyping error nastoikaIP != nastroikaIP. Notice the missing/extra r letter.
Your saving a string so you need to setObject rather than setValue
[[NSUserDefaults standardUserDefaults] setObject:#"vruch" forKey:#"nastoikaIP"];
[[NSUserDefaults standardUserDefaults] synchronize];
and change it for the loading aswell
NSString* automanual = [[NSUserDefaults standardUserDefaults] objectForKey:#"nastroikaIP"];
if ([automanual isEqualToString:#"vruch"]) {
autovruch.selectedSegmentIndex = 1;
[self obnovittext];
}