StringCoding 是一个支持使用字符串值设置任何类型对象属性的简单库。它可以自动检测属性类型并尝试将字符串解释为正确的值。
StringCoding 非常适合创建配置文件,以快速调整应用程序属性而无需重新编译。
StringCoding 主要针对配置 UIKit 视图和控件。一个典型的使用案例是为配置应用程序外观创建 plist 或 json 的 "样式表"。对于具有多个主题或 "皮肤" 的应用程序,这可能非常有用。
与其他库不同,StringCoding 不会为视图添加任何额外的样式属性。它旨在仅提供字符串编码访问现有属性和方法,而不扩展功能。但是,由于它的工作方式,它可以自动检测并支持通过分类添加的附加属性(见下面 "添加对附加字符串属性和类型的支持")。例如,如果您使用 ViewUtils 库(https://github.com/nicklockwood/ViewUtils),该库扩展了 UIView 并对宽度、高度等具有显式确定器,StringCoding 允许您使用字符串设置这些属性,而无需添加显式支持。
查看包含的 UIConfig 示例,以了解 StringCoding 功能的实际应用。
注意:"支持" 意味着该库已与该版本进行过测试。"兼容" 意味着库应在该 iOS 版本上运行(即它不依赖于任何不可用 SDK 功能),但不再测试兼容性,可能需要调整或错误修复以正确运行。
截至版本 1.2,StringCoding 需要 ARC。如果要将 StringCoding 用于非 ARC 项目,请在 StringCoding.m 文件中添加 -fobjc-arc 编译器标志。要这样做,请转到目标设置中的构建阶段选项卡,打开编译源代码组,双击列表中的 StringCoding.m,并在弹出视图中键入 -fobjc-arc。
如果您希望将整个项目转换为 ARC,请在 StringCoding.m 中取消注释 #error 行,然后在 Xcode 中运行 “编辑 > 重构 > 转换为 Objective-C ARC...” 工具,并确保所有想要使用 ARC 的文件都已勾选(包括 StringCoding.m)。
要使用 StringCoding,只需将 StringCoding.h 和 .m 文件拖入您的项目中,并添加 QuartzCore 框架。StringCoding 还需要包含 UIKit 或 APPKit 框架,并且您所使用的框架必须包含在项目中的 .pch 文件中。StringCoding 方法通过分类在现有类中实现,因此只需将头文件导入到您的类中,StringCoding 方法即可使用。
StringCoding 为每个对象扩展以下额外方法
- (void)setValueWithString:(NSString *)value forKey:(NSString *)key;
- (void)setValueWithString:(NSString *)value forKeyPath:(NSString *)keyPath;
这些方法的作用类似于标准的 KVC setValue:forKey: 和 setValue:forKeyPath: 方法,除了值始终为字符串且会自动转换为正确的类型,前提是该类型已知。尝试设置未知类型的属性将抛出异常。这可以通过为每个特定情况添加特定的字符串设置方法来解决(见下文)。
注意:默认情况下,StringCoding 将 setValue:forKey:
和 setValue:forKeyPath:
swizzling,以便在适当的时候调用 setStringValue 相等的方法。这意味着除非您已经禁用了 swizzling(使用 SC_SWIZZLE_ENABLED 宏),否则没有必要显式地调用 setValueWithString:。
StringCoding 为每个 NSString 扩展以下额外方法
- (BOOL)isNumeric;
如果字符串的值可以解释为数字,则返回 YES。
- (Class)classValue;
返回与字符串名称匹配的类,如果该类不存在则返回 nil。相当于 NSClassFromString() 函数。
- (SEL)selectorValue;
返回匹配字符串的选择器。这可以用于调用对象上的方法,并且 UIControls(见下文)的目标/行为绑定系统会使用它。
- (char)charValue;
返回字符串的字符值。值按以下方式确定:如果字符串是单个字符,将返回该字符的 ascii 值(非 ascii 字符的结果未定义)。如果字符串是多位数字值,则返回该数字(如果它在 10-127 或 -1 到 -128 的范围内)。如果字符串是前缀为 "0x" 的十六进制数,则如果它在 0-127 的范围内,则将其返回。较高值被视为负值。如果字符串是如 "yes" 或 "true" 这样的布尔值,则返回 1 或 0。
- (NSURL *)NSURLValue;
返回字符串的 NSURL 值。如果路径是绝对文件路径,则将其作为文件 URL 返回,否则将其作为普通 URL 返回。如果 URL 是相对路径,则将 baseURL 属性设置为应用程序资源包目录。如果字符串为空,则返回 nil。
- (NSURL *)NSURLRequestValue;
将字符串作为 NSURL 处理,其逻辑与 NSURLValue 相同。URL 可选地遵循一个 REST 方法(GET、PUT、POST、DELETE、HEAD、OPTIONS),由空格分隔。如果没有包括方法,则假定是 GET 请求。
- (CGPoint)CGPointValue;
返回字符串的 CGPoint 值。字符串可以是包含一对以空格分隔的浮点值的对,或者可以格式化为 "{x,y}"(相当于调用 NSStringFromCGPoint() 的结果)。
- (CGSize)CGSizeValue;
返回字符串的CGSize值。字符串可以包含一对由空格分隔的浮点数,也可以格式化为"{width,height}"(与调用NSStringFromCGSize()的结果等效)。
- (CGRect)CGRectValue;
返回字符串的CGPoint值。字符串可以包含四个由空格分隔的浮点数,也可以格式化为"{{x,y},{width,height}}"(与调用NSStringFromCGRect()的结果等效)。
- (CGColorRef)CGColorValue;
返回一个CGColorRef,其值根据以下算法确定:如果字符串是匹配标准UIColor/NSColor值之一的名称(例如black或blackColor - 不区分大小写),则将返回该颜色。如果字符串是图像的URL或文件路径,则将其视为图案图像。否则,可以接受形如"rgb(r,g,b)"、"rgba(r,g,b,a)"或6或8个字符的十六进制值(可选带有前导#)(例如"#ff0000"代表红色)的颜色。
- (CGImageRef)CGImageValue;
返回一个CGImageRef。将字符串解释为图像文件名、路径或URL。
- (CGFontRef)CGFontValue;
返回根据以下标准选择的CGFontRef字体:如果字符串匹配字体名称,则将其返回。如果值是"bold"或"italic",则返回相应的加粗或斜体系统字体变体。任何其他值将返回默认系统字体。
- (NSTextAlignment)NSTextAlignmentValue;
- (NSLineBreakMode)NSLineBreakModeValue;
这些方法分别返回字符串的NSTextAlignment和NSLineBreakMode值。字符串可以包含简短名称,如"left"或"justified",或完全限定的名称,如"NSTextAlignmentLeft"。值不区分大小写。
- (UIColor *)UIColorValue;
使用与CGColorRefValue相同的逻辑返回一个UIColor。
- (UIImage *)UIImageValue;
返回一个UIImage,将字符串作为文件名、路径或URL处理。您可以可选地追加一或两个由空格分隔的浮点值,分别表示可拉伸图像的左和顶部帽子。
- (UIFont *)UIFontValue;
使用与CGColorRefValue相同的逻辑返回一个UIFont,同时增加了您可选地通过添加由空格分隔的浮点值来指定字体大小的功能(例如"helvetica 17"或"bold 15")。如果您没有指定字体大小,则将使用默认系统字体大小(在Mac OS中为13点,在iOS中为17点)。
- (UIEdgeInsets)UIEdgeInsetsValue;
- (UIOffset)UIOffsetValue;
返回适当的struct类型。字符串可以包含由空格分隔的浮点数,也可以使用适当的NSStringFromX语法格式化,例如"{top,left,bottom,right}"(与调用NSStringFromUIEdgeInsets()的结果等效)。
- (UIViewContentMode)UIViewContentModeValue;
- (UIViewAutoresizing)UIViewAutoresizingValue;
- (UIBaselineAdjustment)UIBaselineAdjustment;
- (UIControlState)UIControlStateValue;
- (UIControlEvents)UIControlEventsValue;
- (UITextBorderStyle)UITextBorderStyleValue;
- (UITextFieldViewMode)UITextFieldViewModeValue;
- (UIDataDetectorTypes)UIDataDetectorTypesValue;
- (UIScrollViewIndicatorStyle)UIScrollViewIndicatorStyleValue;
- (UITableViewStyle)UITableViewStyleValue;
- (UITableViewScrollPosition)UITableViewScrollPositionValue;
- (UITableViewRowAnimation)UITableViewRowAnimationValue;
- (UITableViewCellStyle)UITableViewCellStyleValue;
- (UITableViewCellSeparatorStyle)UITableViewCellSeparatorStyleValue;
- (UITableViewCellSelectionStyle)UITableViewCellSelectionStyleValue;
- (UITableViewCellEditingStyle)UITableViewCellEditingStyleValue;
- (UITableViewCellAccessoryType)UITableViewCellAccessoryTypeValue;
- (UITableViewCellStateMask)UITableViewCellStateMaskValue;
- (UIButtonType)UIButtonTypeValue;
- (UIBarStyle)UIBarStyleValue;
- (UIBarMetrics)UIBarMetricsValue;
- (UIBarButtonItemStyle)UIBarButtonItemStyleValue;
- (UIBarButtonSystemItem)UIBarButtonSystemItemValue;
- (UITabBarSystemItem)UITabBarSystemItemValue;
返回字符串指定的枚举或位掩码值。对于枚举,这应该是匹配常数值后缀完整名称的单个值(例如"UIViewContentModeScaleAspectFit"或仅"scaleaspectfit")。根据适当的情况,一些别名已提供,例如"fit"代表"scaleaspectfit"。值不区分大小写。对于位掩码类型值,您可以指定由空格分隔的多个值。您还可以使用"none"或"all"。
- (NSPoint)NSPointValue;
- (NSSize)NSSizeValue;
- (NSRect)NSRectValue;
这些都是与CGPoint/Size/RectValue等效物完全相同的。
- (NSColor *)NSColorValue;
使用与CGColorRefValue相同的逻辑返回一个NSColor。
- (NSImage *)NSImageValue;
将字符串作为文件名、路径或URL处理,返回一个NSImage。
- (NSFont *)NSFontValue;
使用与CGColorRefValue相同的逻辑返回一个NSFont,同时增加了您可选地通过添加由空格分隔的浮点值来指定字体大小的功能(例如"helvetica 17"或"bold 15")。如果您没有指定字体大小,则将使用默认系统字体大小。
UIControl的子类通常有一些与特定UIControlState关联的样式属性。例如,为了将UIButton的标题颜色设置为红色,您可以使用以下方法:
[button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
StringCoding通过使用伪属性支持这种类型的样式。为了设置UIControlStateNormal的标题颜色,您可以使用以下任意一种方法:
[control setValueWithString:@"red" forKey:@"titleColor"];
[control setValueWithString:@"red" forKey:@"normalTitleColor"];
要设置选中状态的颜色,您将使用以下方法
[control setValueWithString:@"red" forKey:@"selectedTitleColor"];
因此,在这个情况下,关键字是区分大小写的。这是一个虚拟属性,而不是真正的属性,因此您不能使用以下方法来设置它:
control.selectedTitleColor = [UIColor redColor]; //this won't work
[control setSelectedTitleColor:[UIColor redColor]]; //nor this
要使用字符串绑定动作到一个控件,您可以利用StringCoding提供的某些伪属性。例如,要将名为"showAlert:"的选择器绑定到UIControlEventTouchUpInside,您可以说
[control setValueWithString:@"alert:" forKey:@"touchupinside"];
与其他常量一样,关键字不区分大小写,可以完全限定(例如:"UIControlEventTouchUpInside")或使用简写版本。这是一个虚拟属性,而不是真正的属性,因此您不能使用以下方法来设置它:
control.touchUpInside = @selector(alert:); //this won't work
[control setTouchUpInside:@selector(alert:)]; //nor this
但是,假设您没有禁用swizzling,它可以通过setValue:forKey:或setValue:forKeyPath:来设置,所以这将有效
[control setValue:@"alert:" forKey:@"touchupinside"];
如果您一直在注意,您可能会想知道如何设置动作的目标。目标被设置为一个特殊的代理类,该类将在运行时从响应者链中自动确定目标,因此将消息发送给响应指定的选择器的链中的第一个包含UIResponder(即UIView或UIViewController)。如果视图层次结构发生变化,目标将被重新计算。
除了标准的字符串设置器扩展行为之外,StringCoding还包含一些特殊情况下的伪属性,这些属性可用于使用setValueWithString:forKey设置值。
UITabBarItem
finishedSelectedImage
finishedUnselectedImage
这些属性可用于设置完成的(即后处理过的)标签栏图像。
UIWebView
request
HTMLString
baseURL
这些属性可用于使用字符串设置器将特定的请求URL、HTML字符串或数据对象加载到WebView中。可选的基本URL用作任何随后的请求、HTML或数据值的相对值。
StringCoding仅支持有限的价值类型。为了支持添加的类型,请使用类别扩展NSString的新值方法。
- (<type>)<typeName>Value;
例如,为了支持名为NSFoo的类,您将添加一个形式为的方法
- (NSFoo *)NSFooValue;
为了支持Core Foundation对象类型,省略“Ref”,例如对于CGFooRef类型的类型,使用
- (CGFooRef)CGFooValue;
现在,任何对象的这种类型的任何属性都可以自动使用通过setValueWithString:forKey:方法通过字符串值设置。如果属性类型是未知的,则不会按这种方式工作。StringCoding将自动检测并支持通过类别或子类添加的属性,尽管它并不能总是确定类型。
例如,CALayer的内容属性应该是图像,但它定义为id,所以StringCoder不能自动确定类型。这也适用于期望常量值的属性,因为类型显示为整数或字符串。
为了解决这个问题,您可以添加一个类别来定义的设置方法
- (void)set<propertyName>asString:(NSString *)stringValue;
所以,对于CALayer的内容属性,方法被定义如下
- (void)setContentsAsString:(NSString *)stringValue;
实现将值视为图像。setValueWithString:forKey:方法会自动检测该方法的存在并调用它而不是默认实现。
默认情况下,StringCoding混编了setValue:forKey:
和setValue:forKeyPath:
方法,以便更容易使用(例如,这意味着您可以在Interface Builder中通过字符串值设置对象)。如果您不希望这种行为,请不要恐慌,您可以通过在构建设置中添加以下预编译器宏来禁用它
SC_SWIZZLE_ENABLED=0
或者,如果您愿意,将其添加到您的prefix.pch文件中
#define SC_SWIZZLE_ENABLED 0
版本 1.2.2
版本 1.2.1
版本 1.2
版本 1.1
版本 1.0