How would I get the other app's version from mac app - objective-c

How would I get the other app's version.
I can use [NSWorkspace fullPathForApplication:(NSString *)appName] to get app's path, can I get the app's info?

There's several ways you can accomplish this — I usually take the shortest route using NSBundle in addition to CFBundleversion:
NSBundle *appBundle = [NSBundle bundleWithPath:appPath];
NSString *bundleVersion = [appBundle objectForInfoDictionaryKey:#"CFBundleVersion"];

Once you have the full path to the Application, you can read the Contents/Info.plist file and look at the CFBundleShortVersionString value.
Something like this:
NSString *appPath = [NSWorkspace fullPathForApplication:appName];
NSString *plistPath = [appPath stringByAppendingPathComponent:#"Contents/Info.plist"];
NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:plistPath];
NSString *version = plist[#"CFBundleShortVersionString"];

Related

pathForResource ofType returns nil

here is the code i am working with.
NSString* path = [[NSBundle mainBundle] pathForResource:#"file" ofType:#"plist"];
if(path == nil)
{
NSLog(#"file not found");
}
when i run this it prints file not found in the console.
my file.plist is in the supporting files folder in my cocoa project. where does mainBundle look for files at exactly. this is stumping me quite a bit. i get that it looks for the .app file, but when developing the app where doe mainBundle look?
pathForResource:ofType: only looks in the Resources folder (and localised folders). If you are placing files into dedicated folders in the bundle then you need to use pathForResource:ofType:inDirectory: and supply the directory name.
If the NSBundle you found is what you wanted through :
NSBundle *yourTargetBundle = [NSBundle mainBundle];
or
NSBundle *yourTargetBundle = [NSBundle bundleWithURL:[[NSBundle mainBundle]
URLForResource:#"YourCustomBundleName" withExtension:#"bundle"]];
And get the nil result use function: pathForResource: ofType:. Then you can log the paths of resource under yourTargetBundle:
// Given that your resource type is .png and have no sub dir
NSArray *resoursePaths = [yourTargetBundle pathsForResourcesOfType:#"png" inDirectory:nil];
NSLog(#"resoursePaths == %#",resoursePaths);
it will log all the resources path of type png. You can get the image object use:
targetImg = [[UIImage alloc] initWithContentsOfFile:#"OnePngPathYouChose"];
I think the above approach is one way to resolve the return nil situation.

- [NSBundle pathForResource:ofType] works differently for directories on 10.7 and 10.8

I had this code
NSString *path = #"foo/bar"; // Note this is a directory, not a file!
NSString *pathInBundle = [[NSBundle mainBundle] pathForResource:path ofType:nil];
It was working fine on 10.8 (returning the path found in the bundle) but returned nil in 10.7.
This solution works in both OSes):
[[NSBundle mainBundle] pathForResource:[[path pathComponents] lastObject]
ofType:nil
inDirectory:[path stringByDeletingLastPathComponent]];
NOTE: lastObject and stringByDeletingPathComponents are nice in this case because not crashing with an index out of bound, but rather returning nil!
Originally I thought that this would make it, but it does NOT:
[[NSBundle mainBundle] pathForResource:nil ofType:nil inDirectory:path];
This returns the first element found in the path (a file or folder), which is totally not what I wanted.
I guess Apple "tweaked" the implementation of pathForResource:ofType: since 10.8 to make it work with directories as well, so depending on wether or not you still need to support 10.7, you know what you should use.
Maybe I'm missing something obvious, like an easier way of getting back a directory (again, in 10.7, since in 10.8 it's super easy like I state in the question).
The following should work for finding the path to any item in a subdirectory of the bundle, including the appropriate localised variant, in 10.6 -> 10.8 at least:
// long hand...
NSString *item = [path lastPathComponent]; // path/item -> item
NSString *itemBase = [item stringByDeletingPathExtension]; // base[.ext] -> base
NSString *itemExtension = [item pathExtension]; // base[.ext] -> ext or #""
NSString *pathDirectory = [path stringByDeletingLastPathComponent]; // path/item -> path
NSString *pathInBundle = [[NSBundle mainBundle] pathForResource:itemBase
ofType:itemExtension
inDirectory:pathDirectory];
The allowance for pathForResource: to be a path appears to be an (undocumented?) extension in 10.8; it would be best to avoid using it unless you find it is documented.

How do I copy a directory that is inside of my main bundle to an NSPasteBoard?

I have been tearing my hair trying different combinations of file paths and different types but basically what I am trying to do is copy a folder called "test" that is inside of my resources folder.
Copying folders onto the NSPasteBoard works when I give an absolute path (ex: /Users/dw/src/Menulet) but it doesn't work when I try using my mainBundle's resource path.
Here is the code I currently have:
NSString *resourceFolder = [[NSURL fileURLWithPath:[[NSBundle mainBundle]
resourcePath]] absoluteString];
NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
[pboard declareTypes:[NSArray arrayWithObject:NSURLPboardType] owner:nil];
NSString *SDKPathString = [[NSString alloc] initWithFormat:#"%#test/",
resourceFolder];
NSURL *SDKPathURL = [[NSURL alloc] initWithString:SDKPathString];
[pboard writeObjects:[NSArray arrayWithObject:SDKPathURL]];
The result is that it can't find the file:
__CFPasteboardIssueSandboxExtensionForPath: error for [/Users/dw/Library/Developer/Xcode/DerivedData/Menulet-bvwpfkjlcufhxubvaxubgnubtfgi/Build/Products/Debug/Menulet.app/Contents/Resources/test]
How can I copy the directory?
Edit:
My guess is that you're missing a '/' character when you do this:
NSString *SDKPathString = [[NSString alloc] initWithFormat:#"%#test/",
resourceFolder];
Indeed resourceFolder is a path, I usually use something like this instead:
NSString* SDKPathString= [resourceFolder stringByAppendingPathComponent: #"test"];
Even if in your case you could simply correct the error by putting a '/' character before "test".But I think this is more mnemonic.
Update
Isn't said that if you create a group Xcode also creates a folder. If you want to be sure that Xcode does so, create a folder with finder and drag it to the project. Check these options:
This way the folder is actually created, and also added to the bundle.
Update 2
You shouldn't try to move your directory inside the project folder to put into the right place, instead put it wherever you want in the bundle, provided that the directory is copied in the bundle.
Once did so, the bundle will manage everything for you. So just search the directory using:
- (NSString *)pathForResource:(NSString *)name ofType:(NSString *)extension;
So in your case:
NSBundle* bundle= [NSBundle mainBundle];
NSString *SDKPathString = [ bundle pathForResource: #"test" ofType: #""];

Embedding XML to iOS application

I'm making my first game in iOS and I need to load some levels that are stored as XML. Level files are stored locally and everything works fine from emulator. However, since XML is loaded in the runtime when i try to test my game on an actual device it can't find the XML files since they are not actually part of the app.
I'm coming from Flash background so I might have a wrong idea how this is done on iOS but I need to somehow bundle those XML files with the app, or embed it in the code somehow? Is this possible?
Thanks a lot :)
Well The code to look up your app bundle for the specified file is
NSString *path = [[NSBundle mainBundle] pathForResource:#"fileName.xml" ofType:nil]
NSURL *xmlURL = [NSURL fileURLWithPath:path];
[[NSXMLParser alloc] initWithContentsOfURL: xmlURL]
Hope this helps you...
You could add the XML file to your project and run time read it up with something like this
NSArray *myPathList = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *myPath = [myPathList objectAtIndex:0];
NSError **err;
myPath = [myPath stringByAppendingPathComponent:fileName];
if([[NSFileManager defaultManager] fileExistsAtPath:myPath])
text = [NSString stringWithContentsOfFile:myPath encoding:NSUTF8StringEncoding error:err];
You could consider using JSON in instead of XML. At least to my knowledge the available XML parsers are not nearly as simply to use as SBJson for instance (https://github.com/stig/json-framework/)
Here is my solution in Swift 3.0. In addition to the code, you'll need to add your xml file as a data set in your Assets.xcassets. Do this by creating a new Data Set, giving it any name, and then dragging the xml file from the finder to your newly created data set. When you reference the file in your code, you'll use the file name of the file, and not the name of the data set.
var parseResults = false
if let path = Bundle.main.path(forResource: fileName, ofType: ".xml") {
let url = URL(fileURLWithPath: path)
if let xmlParser = XMLParser(contentsOf: urlToFile) {
xmlParser.delegate = self
parseResults = xmlParser.parse()
}
}

Objective C: How to get another application's bundle identifier

I would like to get the bundle identifier of an application, given it's path.
eg:
NSString* vlcFilePath = #"/Applications/VLC.app"
I know how to get the bundle identifier using NSWorkspace if it is the active application, but in this case it is not necessarily the active application.
NSBundle has a bundleIdentifier method. This won't run or load the application if it is not already loaded/running:
NSString *vlcFilePath = #"/Applications/VLC.app";
NSBundle *bundle = [NSBundle bundleWithPath:vlcFilePath];
NSLog (#"%#", [bundle bundleIdentifier]);
Open the application bundle's plist file and read it from there:
NSDictionary *plistInfo = [NSDictionary dictionaryWithContentsOfFile:[vlcPath stringByAppendingPathComponent:#"Contents/Info.plist"]];
NSLog(#"VLC bundle identifier = %#", [plistInfo objectForKey:#"CFBundleIdentifier"]);