变更记录
方案名称 语法 - 使用字面量
关键字 语法 \ 字面量 \ 字面值
需求场景
提高代码可读性
参考链接
IOS使用字面值
Swifter - 字面量转换
GitHub - Literally
Clang 3.9 documentation - Objective-C Literals
详细内容 #####1. Swift 解决方案
#####NSString
#####Number
1 2 let aNumber : NSNumber = 3 let aBool : NSNumber = true
#####NSArray
#####Dictionary
1 let aDictionary = ["key1" : "value1" , "key2" : "value2" ]
Swift 为我们提供了一组非常有意思的接口,用来将字面量转换为特定的类型。对于那些实现了字面量转换接口的类型,在提供字面量赋值的时候,就可以简单地按照接口方法中定义的规则“无缝对应”地转换为这些类型。这些接口包括了各个原生的字面量,它们是:
ArrayLiteralConvertible
BooleanLiteralConvertible
CharacterLiteralConvertible
DictionaryLiteralConvertible
ExtendedGraphemeClusterLiteralConvertible
FloatLiteralConvertible
NilLiteralConvertible
IntegerLiteralConvertible
StringLiteralConvertible
StringInterpolationConvertible
用法举例:
通常通过 NSString 定义一个 NSURL 的方法如下
1 let url = NSURL (string: "http://swifter.tips" )
使用 StringLiteralConvertible 构造一个 NSURL 的 extension
1 2 3 4 5 6 7 8 9 10 11 12 13 extension NSURL : StringLiteralConvertible { public class func convertFromStringLiteral (value : String ) -> Self { return self (string: value) } public class func convertFromExtendedGraphemeClusterLiteral (value : String ) -> Self { return self (string: value) } }
那么我们现在可以直接使用如下方式直接赋值 NSString 生成 NSURL
1 let url: NSURL = "http://swifter.tips"
#####2. Objective-C 解决方案
#####NSString
1 2 3 4 5 NSString *str = [[NSString alloc] initWithFormat:@"%@",@"Hello World"]; //---->字面值如下 NSString *str = @"Hello World";
#####Number
1 2 3 4 5 6 7 8 9 NSNumber *someNumber = [NSNumber numberWithInt:1]; //---->字面值如下 NSNumber *intNumber = @1; NSNumber *floatNumber = @2.5f; NSNumber *doubleNumber = @3.14159; NSNumber *boolNumber = @YES; NSNumber *charNumber = @'a';
#####NSArray
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 NSArray *animals =[NSArray arrayWithObjects:@"cat", @"dog", @"mouse", @"badger", nil]; //---->字面值如下 NSArray *animals = @[@"cat", @"dog", @"mouse", @"badger"]; NSString *dog = [animals objectAtIndex:1]; //---->通过字面值取数据 NSString *dog = animals[1]; //可变的话可以直接设置新值 [mutableArray replaceObjectAtIndex:1 withObject:@"dog"]; //---->字面值设置值 mutableArray[1] = @"dog"; NSString *str1; NSString *str2 = @"1"; NSString *str3 = @"1"; //插入空数据会抛出异常 NSArray *arr = @[str1,str2,str3]; //reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]' //这种方式不会抛异常,但是数组会收到第一个nil就终止了。所以采用字面值形式会得到错误提示。 NSArray *arr = [NSArray arrayWithObjects:str1,str2,str3, nil]; NSLog(@"arr.count=%d",arr.count); //0 NSLog(@"arr.first=%@",arr.firstObject); //null
#####Dictionary
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 NSDictionary *personData =[NSDictionary dictionaryWithObjectsAndKeys:@"Kevin", @"firstName",@"Jin", @"lastName",[NSNumber numberWithInt:25], @"age", nil]; //---->字面值如下 NSDictionary *personData = @{@"firstName" : @"Kevin",@"lastName" : @"Jin", @"age" : @25}; NSString *str1; NSString *str2 = @"1"; NSString *str3 = @"1"; //和数组一样,value不能有nil ,否则就会抛出异常。 NSDictionary *dic =@{@"str1":str1,@"str2":str2,@"str3":str3}; //reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]' //不会提示你错误 NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:str1,@"str2",str2,@"str2",str3,@"str3", nil]; NSLog(@"dic.count=%d",dic.count); //0 //取值 NSString *lastName = [personData objectForKey:@"lastName"]; //---->字面值取值 NSString *lastName = personData[@"lastName"]; //可变的话可以这样设置新值 [mutableDictionary setObject:@"Galloway" forKey:@"lastName"]; //---->字面值设置值 mutableDictionary[@"lastName"] = @"Galloway";
效果图 (无)
备注 访问的时候数组采用下标方式,字典直接通过 Key 来取值,需要注意的就是数组和字典中不能插入 nil,否则会抛出异常。
字面量语法可以读写 mutable 类型的对象,但通过字面量语法创建的对象是非 mutable 的。如果需要将非 mutable 类的字面量对象变更为 mutable 类型,可以使用 mutableCopy 方法。
1 NSMutableArray *mutable = [@[@1, @2, @3, @4, @5] mutableCopy];
自定义的字面量语法对象的子类不支持字面量语法。
以下为Github上的常用 Swift 字面量转换例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 import Foundationextension NSCharacterSet : ArrayLiteralConvertible { public class func convertFromArrayLiteral (characters : Character ...) -> Self { return self (charactersInString: join("" , characters.map({String ($0 )}))) } } extension NSCharacterSet : StringLiteralConvertible { typealias ExtendedGraphemeClusterLiteralType = StringLiteralType public class func convertFromExtendedGraphemeClusterLiteral (value : StringLiteralType ) -> Self { return self (charactersInString: value) } public class func convertFromStringLiteral (value : StringLiteralType ) -> Self { return self (charactersInString: value) } } extension NSExpression : StringLiteralConvertible { typealias ExtendedGraphemeClusterLiteralType = StringLiteralType public class func convertFromExtendedGraphemeClusterLiteral (value : StringLiteralType ) -> Self { return self (format: value, argumentArray: []) } public class func convertFromStringLiteral (value : StringLiteralType ) -> Self { return self (format: value, argumentArray: []) } } extension NSIndexPath : ArrayLiteralConvertible { public class func convertFromArrayLiteral (indexes : Int ...) -> Self { return self (indexes: indexes, length: indexes.count) } } extension NSIndexSet : ArrayLiteralConvertible { public class func convertFromArrayLiteral (indexes : Int ...) -> Self { var mutableIndexSet = NSMutableIndexSet () for index in indexes { mutableIndexSet.addIndex(index) } return self (indexSet: mutableIndexSet) } } extension NSNull : NilLiteralConvertible { public class func convertFromNilLiteral () -> Self { return self () } } extension NSOrderedSet : ArrayLiteralConvertible { public class func convertFromArrayLiteral (elements : AnyObject ...) -> Self { return self (array: elements) } } extension NSPredicate : StringLiteralConvertible { typealias ExtendedGraphemeClusterLiteralType = StringLiteralType public class func convertFromExtendedGraphemeClusterLiteral (value : StringLiteralType ) -> Self { return self (format: value, argumentArray: []) } public class func convertFromStringLiteral (value : StringLiteralType ) -> Self { return self (format: value, argumentArray: []) } } extension NSRegularExpression : StringLiteralConvertible { typealias ExtendedGraphemeClusterLiteralType = StringLiteralType public class func convertFromExtendedGraphemeClusterLiteral (value : StringLiteralType ) -> Self { return self (pattern: value, options: nil , error: nil ) } public class func convertFromStringLiteral (value : StringLiteralType ) -> Self { return self (pattern: value, options: nil , error: nil ) } } extension NSScanner : StringLiteralConvertible { typealias ExtendedGraphemeClusterLiteralType = StringLiteralType public class func convertFromExtendedGraphemeClusterLiteral (value : StringLiteralType ) -> Self { return self (string: value) } public class func convertFromStringLiteral (value : StringLiteralType ) -> Self { return self (string: value) } } extension NSSet : ArrayLiteralConvertible { public class func convertFromArrayLiteral (elements : AnyObject ...) -> Self { return self (array: elements) } } extension NSTimeZone : StringLiteralConvertible { typealias ExtendedGraphemeClusterLiteralType = StringLiteralType public class func convertFromExtendedGraphemeClusterLiteral (value : StringLiteralType ) -> Self { return self (name: value) } public class func convertFromStringLiteral (value : StringLiteralType ) -> Self { return self (name: value) } } extension NSURL : StringLiteralConvertible { typealias ExtendedGraphemeClusterLiteralType = StringLiteralType public class func convertFromExtendedGraphemeClusterLiteral (value : StringLiteralType ) -> Self { return self (string: value) } public class func convertFromStringLiteral (value : StringLiteralType ) -> Self { return self (string: value) } } #if os(iOS)import UIKitextension UIColor : IntegerLiteralConvertible { public class func convertFromIntegerLiteral (value : IntegerLiteralType ) -> Self { let red = CGFloat ((value & 0xFF0000 ) >> 16 ) / 255.0 let green = CGFloat ((value & 0x00FF00 ) >> 8 ) / 255.0 let blue = CGFloat (value & 0x0000FF ) / 255.0 let alpha = CGFloat (1.0 ) return self (red: red, green: green, blue: blue, alpha: alpha) } } extension UIImage : StringLiteralConvertible { typealias ExtendedGraphemeClusterLiteralType = StringLiteralType public class func convertFromExtendedGraphemeClusterLiteral (value : StringLiteralType ) -> Self { return self (named: value) } public class func convertFromStringLiteral (value : StringLiteralType ) -> Self { return self (named: value) } } #endif #if os(OSX )import Cocoaextension NSColor : IntegerLiteralConvertible { public class func convertFromIntegerLiteral (value : IntegerLiteralType ) -> Self { let red = CGFloat ((value & 0xFF0000 ) >> 16 ) / 255.0 let green = CGFloat ((value & 0x00FF00 ) >> 8 ) / 255.0 let blue = CGFloat (value & 0x0000FF ) / 255.0 let alpha = CGFloat (1.0 ) return self (red: red, green: green, blue: blue, alpha: alpha) } } #endif