"Open With" menu for remote files - cocoa

I'm getting troubles getting the applications associated with a remote file how has a URL like: "http://servername/folder/file.png".
The code I use is:
...
NSURL *url = [NSURL fileURLWithPath:#"http://servername/folder/file.png"];
NSArray *apps = (NSArray *)LSCopyApplicationURLsForURL((CFURLRef) url,kLSRolesAll);
...
I also try using URLWithString: but the result is the same.
What is the correct approach for this?
Edit after Joshua replay:
Sorry for may bad redaction. The problem is that the LSCopyApplicationURLsForURL call return nil.

First, -fileURLWithPath: expects a file system path like #"/Users/me/Desktop/MyFile.png".
Second, you don't say what the "same" results are and what is wrong with them, so it's difficult to tell you what the problem is.
The docs say this:
If the item URL’s scheme is file
(designating either a file or a
directory), the selection of suitable
applications is based on the
designated item’s filename extension,
file type, and creator signature,
along with the role specified by the
inRolesMask parameter; otherwise, it
is based on the URL scheme (such as
http, ftp, or mailto).
So what are you getting and what do you expect to get?

Related

NSData dataWithContentsOfURL returning nil specifically in iOS 8

I am tring to get the NSData from a local file using [NSData dataWithContentsOfURL:] but am getting nil even when the fileSize returned by [NSFileManager defaultManager] is a positive integer.
Surprisingly, I got this issue when the base sdk was increased from iOS 7 to iOS 8.
I am not sure whether it is an iOS bug or what as it worked in iOS 7 base SDK and not with iOS 8, but here is the solution I found after wasting a couple of hours debugging the code :-(
Use [NSData dataWithContentsOfFile:(NSString *)] instead of dataWithContentsOfURL
Are you sure you pass the Bundle path as well ?
Try with this
NSString* path = [[NSBundle mainBundle].bundlePath stringByAppendingPathComponent:yourPath];
NSData* data = [NSData dataWithContentsOfURL:path];
NSData and URLs: There be dragons
+[NSData dataWithContentsOfURL:] can return nil for any number of reasons. If anything goes wrong when attempting to use that URL this method will return nil. For example the file may not exist, the network connection may time out, or the URL may even be malformed. nil is returned and the application has no idea why.
+ [NSData dataWithContentsOfURL:options:error:] on the other hand, will tell the caller what went wrong. When nil is returned the error argument will be populated with an object that describes the problem that occured. Using this method would directly answer the question of "why".
Both of these are synchronous methods and their use for working with files, network resources, and especially files served from a network resource is discouraged. These methods will block the caller and are not really intended for these kinds of uses. It's better to use an input stream or NSURLSession instead.
you can reference enter link description here
My case. it had a space in the URL
remove space

Using Social.framework and SLRequest with Field Expansion

So far, OS X 10.8.2's Social.Framework works great:
NSURL *requestURL = [NSURL URLWithString:#"https://graph.facebook.com/me/friends"];
SLRequest *fbRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodGET URL:requestURL parameters:params];
This properly delivers the list of friends of the me() object. Fine!
However, once I try to make use of Field Expansion, as follows, the request fails with the error:
An active access token must be used to query information about the current user:
[NSURL URLWithString:#".../friends?fields=cover,picture"];
This is surely reasoned by the fact, that the access_token will be appended internally in the Social.framework using st. similar to "?access_token=%#", which will fail in conjunction with the previous ?fields= usage by myself.
So I wonder whether this is actually a bug of the framework, or whether I'm using it wrongly? I'd really be thankful for any helpful information.
After contacting Apple directly, this is clearly the answer:
Add the field expansion tags using the GET parameter variable, instead of adding them to the actual URL:
SLRequest *fbRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET
URL:requestURL
parameters:#{#"fields":#"cover,picture"}];
Which is obvious, but I didn't think of that :). I'll let this thread as it is if someone might stumble upon the same problem in future!

NSFileManager removeItemAtPath:error: does not respect POSIX permissions

I have some code that checks for the existence of a file and, if it is present, deletes it. The problem is, I am unable to get it to fail even if the file should not be writeable. My code looks like:
if([theManager fileExistsAtPath:savingAs isDirectory:&destIsDir])
{
BOOL itemRemoved=[theManager removeItemAtPath:savingAs error:&err];
if(!itemRemoved)
{
// why?
NSAlert *rebuildAlert=[NSAlert alertWithMessageText:#"Error removing item"
defaultButton:nil alternateButton:nil otherButton:nil
informativeTextWithFormat:#"%#",[err localizedDescription]];
[rebuildAlert runModal];
proceed=NO;
}
}
Even if I set ownership to root:wheel and mode to 000 (i.e. not readable, writeable or executable by anyone) the file is still silently deleted. The account I'm running this from is a user account with Admin privileges but even so, being able to kill files owned by root doesn't seem very safe. The only way to throw an error is to lock the file using chflags uchg filename. I have also implemented (as a stub for now) the fileManager:shouldRemoveItemAtPath: delegate method where I could check permissions if necessary. The problem is that returning NO from this method does not cause removeItemAtPath: to return an error. Re-checking with fileExistsAtPath: seems cumbersome. Finally, there doesn't seem to be a simple method of disambiguating which instance of NSFileManager is issuing the call to removeItemAtPath: in the delegate method. Typically these instances are transitory objects so their id's are not valid for any significant length of time. I could sub-class NSFileManager and add a tag instance variable but that seems like a sledgehammer to crack a nut.
In summary:
1) is it correct behaviour for removeItemAtPath to ignore files it does not own?
2) disallowing file deletion in the delegate method is not communicated back to the caller of removeItemAtPath
3) determining which invocation is calling the delegate method is hard
This is the correct behavior. Erasing a file does not require read access to the file, only the directory containing it. Think of a directory as a list of files, and erasing a file as simply removing it from that list, and it will all make sense.

set uniform filepaths

i have an application on Xcode 4 for osx. In my program i have some places where i need to read and write to a plist file. currently i have used a file path of /users/my name/desktop/name of document plist. however naturally when i make the application into a app and transfer it to a different computer it is not able to find and read the files. what should i make the file path so that it works on any computer. below is my file path that i have
filepath = #"/Users/Gautambir/Desktop/CustomerNames.plist"
You should never, ever, hard-code paths. You should construct your paths using the various APIs available to do so.
There are several ways to construct valid paths. For instance, this works:
NSString* filePath = [[NSHomeDirectory() stringByAppendingPathComponent:#"Desktop"] stringByAppendingPathComponent:#"CustomerNames.plist"];
Alternatively, you could use:
NSString* filePath = [#"~/Desktop/CustomerNames.plist" stringByExpandingTildeInPath];
Although these are correct ways to build a path, to access special locations such as the Desktop, the Documents folder or the Application Support folder, you should use the NSSearchPathForDirectoriesInDomains() function or, preferably, the NSFileManager methods URLsForDirectory:inDomains: or URLForDirectory:inDomain:appropriateForURL:create:error:.
These URL-based method should always be preferred over their path-based equivalents. Apple recommends all developers move to support the URL-based methods as soon as practicable.
This is primarily because file URLs can store bookmark data, so that if a file moves the URL can still be resolved, which is not the case with paths as paths are just strings and can't store metadata.
Here's how you'd use the file manager to find your URL:
NSFileManager* fm = [NSFileManager defaultManager];
NSURL* desktopURL = [fm URLForDirectory:NSDesktopDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
shouldCreate:NO
error:nil];
NSURL* fileURL = [desktopURL URLByAppendingPathComponent:#"CustomerNames.plist"];

Cocoa: Correct way to get list of possible PlugIns directories for an app?

In a Cocoa app generally we can install a plugin bundle in one of a number of places. If for example the app is called "MyApp" you'd be able to install the plugin at:
/Applications/MyApp.app/Contents/PlugIns
~/Library/Application Support/MyApp/PlugIns
/Library/Application Support/MyApp/PlugIns
/Network/Library/Application Support/MyApp/PlugIns
I'm building an NSArray of paths to search in the correct order but I'm pretty sure I'm doing this wrong since it feels like I'm doing too much work for something Apple seem to provide a lot of functions for.
NSArray *systemSearchPaths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSAllDomainsMask, YES);
NSMutableArray *searchPaths = [NSMutableArray array];
NSFileManager *fileManager = [NSFileManager defaultManager];
for (NSString *systemPath in systemSearchPaths) {
NSString *systemPluginsPath = [systemPath stringByAppendingPathComponent:#"PlugIns"];
// FIXME: Remove debug code
NSLog(#"Considering plugin path %#", systemPluginsPath);
if ([fileManager fileExistsAtPath:systemPluginsPath]) {
[searchPaths addObject:systemPluginsPath];
}
}
[searchPaths addObject:[[NSBundle mainBundle] builtInPlugInsPath]];
This results in the Array returned by NSSearchPathForDirectoriesInDomains, with the builtInPlugInsPath value appended to the end.
However, it actually searches directories like "~/Library/Application Support/PlugIns" (missing the "MyApp") folder. Before I start hacking the code to inject the name of my application (which is subject to change at any time), am I doing this wrong?
Is there a way to just tell Cocoa "give me all search paths for 'PlugIns'" directories for this application"?
Nope. You're doing it right.
You can get the name of your application at run time by asking the main bundle for its info dictionary and looking for kCFBundleNameKey therein. When you rename your application, change the bundle name in your Info.plist.
(Definitely do not use your application's filename, as that's much more fragile.)
Be aware that users might not like it if the plug-ins they installed stop working because you renamed your application.
Note that your code above will not catch the PlugIns folder inside the application bundle. For that, ask your main bundle for its built-in plug-ins path or URL.

Resources