Having problem to fetch/save settings.bundle value by code - iphone

I'm facing difficulty in fetching/saving setting bundle preference file by code. I'm a beginner.
I just need to fetch/save default value of key "VERSION 2" by code. I want to use the value of this key for my controllers to work. Thanks.
This data is in:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "apple.com/DTDs/PropertyList-1.0.dtd">;
<plist version="1.0">
<dict>
<key>DefaultValue</key>
<string>Karachi</string>
<key>Key</key>
<string>version2</string>
<key>Title</key>
<string>VERSION</string>
<key>Type</key>
<string>PSTitleValueSpecifier</string>
</dict>
</plist>

You do that by simply doing the following
NSUserDefaults *prefs - [NSUserDefaults standardUserDefaults]; //considering it's in the default settings.bundle
NSString *versionString = [prefs stringForKey:#"Key"];
You can use the following methods to get defaults
arrayForKey
boolForKey
dataForKey
dictionaryForKey
floatForKey
integerForKey
objectForKey
stringArrayForKey
stringForKey
doubleForKey
URLForKey

Related

Change App icon programmatically

I have seen this application on iTunes, it is creating custom icon in iphone. In my application I also want to change icon , specifically what I want to do is in my icon there is one label and programmatically I want to change the value of label.
From the video tutorial of the app, it seems like all they're doing is they created a web page with favicon of the custom icon that you created, then the user would tap "Add To Home Screen" to add the custom web page to the home screen. That should be enough to get you going.
It is possible to change appIcon from iOS 10.3.
Swift 3:
if UIApplication.shared.supportsAlternateIcons{
UIApplication.shared.setAlternateIconName("icon2", completionHandler: { (error) in
print(error ?? "")
})
}
Objective C:
[[UIApplication sharedApplication] setAlternateIconName:#"icon2" completionHandler:^(NSError * _Nullable error) {
//NSLog(#"Error...");
}];
set supportsAlternateIcon to Yes in info.plist. Both primary and secondary icons should be added in CFBundleIcons key of your app's Info.plist file.
//Info.plist
<key>CFBundleIcons</key>
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>Icon1</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>icon1</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>Icon2</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>icon2</string>
</array>
</dict>
</dict>
</dict>
References:
Apple Document: setAlternateIconName(_:completionHandler:)
How to change your app icon dynamically with setAlternateIconName()
This is not possible. Unless your app is of Newsstand category. For newsstand app, change the icon using the code,
UIApplication *app = [UIApplication sharedApplication];
[app setNewsstandIconImage:newsstandImage];
Note: What #Enrico suggests is a different solution. Your app icon will still be there in home screen, a duplicate icon will be created. Which most of the users wont prefer.
Only my two cents.
Adding to plist directly is fine, the net effect is to have a "strange" value (IOS5...) in plist if seen visually in Xcode:
2) on simulator (Xcode 10 beta...) debug console on run you will see:
MobileGestalt.c:890: MGIsDeviceOneOfType is not supported on this platform.
but works
3) don't call directly in AppDelegate. if needed so, call it dispatched:
final func changeIcon(){
let name = "Icon1"
let icon = UIImage(named: name)
if UIApplication.shared.supportsAlternateIcons{
UIApplication.shared.setAlternateIconName(name, completionHandler: { (error) in
print(error ?? "ok")
})
}
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let when = DispatchTime.now() + 1
DispatchQueue.main.asyncAfter(deadline: when) {
self.changeIcon()
}
return true
}
.....
4) note: icon name is the symbolic name you put in key in upper level, so for example:
<key>CFBundleIcons</key>
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>Icon1</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>logo2_120x120</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>Icon2</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>logo3_120x120</string>
</array>
</dict>
</dict>
</dict>
and do NOT add #2x or similar in plist.

UIActivityViewController Attaching File - Wrong File Type

I am using UIActivityViewController to share the contents of my app in both a pure text format as well as a custom filetype that can be opened on other devices. The file attaches to the email created with no problem, however it is getting the wrong filetype associated with it. The custom file that is created is an NSDictionary that uses writeToURL.
NSMutableDictionary *theBinder = [NSMutableDictionary dictionaryWithObjects:#[#"test object"] forKeys:#[#"test key"]];
NSURL *binderURL = [NSURL fileURLWithPath:[[self cachesDirectory] stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.mtgbinder", [[NSUserDefaults standardUserDefaults] valueForKey:#"Current Binder"]]]];
[theBinder writeToURL:binderURL atomically:YES];
NSArray *activityItems = [NSArray arrayWithObjects:binderContents, binderURL, nil];
UIActivityViewController *shareView = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
shareView.excludedActivityTypes = #[UIActivityTypePostToTwitter, UIActivityTypePostToWeibo];
[self presentViewController:shareView animated:YES completion:nil];
The file is correctly created as expected:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>test key</key>
<string>test object</string>
</dict>
</plist>
However, when I then try to open that file from another app, the extension gets changed to csv. My app is able to open and export both my mtgbinder filetypes and also CSV. Am I doing something wrong with the UTExportedTypeDeclarations?
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeIdentifier</key>
<string>com.chichapps.MTG-Binder.csv</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>csv</string>
<key>public.mime-type</key>
<string>application/MTG-Binder</string>
</dict>
</dict>
<dict>
<key>UTTypeIdentifier</key>
<string>com.chichapps.MTG-Binder.mtgbinder</string>
<key>UTTypeDescription</key>
<string>MTG Binder Document</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.mime-type</key>
<string>application/MTG-Binder</string>
<key>public.filename-extension</key>
<string>mtgbinder</string>
</dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
</dict>
</array>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>MTG Binder Document</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.chichapps.MTG-Binder.csv</string>
<string>com.chichapps.MTG-Binder.mtgbinder</string>
</array>
</dict>
</array>
Thanks for any help and suggestions.
I figured out what to do. I had to change:
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeIdentifier</key>
<string>com.chichapps.MTG-Binder.csv</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>csv</string>
<key>public.mime-type</key>
<string>application/MTG-Binder</string>
</dict>
</dict>
To:
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeIdentifier</key>
<string>com.chichapps.MTG-Binder.csv</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>csv</string>
<key>public.mime-type</key>
<string>application/csv</string> //Changing this fixed the problem
</dict>
</dict>

Exclusive iOS UTI

I'm trying to create / export an exclusive UTI type for my iOS app (very similar to how Instagram exclusively handles the UTI com.instagram.exclusivegram).
Basically, I want com.photoapp.photo to be what an app can use if they want to be able to open the photo in any app registered for taking photos (similar to Instagram's com.instagram.photo). Then I want com.photoapp.exclusive to only be able to open in my app (similar to com.instagram.exclusivegram).
What I'm running into on my device is that even when using com.photoapp.exclusive, the UIDocumentController prompts me to open it in either PhotoApp or DropBox where it should just be PhotoApp.
I have my app that registers the UTI as well as an example app I'm using to check on the opening ability. The code I'm using in the example app is below:
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:#"photoapp://"]]) {
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:#"derp.png"], 1.0);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *fullPathToFile = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"photoapp.pae"];
[imageData writeToFile:fullPathToFile atomically:NO];
interactionController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:[NSString stringWithFormat:#"file://%#", fullPathToFile]]];
interactionController.UTI = #"com.photoapp.exclusive";
interactionController.delegate = self;
[interactionController presentOpenInMenuFromRect:self.view.frame inView:self.view animated:YES];
}
And here is what I have in my plist file for my app:
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeDescription</key>
<string>Exclusive PhotoApp Photo</string>
<key>UTTypeConformsTo</key>
<array>
<string>com.photoapp.photo</string>
</array>
<key>UTTypeIdentifier</key>
<string>com.photoapp.exclusive</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>pae</string>
</dict>
</dict>
<dict>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>pa</string>
</dict>
<key>UTTypeIdentifier</key>
<string>com.photoapp.photo</string>
<key>UTTypeDescription</key>
<string>PhotoApp Photo</string>
<key>UTTypeConformsTo</key>
<array>
<string>public.png</string>
<string>public.jpeg</string>
</array>
</dict>
</array>
<key>UIFileSharingEnabled</key>
<true/>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>LSItemContentTypes</key>
<array>
<string>com.photoapp.exclusive</string>
<string>com.photoapp.photo</string>
</array>
<key>CFBundleTypeName</key>
<string>Photo</string>
<key>LSHandlerRank</key>
<string>Default</string>
</dict>
</array>
As soon as you specify a UTI such as public.png or public.jpeg, all apps that specify that they can open files of these types will be able to open your file. So, if you do not specify any type conformance at all in your com.photoapp.exclusive UTI, no apps will appear to support it.

iPhone: Can't access all value from .plist file

I have a pretty simple root.plist file that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>StringsTable</key>
<string>Root</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>Title</key>
<string>User Info</string>
</dict>
<dict>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>Title</key>
<string>Username</string>
<key>Key</key>
<string>username_preference</string>
<key>DefaultValue</key>
<string></string>
<key>IsSecure</key>
<false/>
<key>KeyboardType</key>
<string>Alphabet</string>
<key>AutocapitalizationType</key>
<string>None</string>
<key>AutocorrectionType</key>
<string>No</string>
</dict>
<dict>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>Title</key>
<string>Password</string>
<key>Key</key>
<string>password_preference</string>
<key>DefaultValue</key>
<string></string>
<key>IsSecure</key>
<true/>
<key>KeyboardType</key>
<string>Alphabet</string>
<key>AutocapitalizationType</key>
<string>None</string>
<key>AutocorrectionType</key>
<string>No</string>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>Title</key>
<string>Application Info</string>
</dict>
<dict>
<key>Type</key>
<string>PSTitleValueSpecifier</string>
<key>Title</key>
<string>Version</string>
<key>Key</key>
<string>api_version_preference</string>
<key>DefaultValue</key>
<string>2.0</string>
<key>Value</key>
<string>2.0</string>
</dict>
</array>
</dict>
</plist>
All the fields is shown when navigating to the relevant settings page in the iphone's settings application, but i can't access api_version_preference from my application.
I've tried to print out the .plist file as a dictionary and I only see the values from the username/password fields, so i'm probably doing something wrong. Here is what I use when printing the data:
NSLog(#"defs: %#", [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]);
Can anyone help? :)
You forgot to supply defaults to NSUserDefaults. NSUserDefaults doesn't store the setting if you haven't changed (ie saved) it.
create a NSDictionary of default values and set it with [[NSUserDefaults standardUserDefaults] registerDefaults:userDefaultsDefaults];
like this:
NSDictionary *userdefaultsDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
#"2.0", #"api_version_preference",
nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:userdefaultsDefaults];
do this with all the settings you use from NSUserDefaults

Changing Data in a Plist

Hey, alright so I have a .plist that looks like;
<plist version="1.0">
<dict>
<key>Item 0</key>
<dict>
<key>Name</key>
<string>Jero</string>
<key>Initiative</key>
<integer>0</integer>
<key>EditThis</key>
<false/>
</dict>
</dict>
</plist>
In the app I have it so that when one of the rows (The data is put in a UITableView) is selected it pushes to a new view controller. I would like also to set the 'EditThis' boolean to yes, so the edit view controller can learn which to edit. However I can't seem to figure out how to change the value. Any help is much appreciated.
Load the plist into a mutable dictionary:
NSMutableDictionary *plist = [NSMutableDictionary dictionaryWithContentsOfFile:#"file.plist"];
[plist setObject:[NSNumber numberWithBool:YES] forKey:#"EditThis"];
[plist writeToFile:#"file.plist" atomically:YES];