Skip to content

Commit

Permalink
Changed auto-load code location to avoid the “unrecognized selector” …
Browse files Browse the repository at this point in the history
…warning.

Fixed typos in README. Updated project settings with Xcode5.
  • Loading branch information
AliSoftware committed Feb 9, 2014
1 parent bb55b6b commit 8934ba1
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 31 deletions.
21 changes: 11 additions & 10 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# xcode noise
build/
*~.nib/
# Xcode
build/*
*.pbxuser
*.perspective
*.perspectivev3
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3

# old school
.svn

# osx noise
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
profile
*.moved-aside
.DS_Store
*.xccheckout
5 changes: 2 additions & 3 deletions Example/OHAutoNIBi18n.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@
29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0460;
LastUpgradeCheck = 0500;
};
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "OHAutoNIBi18n" */;
compatibilityVersion = "Xcode 3.2";
Expand Down Expand Up @@ -266,19 +266,18 @@
C01FCF4F08A954540054247B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
C01FCF5008A954540054247B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
Expand Down
31 changes: 16 additions & 15 deletions OHAutoNIBi18n.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Copyright 2010 FoodReporter. All rights reserved.
//

#import <objc/runtime.h>
#import <objc/runtime.h>
#import <UIKit/UIKit.h>

static inline NSString* localizedString(NSString* aString);
Expand All @@ -20,26 +20,15 @@
static inline void localizeUITextField(UITextField* tf);
static inline void localizeUITextView(UITextView* tv);
static inline void localizeUIViewController(UIViewController* vc);

@interface OHAutoNIBi18nLoader : NSObject
@end

@implementation OHAutoNIBi18nLoader
+(void)load
{
// Autoload : swizzle -awakeFromNib with -localizeNibObject as soon as the app (and thus this class) is loaded
Method localizeNibObject = class_getInstanceMethod([NSObject class], @selector(localizeNibObject));
Method awakeFromNib = class_getInstanceMethod([NSObject class], @selector(awakeFromNib));
method_exchangeImplementations(awakeFromNib, localizeNibObject);
}
@end

/////////////////////////////////////////////////////////////////////////////
// ------------------------------------------------------------------------------------------------

@interface NSObject(OHAutoNIBi18n)
-(void)localizeNibObject;
@end


@implementation NSObject(OHAutoNIBi18n)

#define LocalizeIfClass(Cls) if ([self isKindOfClass:[Cls class]]) localize##Cls((Cls*)self)
Expand All @@ -65,6 +54,15 @@ -(void)localizeNibObject
// Call the original awakeFromNib method
[self localizeNibObject]; // this actually calls the original awakeFromNib (and not localizeNibObject) because we did some method swizzling
}

+(void)load
{
// Autoload : swizzle -awakeFromNib with -localizeNibObject as soon as the app (and thus this class) is loaded
Method localizeNibObject = class_getInstanceMethod([NSObject class], @selector(localizeNibObject));
Method awakeFromNib = class_getInstanceMethod([NSObject class], @selector(awakeFromNib));
method_exchangeImplementations(awakeFromNib, localizeNibObject);
}

@end

/////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -99,7 +97,9 @@ -(void)localizeNibObject
#endif
}

/////////////////////////////////////////////////////////////////////////////

// ------------------------------------------------------------------------------------------------


static inline void localizeUIBarButtonItem(UIBarButtonItem* bbi) {
localizeUIBarItem(bbi); /* inheritence */
Expand Down Expand Up @@ -178,3 +178,4 @@ static inline void localizeUITextView(UITextView* tv) {
static inline void localizeUIViewController(UIViewController* vc) {
vc.title = localizedString(vc.title);
}

10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,29 @@ Alternatively, you can install all of it using CocoaPods. Simply add `pod "OHAut

You can `#define OHAutoNIBi18n_DEBUG 1` if you want `OHAutoNIBi18n` to warn every time it encounters a string for which it does not find any translation in your `Localizable.strings` file. In that case, it will log a message in your console and add the `$` character around the text in your XIB at runtime so you can easily see it.

> Note that you can use strings starting with a "." in your XIB (like ".Lorem ipsum dolor sit amet" to avoid warnings on those strings when `OHAutoNIBi18n_DEBUG` is set. This is useful for your strings you use only as layout helpers (dummy strings to help you see your label in your XIB, which is easier than an empty label to help you position it), like for a `UILabel` in a custom `UITableViewCell` for which you don't want those warnings, knowing that you will override its text by code anyway.
> Note that you can use strings starting with a "." in your XIB (like ".Lorem ipsum dolor sit amet" to avoid warnings on those strings when `OHAutoNIBi18n_DEBUG` is set. This is useful for strings you use only as "layout helpers" (dummy strings to help you see your label in your XIB, which is easier than an empty label to help you position it), like for a `UILabel` in a custom `UITableViewCell` for which you don't want those warnings, knowing that you will override its text by code anyway.

# How it works

This class uses method swizzling to intercept the calls to awakeFromNib and automatically localize any objet created/extracted from a XIB file by the runtime. The method swizzling is done automatically when your application is loaded in memory, so you don't even to add code to install this: the only presence of the OHAutoNIBi18n.m file in your project make everything magic!
This class uses method swizzling to intercept the calls to `awakeFromNib` and automatically localize any object created/extracted from a XIB file by the runtime. The method swizzling is done automatically when your application is loaded in memory, so you don't even have to add code to install this: the only presence of the OHAutoNIBi18n.m file in your project makes everything magic!


### Comparison with Xcode 4.5's "Base Localization"

Starting with Xcode 4.5, you can use the "Base Localisation" (see [Apple Tutorial: Internationalize your application](https://developer.apple.com/library/ios/referencelibrary/GettingStarted/RoadMapiOS/chapters/InternationalizeYourApp/InternationalizeYourApp/InternationalizeYourApp.html)).

But this process requires that you create a `*.strings` file for each of your XIB files, with the same name as the XIB file.
But this process requires that you create a `*.strings` file for each of your XIB files, with the same name as the XIB file, and that you rely on Interface Builder's "Object IDs" which are fare from descriptive and human-readable.

This can become quite a pain:

* If you have a lot of XIB files, you will have to create as many `.strings` files, resulting in a lot of files
* With Base Localization, your `.strings` files will use abstract Object IDs, which are far from convenient to identify objects of your XIB (not even mentioning when you need to provide those `Localizable.strings` files to the person you pay to translate your application, how will s/he understand how to match those IDs with the actual UI?)
* This is also problematic for every generic term in your application that is used across multiple XIB, like some vocabulary or strings specific to your application domain and used in all of your XIB files. In that case, Base Localization requires that you repeat this term in every of your `.strings` files, whereas with `OHAutoNIBi18n` you can just translate it once in your `Localizable.strings`.

For all these reasons, Base Localization is just not such a great solution after all, whereas `OHAutoNIBi18n` does not have those quirks.


# License

This code is distributed under the MIT License.

0 comments on commit 8934ba1

Please sign in to comment.