How should I store localized Strings in an iOS project? - ios

I’m developing an iOS application. One of my tasks is localization. For this reason, I’ve taken all strings and put them each in a NSLocalizedString(key,comment), and everything’s been OK.
But my new solution is to create a Singleton class, which stores every String that I use in the project. With this I have one small, but tricky problem: naming. Do I need to create some dictionaries for every class (view) that needs localized strings? Or should I use prefixes for this, or functions that return objects with good, understandable property names?
P.S: i don't want to invent new wheel. I want to create STORAGE of localized strings, that will be used in project. So, my target is to make singleton:
[[[StringStorage sharedInstance] getStringsForClass:self] objectForKey:#"title"];
or something like this:
[StringStorage sharedInstance].stringTitleForMainView

You really should stick with NSLocalizedString and NSLocalizedStringFromTable. You also can use the NSBundle method localizedStringForKey:value:table:.
But if you take any other route you are reinventing the wheel, and you lose the ability to use the genstrings command line tool to extract all your strings from the source code.

Related

Is prefix necessary for methods in iOS?

I'm a bit confused with Apple documentation relating to the explanation of whether to use prefix for methods or not?
Apple Doc Explanation 1:
Use prefixes when naming classes, protocols, functions, constants, and typedef structures. Do not use prefixes when naming methods; methods exist in a name space created by the class that defines them. Also, don’t use prefixes for naming the fields of a structure
Apple Doc Explanation 2:
If you are subclassing a large Cocoa framework class (such as NSView or UIView) and you want to be absolutely sure that your private methods have names different from those in the superclass, you can add your own prefix to your private methods. The prefix should be as unique as possible, perhaps one based on your company or project and of the form "XX_". So if your project is called Byte Flogger, the prefix might be BF_addObject:
For Classes which contains project related storylines/stuffs, there prefixes are not required.
But if we are using Apple Classes by extending few methods as given in example, like UIView to MBView then we should add prefix to methods to private methods in private category ( in .m file).
This is because ObjC does not support namespaces. Instead you should you capital letter prefixes(as you properly read in documentation). You could read this SO discussion why to use them.
Note that Apple uses two-letter prefixes(UI(View), NS(String), etc.) and advises programmers to use 3 letter prefixes.
I think you should use a prefix when you can, it can become a good practice and you can identify, by the name which part of your big software you're playing with.
Let's say your program name is Byte Flogger, then all your classes should start with :
BF prefix. BFBaseList for exemple, and if you want to prevent rejections when submitting your app to the AppStore, it's also a good practice to name your methods bfMyMethodName so that you still respect CamLCase naming conventions.
So for an image, you could name a property bfContentMode without being suspected by Apple to use one private API feature.
Now, let's say you handle some modules, a core module, a network module, etc...
If your class name is BFCObject, you could know that you're working with a Core object of your program.
So it is not necessary, but not doing it could force you to refactor your code in the last moment of submission. In a time driven project, I wouldn't even take that risk.

Create Header and implementation file in swift

This is more of a coding style question but i believe it is valid. Coming from an obj c background i always create a .h and a .m when creating a class. However with swift that changes and all that goes into a single file. I know that for some people this is cool but i miss having these two things separate.
Quoting a comment from Zaph
"What I miss is a list of public methods as opposed to searching an
entire source file for methods not marked private. There is a
programming concept of "writing to the interface". And the public
methods should be carefully picked, not just because the developer
forgot to make some private."
is there a way to have a header - implementation class in separate files using swift? Maybe some trick?
Thanks
May be you can use Generated Interface to view all the public methods and properties. You can find that option at the bottom of related files popup in the upper-left of the source editor window. To switch back, click Original Source in the same pop up.
Shortcut: control + cmd + down arrow
This is how generated interface file looks.
As far as i'm aware, this cannot be done. That being said, if set out your .swift files correctly then they are still very readable. I tend to follow this as a guideline for styling in swift and i find that it breaks things up into readable sections, especially by using // MARK: as well.
In short, no.. But what do you miss..? Once you get used to it, you will probably prefer it like this! The old separation has no clear advantage over this new one!
More and more languages use this approach, as it reduce coupling and errors.
So when you change the signature of a function, to need to check another file to update it, it's only duplication without any added value.
The problem you describe (how to see only "public" functions) is usually done buy tools( IDE) or documentation generators.
You can create 2 swift files:
YourClassNameHeader.swift
class YourClassName {// put here all your properties
}
YourClassNameMethods.swift or YourClassNamePrivate.swift
extension YourClassName { // put here all private methods and
properties }
But in general its not good practise

How to make it modular - Creating objects in Swift based on classnames defined in a plist?

How can I add objects based on classes/classnames loaded from a plist (as strings) using Swift? Is this even possible?
Here's what didn't work …
var layer:NSClassFromString(layerClassNameString) = (NSClassFromString(layerClassNameString))()
I'd like to create a modular structure where I can add and remove layers of functionality defined as classes (≈in-app purchases) easily. Therefore these classes should be used for instantiation with the minimum amount of hard coding of switch statements and fixed classnames to make it easy to add new ones going forward.
Ideally I'd like to just add new the classes to the project and add their name to the plist. It would be great if the instantiation works across different classes of the same type/following the same protocol based on only one central definition (like the plist).
How can this kind of modularity be solved? Am I on the right track with using a plist as central point for this information?

How can I add a custom extension tag to the GPXFramework code?

I found the excellent resource of the open source iOS GPX Framework (http://gpxframework.com/) which allows me to create and read GPX files. However I would like to add a custom extension to store data specific to my app. I can see that the GPX framework implements a file GPXExtensions.h and .m, but I am not sure how to go about adding say a tag for storing the speed data at a particular coordinate in the GPX.
I am guessing I would have to add the data I would like to add as an extension to the GPXExtensions class as a property and then somehow modify the code in this method:
- (void)addChildTagToGpx:(NSMutableString *)gpx indentationLevel:(NSInteger)indentationLevel
{
[super addChildTagToGpx:gpx indentationLevel:indentationLevel];
}
But I am not sure what this method is supposed to do, any ideas?
That's basically the right idea. Jaime Machuca's fork contains a commit where he added heart rate, etc. It should give you a pretty good template from which to create your own modifications. Note that if you want something more sophisticated, you may need to create your own subclass of GPXElement so that you can take advantage of the tree structure.

InfoPlist.strings vs a global.h for constants

If I want to declare a constant string (not necessarily changing based on language) that can be used in multiple .m files should I do that in my InfoPlist.strings or should I create a separate global.h file and use #define?
The research I've done makes me thing global.h is the way to go but I want to make sure.
It depends on what type of constant you need. For a simple string constant, using a .strings file has an advantage in that it doesn't need to re-compile the binary to have the values available inside the app, on the other hand, makes it easier for a hacker to modify.
Using a .h to store constants is better if you want to store numerics, as parsing an integer from a string is no small task.
Most of the time, I would say that a .h is better, but beware of pitfalls of using one! You cannot take an address of a constant in a .h (which normally you don't have to use), and comparing a string with == and a constant is a no-no.

Resources