Closest one I found is: https://stackoverflow.com/questions/4778932/cocoa-app-not-receiving-all-dropped-files-in-applicationopenfiles
But it hasn't been answered.
My Problem is this,
So let's say I am dropping 4 files on my dock application:
test.xls
test.rtf
test.jpg
test.pdf
If I go debug my program it shows this:
Debug log
As you can see the .jpg file is not in there.
This also happens for: .py, other image types, .txt files
I have found out that if I drop files only from that group (.py .jpg .txt) then it recognizes all of them.
My Info.plist looks like this:
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEplistPUBLIC"-//Apple//DTDPLIST1.0//EN""http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plistversion="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>AllFiles</string>
<key>CFBundleTypeIconFile</key>
<string>application.icns</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.item</string>
</array>
</dict>
</array>
I don't know where the error is in here, maybe it's a bug? Or did I configure my info.plist wrong?
I hope someone can help me and thank you all in advance!
I encountered the same problem and here is how I solved it:
#property (strong) NSMutableArray *openFilesList;
#property (strong) NSTimer *openFilesTimer;
...
#synthesize openFilesList;
#synthesize openFilesTimer;
...
-(void)init {
openFilesList = [[NSMutableArray alloc] init];
openFilesTimer = nil;
}
-(void)application:(NSApplication *)sender openFiles:(NSArray *)filenames {
if (openFilesTimer) {
[openFilesTimer invalidate];
}
[openFilesList addObjectsFromArray:filenames];
openFilesTimer = [NSTimer scheduledTimerWithTimeInterval:0.2f
target:self
selector:#selector(processOpenFiles)
userInfo:nil
repeats:NO];
}
-(void)processOpenFiles {
NSArray *filenames = [openFilesList copy];
openFilesTimer = nil;
[openFilesList removeAllObjects];
// Do your processing with filenames
}
set in info.plist like this
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>*</string>
</array>
<key>CFBundleTypeName</key>
<string>Files</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>public.data</string>
</array>
</dict>
</array>
and use this method in AppDelegate.m
-(void)application:(NSApplication *)sender openFiles:(NSArray *)fileList{
// use fileList array
}
-(BOOL)application:(NSApplication *)sender openFile:(NSString *)filename{
return YES;
}
I want to add into my plist file present in "prefPlist" variable some key with its relative type.
The example content must be:
<dict>
<key>App Version</key>
<string>Beta 1</string>
<key>Configuration Type</key>
<integer>7</integer>
<key>Creation Date</key>
<date>27 04 2013, 03:00</date>
<key>Want some milk?</key>
<true/>
</dict>
The first key must have the string type, the second the integer type, the third the date time type and the fourth a boolean value.
How can I do this?
<key>prefList</key>
<array>
<string>string</string>
<string>integer</string>
<string>date</string>
<string>boolean</string>
</array>
Matteo:
You should be able to read the NSDictionary and NSMutableDictionary messages supported HERE
In the meantime, it seems as though you want to use, as an example:
NSString *source = [[NSBundle mainBundle] pathForResource:#"FileName ofType:#"plist"];
myDictionary = [[[NSDictionary alloc] initWithContentsOfFile:source] mutableCopy];
This of course assumes that the plist is in your bundle. Use FileManager to your sandbox documents or elsewhere to get the right location before loading with dictionary.
Frank
I am writing a tweak for jailbroken iOS devices and I want to be able to write this NSString "bundleID" and the integer created in my code to a plist file. The code below can do this, however, it only does this once and doesn't allow me to write it to the plist multiple times. I want to do this because the bundleID changes and should also be written to the plist. Basically what I want to do is when an app is launch the bundle id for that app (com.apple.mobilesafari) is written as the key in my plist. I then have code to work add 1 to the value every time the app is opened. So for example if I opened mobile safari four times the plist should look 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>com.apple.mobilesafari</key>
<integer>4</integer>
<key>customText</key>
<false/>
<key>enabled</key>
<false/>
</dict>
</plist>
However, when I launch mobile safari four times it stays as...
<key>com.apple.mobilesafari</key> <integer>1</integer>
I also want the bundleID saved for every app. So if I open safari then contacts I want both in my plist. For example...
<?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>com.apple.mobilesafari</key>
<integer>1</integer>
<key>customText</key>
<false/>
<key>enabled</key>
<false/>
</dict>
<dict>
<key>com.apple.contacts</key>
<integer>1</integer>
<key>customText</key>
<false/>
<key>enabled</key>
<false/>
</dict>
</plist>
Here is my objective-c code...
%hook SBApplicationIcon
-(void)launch
{
// Return original method
%orig;
// Get Bundle ID
NSString* bundleID = [self leafIdentifier];
// Print that badboy!
NSLog(#"Bundle ID: %# ",bundleID);
// Set up plist
NSMutableDictionary *launches = [[NSMutableDictionary alloc] initWithContentsOfFile:#"/var/mobile/Library/Preferences/com.bengerard.ipslider.plist"];
// Check plist exists
NSString *pathToFile = #"/var/mobile/Library/Preferences/com.bengerard.apppop.plist";
BOOL isFile = [[NSFileManager defaultManager] fileExistsAtPath:pathToFile isDirectory:NO];
if(isFile)
{
// Counting
int count = [[launches objectForKey:bundleID] intValue];
count++;
// Write number of launches to plist
[launches setObject:[NSNumber numberWithInt:count] forKey:bundleID];
//[launches insertObject:[NSNumber numberWithInt:count] forKey:bundleID];
[launches writeToFile:#"/var/mobile/Library/Preferences/com.bengerard.apppop.plist" atomically:YES];
}
else {
//The file doesn't exit.
}
// [bundleID release];
// [pathToFile release];
// [launches release];
}
%end
P.S: I am also using theos by DHowett to compile my tweak.
Edit: Realised my two plists are different. Probably causing my problem. I will test later
I am writing an app that copies a plist into the docsdir and then reads it into a mutable array. The code below, however, returns a count of 0 for the array. The line with the dictionary log, however, returns the correct items. I have also verified that the file is being copied to the docsdir.
-(NSString *)docsDir {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *listPath = [[self docsDir]stringByAppendingPathComponent:#"list.plist"];
if (![[NSFileManager defaultManager]fileExistsAtPath:listPath]) {
[[NSFileManager defaultManager]copyItemAtPath:[[NSBundle mainBundle]pathForResource:#"list" ofType:#"plist"] toPath:listPath error:nil];
NSLog(#"Chicken");
}
NSLog(#"%#", [NSDictionary dictionaryWithContentsOfFile:listPath]);
_array = [NSArray arrayWithContentsOfFile:listPath];
NSLog(#"Count: %i", [_array count]);
}
- (void)viewDidUnload
{
[super viewDidUnload];
/ / Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
Usually this is because by default root element in plist files is a Dictionary.
Right click and select Open as Source Code, your file may look 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>foo</key>
<array>
<string>foo1</string>
<string>foo2</string>
<string>foo3</string>
</array>
</dict>
</plist>
where the root element is a dict, change it to:
<?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">
<array>
<string>foo1</string>
<string>foo2</string>
<string>foo3</string>
</array>
</plist>
where the root element is an array. You can now edit as usual.
Open the plist file with Xcode.
Just find the 'key' at the top left corner and Type of the plist.
Make sure the Type is Array.
I think your plist is a dictionary that contains an array.
Try this
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:listPath]
NSArray *array = [dict objectForKey:#"key"];
Plists are usually saved a dictionaries:
Here's an example :
<dict>
<key>tiltingAnim</key>
<dict>
<key>filenamePrefix</key>
<string>radar_</string>
<key>delay</key>
<real>0.25</real>
<key>animationFrames</key>
<string>1,2,3,4,5,5,4,3,2,1,2,3,4,5</string>
</dict>
<key>takingAHitAnim</key>
<dict>
<key>filenamePrefix</key>
<string>radar_</string>
<key>delay</key>
<real>0.1</real>
<key>animationFrames</key>
<string>5,5,7,8,8</string>
</dict>
<key>blowingUpAnim</key>
<dict>
<key>filenamePrefix</key>
<string>radar_</string>
<key>delay</key>
<real>0.2</real>
<key>animationFrames</key>
<string>5,6,7,8,9,10,11,12,13,14,15,16,17</string>
</dict>
<key>transmittingAnim</key>
<dict>
<key>filenamePrefix</key>
<string>radar_</string>
<key>delay</key>
<real>0.3</real>
<key>animationFrames</key>
<string>5,6,5,6,5,6,5</string>
</dict>
</dict>
Now, there are 2 solutions to your question.
Either get the contents into a dictionary then take out the array for a specific key.
Open up the plist with a text editor and change the root key into then change root into . If your plist is static and in the bundle resources then you could do this but if it's a plist generated by your code then i wouldn't recommend this.
Scenario:
I like to define the allowed file types (content types) in the Info.plist file of my Cocoa application. Therefore, I added them like the following example shows.
# Extract from Info.plist
[...]
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>public.png</string>
<key>CFBundleTypeIconFile</key>
<string>png.icns</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSIsAppleDefaultForType</key>
<true/>
<key>LSItemContentTypes</key>
<array>
<string>public.png</string>
</array>
</dict>
[...]
Further, my application allows to open files using an NSOpenPanel. The panel allows to set the allowed file types through the following selector: setAllowedFileTypes:. The documentation states that UTI can be used.
The file type can be a common file extension, or a UTI.
A custom solution:
I wrote the following helper method to extract the UTI from the Info.plist file.
/**
Returns a collection of uniform type identifiers as defined in the plist file.
#returns A collection of UTI strings.
*/
+ (NSArray*)uniformTypeIdentifiers {
static NSArray* contentTypes = nil;
if (!contentTypes) {
NSArray* documentTypes = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleDocumentTypes"];
NSMutableArray* contentTypesCollection = [NSMutableArray arrayWithCapacity:[documentTypes count]];
for (NSDictionary* documentType in documentTypes) {
[contentTypesCollection addObjectsFromArray:[documentType objectForKey:#"LSItemContentTypes"]];
}
contentTypes = [NSArray arrayWithArray:contentTypesCollection];
contentTypesCollection = nil;
}
return contentTypes;
}
Instead of [NSBundle mainBundle] also CFBundleGetInfoDictionary(CFBundleGetMainBundle()) can be used.
Questions:
Do you know a smarter way to extract the content type information
from the Info.plist file? Is there a Cocoa-build-in function?
How do you deal with the definition of folders that can contained
there, e.g. public.folder?
Note:
Throughout my research, I found this article quite informative: Simplifying Data Handling with Uniform Type Identifiers.
Here is how I read information from a plist (it can be the info.plist or any other plist you have in you project provided you set the correct path)
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
NSString *fullPath = [NSString stringWithFormat:#"%#/path/to/your/plist/my.plist", resourcePath];
NSData *plistData = [NSData dataWithContentsOfFile:fullPath];
NSDictionary *plistDictionary = [NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListImmutable format:0 errorDescription:nil];
NSArray *fileTypes = [plistDictionary objectForKey:#"CFBundleDocumentTypes"];