How do I get a document UTI from a file path? - objective-c

I have a document path as an NSString. How do I get its UTI as an NSString? I currently use LSCopyItemAttribute but that requires an FSRef and all the functions for making an FSRef seems to be deprecated.
(Note: This is for Mac OS 10.8+.)

You will be able to get it using mobile core services framework. Refer the code below
NSString *path; // contains the file path
// Get the UTI from the file's extension:
CFStringRef pathExtension = (__bridge_retained CFStringRef)[path pathExtension];
CFStringRef type = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension, NULL);
CFRelease(pathExtension);
The code snippet is taken from here.

Use can use url.resourceValues(forKeys: (as mentioned in the comments):
if let resourceValues = try? url.resourceValues(forKeys: [.typeIdentifierKey]),
let uti = resourceValues.typeIdentifier {
return uti
}

Related

Stop copying file in Cocoa

I'm facing a problem I using the FSEvent to catch the file created in my app but I also want to check the file extension (ex: photo/ video type) are allowed, otherwise these files will not be copied. How can I check the file extension before copying in Cocoa? Any suggestion would be appreciated. Thanks
Please note I don't use NSFileManager to copy file.
Use following code to check for movies or audio file types. Full list of UTI-Types in the documentation.
NSString * fileUTI = nil;
BOOL success = [self getResourceValue:& fileUTI forKey:NSURLTypeIdentifierKey];
if (success && [uti isKindOfClass:[NSString class]]) {
BOOL fileConformsToUTI = UTTypeConformsTo(fileUTI, kUTTypeMovie);
fileConformsToUTI = fileConformsToUTI || UTTypeConformsTo(fileUTI, kUTTypeAudio);
// check and do the copy
}

iTunes Mp3 Add Returning Nil Via Scripting Bridge In ObjC and Swift And Doesn't Import

I'm trying to import a downloaded MP3 into iTunes. My app is for OSX using Swift, and I've tried doing this both in Swift code and in ObjC using interoperability. I've generated the iTunes.h using sdef and sdp. I'm importing it in my Bridging Header for the Swift attempt and in my .m file for the ObjC attempt. I've added Scripting Bridge to my build.
This is my first program in Swift or ObjC (my experience is in C#) so this may be something simple I don't have the experience to realize.
Here is my ObjC code:
NSString *filepath = "~/Music/test.mp3";
iTunesApplication *iTunes = [SBApplication applicationWithBundleIdentifier:#"com.apple.iTunes"];
iTunesPlaylist *pl;
for (iTunesSource *source in sources) {
if([source kind] == iTunesESrcLibrary) {
SBElementArray *libraries = [source libraryPlaylists];
pl = [libraries objectAtIndex:1];
break;
}
}
iTunesTrack *track = [iTunes add:[NSArray arrayWithObject:[NSURL fileURLWithPath:filepath]] to: pl];
Everything compiles and runs, but the iTunes add returns nil (and more importantly, doesn't add to iTunes). I've tried using different Playlists from the Library, and difference Sources as well. I've tried using a different MP3 file. And as I said, I've written it in Swift as well. All give me the same result.
So apparently I was fetching the path for MyMusic incorrectly. You can't just use the tilde, you have to resolve it:
NSString *musicDirectory = [NSSearchPathForDirectoriesInDomains(NSMusicDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filepath = [musicDirectory stringByAppendingPathComponent:#"test.mp3"];
Or with Swift:
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.MusicDirectory, inDomains: .UserDomainMask)
let musicDirectory: NSURL = urls.first as? NSURL
let filepath = musicDirectory.URLByAppendingPathComponent("test.mp3")
At this point, I no longer needed to mess with any of the source searching either, I could just pass nil as the playlist:
iTunesTrack *track = [iTunes add:[NSArray arrayWithObject:[NSURL fileURLWithPath:filepath], nil] to: nil];
I still need an Objective C wrapper around the actual add method, however, which is connected to the Swift programming via the Bridging Header. If I try to use the add method in Swift directly, I get linker errors which seem unrelated to the original issue, so I won't address.

objective C save file with extension and name to dictonary

I have a browse function where I get the url of a file.
Now I want to save the file in the supporting file dictionary so that if the file is move anywhere else it can still access it
I have a code which saves it to the supporting files:
NSURL *mainUrl;
mainUrl=[[NSBundle mainBundle] bundleURL];
NSFileManager *Fm;
[Fm copyItemAtURL:url toURL:mainUrl error:nil];
but I don't know what the name and the extension because the browse function allows png,jpg,jepg files
and I would need the name to access it
so my question would be how I can I save the file there with a name and extension of my choose
my name would look like that:
NSString *string;
NSInteger number;
number=0;
string=[NSString stringWithFormat:#"%#%li",#"img",(long)number];
and the extension would be jpg
can somebody help me?
You can use NSString's -stringByAppendingPathExtension: method:
[#"foo" stringByAppendingPathExtension: #"jpg"];
results in #"foo.jpg".
You could get the file name and the extension using the specified full path and the following functions.
/* NSString Class References*/
lastPathComponent
Returns the last path component of the receiver.
(NSString *)lastPathComponent
pathExtension
Interprets the receiver as a path and returns the receiver’s extension, if any.
(NSString *)pathExtension

Custom font in a Cocoa application

I know you can customize fonts by using Interface Builder and selecting a font. However, I'm curious if I can use a custom font that's not included by default on systems. Is there a way to include a custom font in my application?
While the manual font activation procedure is one option, you might also consider the ATSApplicationFontsPath Info.plist key:
Information Property List Key Reference:
"ATSApplicationFontsPath (String - Mac
OS X) identifies the location of a
font file or directory of fonts in the
bundle’s Resources directory. If
present, Mac OS X activates the fonts
at the specified path for use by the
bundled application. The fonts are
activated only for the bundled
application and not for the system as
a whole. The path itself should be
specified as a relative directory of
the bundle’s Resources directory. For
example, if a directory of fonts was
at the path
/Applications/MyApp.app/Contents/Resources/Stuff/MyFonts/,
you should specify the string
Stuff/MyFonts/ for the value of this
key."
I'd be sure to double-check, but I believe this functionality was added in OS X 10.5.x (which the code posted by Jinhyung Park targets).
ATSApplicationFontsPath uses [NSBundle mainbundle] path as base path, so it does not work when Resources folder is not located there (e.g. for app plugins).
In my Cocoa plugin I need to load custom fonts using CTFontManagerRegisterFontsForURL
#import <Cocoa/Cocoa.h>
static void FGDActivateFont(NSString *fontName)
{
// Can't make ATSApplicationFontsPath in Info.plist work for plugins (non-standard Resources path)
NSArray *availableFonts = [[NSFontManager sharedFontManager] availableFonts];
if (![availableFonts containsObject:fontName]) {
NSURL *fontURL = [[FGDRapidCart bundle] URLForResource:fontName withExtension:#"ttf" subdirectory:#"Fonts"];
assert(fontURL);
CFErrorRef error = NULL;
if (!CTFontManagerRegisterFontsForURL((__bridge CFURLRef)fontURL, kCTFontManagerScopeProcess, &error))
{
CFShow(error);
}
}
}
int main(int argc, char *argv[])
{
#autoreleasepool
{
FGDActivateFont(#“FontAwesome”);
}
return NSApplicationMain(argc, (const char **)argv);
}
Credits: https://github.com/OneSadCookie/Extendaword/blob/master/Extendaword/main.m
Here is the example for Mac App custom font loading.
NSString *fontFilePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"/fonts"];
fontsURL = [NSURL fileURLWithPath:fontFilePath];
if(fontsURL != nil)
{
OSStatus status;
FSRef fsRef;
CFURLGetFSRef((CFURLRef)fontsURL, &fsRef);
status = ATSFontActivateFromFileReference(&fsRef, kATSFontContextLocal, kATSFontFormatUnspecified,
NULL, kATSOptionFlagsDefault, NULL);
if (status != noErr)
{
errorMessage = #"Failed to acivate fonts!";
goto error;
}
}
I have managed to do this using cocos2d (CCLabelBMFont) and hiero tool. You will need to create the font using the hiero, and give this font to the CCLabelBMFont object.

NSString to FSRef conversion doesn't work

For my app I need to use the Carbon file manager API to get the size of a folder (NSEnumerator is slow, and using NSTask with a shell command is even worse). I've imported the Carbon framework, and I'm using this method to get the size of a folder:
http://www.cocoabuilder.com/archive/message/cocoa/2005/5/20/136503
It uses an FSRef as an argument, and my path string is currently an NSString. I tried using this to convert the NSString to an FSRef:
FSRef f;
OSStatus os_status = FSPathMakeRef((const UInt8 *)[filePath fileSystemRepresentation], &f, NULL);
if (os_status != noErr) {
NSLog(#"fsref creation failed");
}
And then I called the folder size method:
[self fastFolderSizeAtFSRef:f];
However when I try to build, I get this error regarding the above line:
error: incompatible type for argument one of 'fastFolderSizeAtFSRef:'
Any help would be appreciated. Thanks
The "fastFolderSizeAtFSRef" method takes an FSRef* (FSRef pointer). You're giving it an FSRef. It's a one character fix, luckily enough. You have:
[self fastFolderSizeAtFSRef:f];
Simply change that to:
[self fastFolderSizeAtFSRef:&f];
And you should be good to go. However, I was implementing this same method yesterday but was having trouble creating the FSRef itself. I eventually went with the following code:
FSRef convertNSStringToFSRef(NSString * theString) {
FSRef output;
const char *filePathAsCString = [theString UTF8String];
CFURLRef url = CFURLCreateWithBytes(kCFAllocatorDefault,
(const UInt8 *)filePathAsCString,
strlen(filePathAsCString),
kCFStringEncodingUTF8,
NULL);
CFURLGetFSRef(url, &output);
CFRelease(url);
return output;
}
This has been working flawlessly for me.
EDIT: I just open sourced the code that I'm using this in. It's these files:
This file adds a method to NSFileManager that uses an FSRef to find the complete size of a directory.
This file adds a method to NSString that will convert it to an FSRef.
Everything happens on line 46 of this file.