NSString子类或包装类或类别

问题描述:

由于某些*指南(医疗与健康措辞),我目前正在帮助客户需要更改其应用程序中的语言。他们的应用程序非常庞大,所有的字符串都包含在代码中,即(stringWithFormat/hardcoded),它们都不在外部表中。这意味着这将是一项巨大的手动任务。NSString子类或包装类或类别

在未来一个未定的时间点,客户相信他们将获得批准返回到他们当前的措辞,并希望将字符串切换回来。从字面上看,大部分的变化都是将一个有问题的单词转换成一个不太成问题的单词。

我想,也许如果我可以在运行时基于bool开关更改字符串,它可能会消除所涉及的手动工作,并且可以让我在需要时切换回语言。

第一次尝试:

+ (instancetype)stringWithFormat:(NSString *)format, ... 
{ 
    va_list args; 
    va_start(args,format); 
    //todo check flag if we're changing the language 
    //todo replace problematic word from 'format' 
    NSString *result = [NSString stringWithFormat:format,args]; 

    return result; 
} 

我第一次迅速编写了一个类别覆盖stringWithFormat更换有问题的话。我忘了我会失去stringWithFormat的原始实现。这导致无尽的递归。

下一次尝试(子类):

我开始试图子类的NSString打了一个计算器后说,如果我的解决办法是继承一个类簇,那么我没有因为继承类簇明白我的问题几乎从未完成。

最后一个选项(包装):

我的最后一次尝试是写一个包装类,但那种失败的初衷是要求避免手动寻求在应用程序的每个字符串。

我不太确定如何解决这个问题了。如果我需要为其中一个核心类添加/覆盖功能,该怎么办?

+1

相关:有没有什么办法猴补丁或调酒一个NSArray或其他类簇?](http://*.com/q/11751473) –

有一个更简单的解决方案,看起来更合适。使用NSLocalizedString,用键而不是实际的字符串:

displayString *NSString = NSLocalizedString(@"displayString", nil); 
cancelButtonTitle *NSString = NSLocalizedString(@"cancelButtonTitle", nil); 

然后创建一个在您的应用程序一个Localizable.strings文件,并定义应显示的实际值:

"displayString" = "The string to display in English" 
"cancelButtonTitle" = "Cancel" 

你把本地化。应用程序包中的字符串文件,应用程序使用它在运行时进行字符串替换。

您还可以为不同的语言定义Localizable.strings的不同版本,例如,如果用户已将其语言设置为西班牙语,则调用NSLocalizedString()会为您提供西班牙语版本。 (你已经提到过,NSString是一个类的集群,这意味着它是一个公共接口,用于各种不同的私有子类,当你创建一个NSString时,你不能确定你得到的是哪个私有子类,这使得它是一个坏主意尝试子类。)

对于硬编码的字符串,你没有别的办法,只能通过将它们分配给某种类型的字符串转换器类来手动修改它们。所以那些:

yourmom.text = @"Hi Mom"; 
yourdad.text = [NSString stringWithFormat:@"%@ and Dad!",yourmom.text]; 

你需要这些分配类型更改为类似

yourmom.text = [StringConverter string:@"Hi Mom"]; 
yourdad.text = [StringConverter string:@"%@ and Dad!" placeHolder:yourmom.text]; 

至于在故事板或xibs字符串,可以在viewDidLoad中通过迭代循环改变它们。祝你好运。

你的第一次尝试的想法没有什么错,只是在执行过程中出现了一点小错误。更改:

NSString *result = [NSString stringWithFormat:format,args]; 

到:

NSString *result = [NSString alloc] initWithFormat:format arguments:args]; 

这是stringWithFormat:扩张和拦截将工作。

有关类集群思想是在这种特殊情况下一个红色的鲱鱼,为集群(NSString)必须提供类的方法实现(+stringWithFormat:)前级,这样你就可以用一个简单的类来拦截他们。

然而,已经截获+stringWithFormat:小心。一个简单的测试会告诉你它被框架使用了很多,你不想破坏它们 - 因为我的第一个简单的测试是通过简单地将“d”更改为“c”,它将“window”更改为“wincow”,这反过来打破了绑定设置的Xcode的默认应用程序绑定属性“窗口”...

如果你正在改变健康相关的话你可能会好,整个字符串会更好。

一个更好的方法可能是简单地编写一个RE来匹配代码中的所有文字字符串,并将其替换为function(string)用于您编写的某个函数(而不是方法)以执行转换。

HTH

+0

然而,对于这个解决方案工作的大部分我遇到了一个障碍。 **由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'尝试用appendString变异不可变对象:' 所以我做了这些更改,这是错误。与crashlytics /织物有关。所以你是对的......它确实打破了一些框架。 :D – Atomhax

+0

这是stringWithFormat还与NSMutableString一起使用,我只是从这个重写的函数返回一个NSString?所以我需要改变实现来考虑Mutable Strings。 – Atomhax

+1

您是否尝试过向'NSMutableString'添加类别?对打破框架的担忧不是拦截*本身*,而是如何修改方法的*行为*。我不会说替换这个方法是最好的方法,但它确实具有您似乎正在寻求的最小源代码变更的好处。 – CRD