There are a lot of nice little functions in System.IO.Path like replacing a file extension, append to a path, getting a filename, getting a directory from a path in C#. Is there an iOS equivalent or somewhat close API?
thanks!
Yes, there is. Have a look at "Working with Paths" section in NSString reference.
To work with actual files you need to use NSFileManager class
NSString has a number of methods that allow you to manipulate paths.
It's not super elegant, but it's very useful.
NSString *textFile = #"readme.txt"
NSString *markdownFile = [[textFile stringByDeletingPathExtension] stringByAppendingPathExtension:#"markdown"];
// markdownFile is now "readme.markdown"
Related
There's a lot of pieces to this, but from what I can tell, they're all necessary to reproduce the problem.
I made a trivial NSURL subclass, like so:
class URL2: NSURL { }
I made a file URL with it:
let f = URL2(fileURLWithPath: "/Users/me/Downloads/ついて.pdf")
Then I tried returning it from previewPanel(panel:previewItemAtIndex index:).
Result: I get a generic file icon in the QLPreviewPanel (but it has the correct filename).
Curiously, if I do any of these differently, it works:
If I use a plain NSURL(fileURLWithPath: "/Users/me/Downloads/ついて.pdf"), it displays the file contents correctly.
If I use an ASCII-only filename, it displays the file contents correctly.
If I do something else with the URL2 (like some NSFileManager operation), it locates the file just fine.
What could I be doing wrong that causes QuickLook to be unhappy with my NSURL subclass in this case?
Subclassing NSURL (or NSURLRequest) is often a path to madness, thanks in no small part (I think) to heavy use of NSXPC in various parts of the OS.
I would suggest using a category with associated objects instead. This should avoid the edge case you're hitting, while still allowing you to add custom methods and properties to the NSURL objects.
I just came across a line of code that was written by a co-worker and I've never seen this before in Obj-C. It looks like poor form and I want to change it, but it seemingly works (the app is working as expected) and I don't even know what to change it to.
NSString **stringArray= new NSString *[numberOfStrings];
Is this OK? Would an NSArray of NSStrings make more sense?
EDIT: In order to properly free the array from memory, are any release calls needed? Currently, all I see is delete [] stringArray;.
EDIT 2: This seems to properly remove the array from memory:
for (int i=0; i < numberOfStrings; i++)
{
[stringArray[i] release];
}
delete [] stringArray;
Using an NSArray might be more legible to someone without a C background, this is just a plain old C array filled with NSString*, perfectly valid but quite different from an NSArray instance.
Both make sense, but if the users of that array are expecting a C-style array rather than an NSArray instance, there might be a lot of refactoring involved.
He is using Objective-C++ (you should be able to verify that in the 'file type' on the right panel for the file in xcode4).
the new keyword is creates a new array of (NSString *) with numberOfStrings size.
To answer your question, an NSArray would very likely be more manageable, especially if there are different developers on the code. To use a C++ array there may have been performance issues but that depends on the context of that code.
I am working on an iphone application and I am wondering what the correct practice is for abstracting out strings. I am used to creating a file with constant strings and referencing them in my application (such as urls, port numbers or even button labels). I am wondering if this is considered good practice in Obj-C and if so what the best way to do it is? Should I make a class with the strings? Or use the ".strings" file?
p.s I may be localizing my application at a later time. I havent looked into how to do it, but I figure abstracting out my strings is a good idea while i'm developping.
Thank you!
MGA
generally, you interface with NSBundle. You use a string to read a localized version of the string (which is loaded from a localized strings file).
there are also some macros some people use to lighten the syntax, these are prefixed with NSLocalizedString. NSLocalizedString implementations use NSBundle.
imo, you should use string constants to identify the localized string you read (like you should with dictionaries and object keys).
you can declare your constants using this form (objc assumed):
extern NSString* const MONAppString_Download;
and define like so:
NSString* const MONAppString_Download = #"Download";
then access it using:
NSString * tableName = nil; // << using the default
NSString * localized =
[[NSBundle mainBundle]
localizedStringForKey:MONAppString_Download
value:MONAppString_Download // << return the string using the default localization if not found
table:tableName];
sometimes it helps to create wrapper functions to reduce the noise, especially when you use them in many places:
// #return what's set to the above variable named 'localized'.
NSString * MONLocalized_Download();
then you set up your strings files like a map, one for each localization you support.
so, whenever you need to read a string which is visible to the user, you use the above form. also consider that there are other resources to localize (nibs, images, pdfs, etc.) which you may bundle with your app. much of the work here is also abstracted by NSBundle, of CFBundle, if you prefer.
good luck
I am trying to store the location of my Application's Document Directory in a NSString.
NSString *documentDirectory = [self applicationDocumentsDirectory];
The code compiles without error, but I get the warning that I am trying to initialize a NSString with a NSURL. When I run the app, the app crashes. I tried casting, but it gave me an error. The book I got it off(Head First iPhone Development) says the code should work. The code is in my appDelegate.m file. Any Help will be greatly appreciated.
Regards
It is returning an NSURL as Dave DeLong said. However the easiest way to get round this and convert it to an NSString without changing the method, is setting the string to the NSURL's absoluteString.
NSString *documentDirectory = [[self applicationDocumentsDirectory] absoluteString];
Your -applicationDocumentsDirectory method is returning an NSURL. You want it to return an NSString.
The methods return a NSURL. You must convert the url in NSString.
It's very easy. Use a method in NSURL class.
I'm building a version of an App I have already released, but with a few changes. It's not quite a lite/full version relationship, but they're similar enough that I'm using the same project with a different target.
I'd like to reword almost all of the strings I have used in the first version for the new version, and was wondering the best way to approach this. Rather than use #ifdef/#else statements before the declaration of each string, I was thinking of using NSLocalizedStrings. However, the actual language is still the same.
I read in this post that you can set the language yourself, so presumably I can invent my own language and set it to that. But I'm wondering if this is the best way to go about things? Any advice would be most welcome.
You can have multiple string tables for any given language (that is multiple .strings files). When you want a localised string, you can obtain it through:
NSString *str;
// Look up string in Full.strings
str = [[NSBundle mainBundle] localizedStringForKey:#"SomeKey"
value:#"DefaultValue"
table:#"Full"];
// Look up strings in Lite.strings
str = [[NSBundle mainBundle] localizedStringForKey:#"SomeKey"
value:#"DefaultValue"
table:#"Lite"];
Since the table for this method can be variable, you can even switch it at runtime. The above assumes you have a Full.strings table and a Lite.strings table.
Full.strings
"SomeKey" = "This string appears in the full version";
Lite.strings
"SomeKey" = "This string appears in the lite version";
You may not want to ship them together, if that is the case, you can configure your Info.plist to contain the name of the table to use for a specific target (if you add an entry called "TableToUse", you can get it via [[[NSBundle mainBundle] infoDictionary] objectForKey:#"TableToUse"])
NSLocalizedStrings actually is a macro defined as
#define NSLocalizedString(key, comment) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:#"" table:nil]
With table parameter set as nil, the code will use the default one "Localizable" so if we add another localized string file, we should call [[NSBundle mainBundle] localizedStringForKey:value:table: directly instead of calling NSLocalizedStrings
I'd be very hesitant to invent my own language, but you probably don't need to either. If you use NSLocalizedString in the appropriate places and then use genstrings to extract these to a Localizable.strings (see the docs), then you could simple have two versions of this file and then copy the correct version in each target.