iOS语法糖 简单却不那么简单
转载作者 香蕉大大 (Github)
开发过程中我特别喜欢用语法糖,原因很简单,懒得看到一堆长长的代码,但是语法糖我今天无意中看到更有意思的玩法.这里暂时吧把今天新学到的知识点整理一下希望大家喜欢,如果有更好的补充希望能和我说下,我希望更更加好的完善。
语法糖
(Syntactic sugar
),也译为糖衣语法
,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。
本文的目录如下
OC语法糖
基础
@[],@{}用法在NSArray,NSDictionary,NSNumber使用!重点!
@()使用!重点!
语法糖在UI中的使用方法
swift
基础
if let 与 guard 语法糖基础
语法糖Selector例子
OC语法糖
常用基础使用部分@[],@{}这两部分的用法
1.一般数组的初始化和访问数组元素是这样的在之前的博客中我是这样初始化NSArray的:
1
2
3
4
|
//NSArray的便利初始化 NSArray *array1 = [[NSArray alloc] initWithObjects:@ "aaa" , @ "bbb" , @ "ccc" , nil]; //NSArray的便利构造器 NSArray *array2 = [NSArray arrayWithObjects:@ "111" , @ "222" , @ "333" , nil]; |
获取数组的元素
1
2
3
|
//获取相应索引的元素 id element = [array1 objectAtIndex:0]; NSLog(@ "array1_count = %d, array[0] = %@" , count, element); |
简化后的数组初始化和访问的做法如下
1
2
3
4
5
6
7
|
//NSArray的定义 NSArray *array = @[@ "lu" , @ "da" , @ "shi" , @YES, @123]; int count = ( int )[array count]; for ( int i = 0; i < count; i++) { NSLog(@ "%@" , array[i]); } |
2.对字典(NSDictionary)的简化也引用我之前博客中得一段代码吧
1
2
3
4
5
|
//不可变字典的初始化 NSDictionary *dictionay = [NSDictionary dictionaryWithObjectsAndKeys:@ "value1" , @ "key1" , @ "value2" , @ "key2" , nil]; id value = [dictionay objectForKey:@ "key1" ]; NSLog(@ "key1 => %@" , value); |
我们还可以这样做
1
2
3
4
5
6
7
|
//NSDictionary的定义简化 NSDictionary *dictionary = @{ @ "key0" : @ "value0" , @ "key1" : @ "value1" , @ "key2" : @ "value2" }; NSLog(@ "key2 => %@" , dictionary[@ "key2" ]); |
3.对NSNumber简化
我们可以这样做
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
把基本类型包装成对象的便利构造函数 -(id) initWithChar : ( char ) value; -(id) initWithInt : ( int ) value; -(id) initWithFloat : ( float ) value; -(id) initWithBool: ( BOOL ) value; 把基本数据类型包装成对象的便利构造器 +(id) numberWithChar : ( char ) value; +(id) numberWithInt : ( int ) value; +(id) numberWithFloat : ( float ) value; +(id) numberWithBool : ( BOOL ) value; |
我们也可以这样做,说明:在char转换为NSNumber是存的是ASCII码的形式,c输出为97
1
2
3
4
5
|
//NSNumber的简化 NSNumber *a = @123; NSNumber *b = @11.2; NSNumber *c = @( 'a' ); NSLog(@ "a = %@, b = %@, c = %@" , a, b, c); |
针对以上部分的简单练习
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
|
//NSNumber的语法糖 NSNumber *intNumber = [NSNumber numberWithInt:100]; NSNumber *intNumber2 = @100; //不可变字符串的语法糖 NSString *string = @ "hanjunqiang" ; //可变字符串的语法糖 NSMutableString *mString = @ "大爱中华" .mutableCopy; //后缀不能丢 //不可变数组的语法糖 NSArray *array = @[@ "1" ,@ "2" ,@ "3" ,@ "4" ]; NSLog(@ "%@" ,array); //访问数组元素的语法糖 NSLog(@ "%@" ,array[1]); //可变数组的语法糖 NSMutableArray *mArray = @[@ "1" ,@ "2" ,@ "3" ,@ "4" ].mutableCopy; //字典的语法糖 //字典对象[key值]取出对应的value值 NSDictionary *dict = @{@ "a" :@ "1" ,@ "b" :@ "2" }; //key值在冒号前,value值在冒号后 NSLog(@ "%@" ,dict); NSLog(@ "%@" ,dict[@ "a" ]); //可变字典可以赋值和修改值 NSMutableDictionary *mDic = @{@ "a" :@ "1" ,@ "b" :@ "2" }.mutableCopy; mDic[@ "a" ]=@ "100" ; NSLog(@ "%@" ,mDic[@ "a" ]); |
@()介绍以及使用
在 Objective-C 中我们可以用 @”foo” 来创建一个 NSString 常量,看起来似乎平淡无奇。
但它背后其实比想象的精彩,@ 可以被理解成一个特殊的宏,其接受一个 C 字符串作为参数,也可写作 @(“foo”)。
之所以说 @ 是一个特殊的宏,是因为其能根据传入的 C 字符串类型不同——C 字符串常量或 C 字符串——在运行时构建返回不同类型的 NSString,
参见下面的代码:
1
2
3
4
5
6
7
8
9
|
char * obtain_c_string( void ) { return "c_string" ; } NSLog(@ "%@" , @ "foo" . class ); NSLog(@ "%@" , @( "bar" ). class ); NSLog(@ "%@" , @(obtain_c_string()). class ); NSLog(@ "%@" ,@ "aaa" ); NSLog(@ "%@" ,@( "aaa" )); |
输出如下__NSCFConstantString
__NSCFConstantString
__NSCFString
aaa
aaa
可见,如果传入的是 C 字符串常量,运行时
构建的则为 NSConstantString
;如果传入的是C 字符串
则创建的是 NSString
。
众所周知,Objective-C 代码里有很多地方需要我们把代码中的一些文法串写成字符串再作为传入参数,比如 KVO 中的 keyPath 参数往往就要传入形如 propertyA.propertyB 的字符串,从实用角度出发这有两个弊端: 写字符串的时候没有代码提示,很容易写错 即便一开始写对了,如果后来相关类重构了,keyPath 的参数便失效了,而 Xcode Refactor 无法扫描字符串 当我们理解了 @(),再加上自定义的宏,上述两个问题便可迎刃而解。
1
2
3
4
5
6
7
|
/** * # 将宏的参数字符串化,C 函数 strchr 返回字符串中第一个 '.' 字符的位置 */ #define Keypath(keypath) (strchr(#keypath, '.') + 1) // 有代码提示,可以被重构扫描到 [objA addObserver: objB forKeyPath: @Keypath(ObjA.property1.property2) options: nil context: nil]; |
UI使用部分
拿UIImageView来做例子,原来创建对象和下面一致
1
2
3
4
5
|
self.imageView = [[UIImageView alloc] init]; self.imageView.backgroundColor = [UIColor redColor]; self.imageView.image = [UIImage imageNamed:@ "12345" ]; self.imageView.frame = CGRectMake(0, 0, 100, 100); [self.view addSubview:self.imageView]; |
重点来了
这个就是语法糖在UI中创建对象的使用,瞬间感觉很高大上~
1
2
3
4
5
6
7
8
|
self.imageView = ({ UIImageView *imageView = [[UIImageView alloc] init]; imageView.backgroundColor = [UIColor redColor]; imageView.image = [UIImage imageNamed:@ "12345" ]; imageView.frame = CGRectMake(0, 0, 100, 100); [self.view addSubview:imageView]; imageView; }); |
swift语法糖
if let 与 guard 语法糖
话说if let 和 guard 只是语法糖,没有也可以,但有了可以使得代码更简洁方便。要理解 if let 和 guard,不妨设想假如没有这两者,代码会怎么写。
1
2
3
4
5
6
7
8
9
|
if let func doSomething(str: String?) { let v: String! = str if v != nil { // use v to do something } } |
Swift 中因为有optional, 经常需要判断是否为空。假如没有if let,大致写成上面的样子,有了if let, 可以改写成
1
2
3
4
5
6
7
|
func doSomething(str: String?) { if let v = str { // use v to do something } } |
上面两段代码的控制流是一样的。对照着,可以看出if let的写法更加简洁方便。
1
2
3
4
5
6
7
8
9
10
11
12
|
guard 假如 if 中出现的代码很长,我们写代码时可以将错误情况先返回。比如: func doSomething(str: String?) { let v: String! = str if v == nil { return } // use v to do something } |
这样做可以避免过多的嵌套。上面代码实在太常见了,swift也提供一个guard这个语法糖,用guard可以改写成:
1
2
3
4
|
func doSomething(str: String?){ guard let v = str else { return } // use v to do something } |
上面两段代码的控制流是一样的。也可以看出guard的写法更加简洁方便。
至于if let 和 guard 语法中出现的where,只是附加一些条件。相当于逻辑运算 && 和 ||。SQL中的条件语法也是用where这个关键字。
假如还不理解,动手将一段代码,不用if let 和 guard 进行改写。试多几次,就会发觉很自然了。
语法糖Selector例子
创建控制器,添加Button
1
2
3
4
5
6
7
8
9
10
11
12
|
override func viewDidLoad() { super.viewDidLoad() let btn = UIButton(frame: CGRectMake(100,100,100,100)) btn.backgroundColor = UIColor.redColor() view.addSubview(btn) } func printFire() { print( "fire" ) } |
想实现控制器里的Button点击事件,但是,如果一个控制器里的Button特别的多,那添加Button点击事件的Selector 会觉得特别的臃肿。所以语法糖就是要拓展Selector
1
2
3
4
5
|
private extension Selector { static let printFire = #selector(ViewController.printFire) } |
我们现在给viewDidLoad方法中的Button 添加点击事件
1
|
btn.addTarget(self, action: .printFire, forControlEvents: .TouchUpInside) |
如果Button过多的话,用语法糖方便管理Button的点击事件,又不会把点击事件变得过于臃肿
下面是控制器的完整代码
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
|
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let btn = UIButton(frame: CGRectMake(100,100,100,100)) btn.backgroundColor = UIColor.redColor() btn.addTarget(self, action: .printFire, forControlEvents: .TouchUpInside) view.addSubview(btn) } func printFire() { print( "fire" ) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } } private extension Selector { static let printFire = #selector(ViewController.printFire) } |
iOS语法糖 简单却不那么简单的更多相关文章
- 第十三节:实际开发中使用最多的监视锁Monitor、lock语法糖的扩展、混合锁的使用(ManualResetEvent、SemaphoreSlim、ReaderWriterLockSlim)
一. 监视锁(Monitor和lock) 1. Monitor类,限定线程个数的一把锁,两个核心方法: Enter:锁住某个资源. Exit:退出某一个资源. 测试案例:开启5个线程同时对一个变量进行 ...
- Vue3 Composition API写烦了,试试新语法糖吧—setup script
前言 Vue3发布近一年了,相信大家对Vue3的新特性,新语法都很熟悉了.那么在使用Composition API的过程中,有没有觉得整个过程比较繁琐.比如你的模板里用到了大量的state和方法的时候 ...
- C# 9 record 并非简单属性 POCO 的语法糖
C# 9 record 并非简单属性 POCO 的语法糖 最近升级专案到大统一 .NET 5 并使用 C#9 语法尝试改写套件,发现之前以为 record 只是简单属性 POCO 的简化语法糖的认知是 ...
- iOS开发UI篇—UITableview控件简单介绍
iOS开发UI篇—UITableview控件简单介绍 一.基本介绍 在众多移动应⽤用中,能看到各式各样的表格数据 . 在iOS中,要实现表格数据展示,最常用的做法就是使用UITableView,UIT ...
- 李洪强iOS开发Swift篇---12_NSThread线程相关简单说明
李洪强iOS开发Swift篇---12_NSThread线程相关简单说明 一 说明 1)关于多线程部分的理论知识和OC实现,在之前的博文中已经写明,所以这里不再说明. 2)该文仅仅简单讲解NSThre ...
- qt-qml移动开发之在ios上开发和部署app流程简单介绍
qt5.3已经全面支持移动开发,除了mac,windows,linux.还支持ios,android,wp,meego等移动平台,本教程是作者依据自己的经验,从头讲怎么样在ios上公布自己的app.因 ...
- 看看C# 6.0中那些语法糖都干了些什么(终结篇)
终于写到终结篇了,整个人像在梦游一样,说完这一篇我得继续写我的js系列啦. 一:带索引的对象初始化器 还是按照江湖老规矩,先扒开看看到底是个什么玩意. 1 static void Main(strin ...
- C#语法糖,让编程更具乐趣
一.什么是语法糖 语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法 ...
- Java语法糖1:可变长度参数以及foreach循环原理
语法糖 接下来几篇文章要开启一个Java语法糖系列,所以首先讲讲什么是语法糖.语法糖是一种几乎每种语言或多或少都提供过的一些方便程序员开发代码的语法,它只是编译器实现的一些小把戏罢了,编译期间以特定的 ...
随机推荐
- wordpress的安装及使用
1.如何查看别人的wordpress站点所有的模板 2.如何使用自定义的模板
- 记录:EPALN Electric P8 2.4.4.8366 安装记录
系统:win7 32位 旗舰版. (原版系统 非GHOST) 第一步:解压安装. setup.exe 右击 选择 注意:把 360 百度 杀毒之类的全部关闭 第二步: 第三步: 第四步: 第五 ...
- CodeForces - 366C Dima and Salad (01背包)
题意:n件东西,有属性a和属性b.要选取若干件东西,使得\(\frac{\sum a_j}{\sum b_j} = k\).在这个条件下,问\(\sum a_j\)最大是多少. 分析:可以将其转化为0 ...
- HIVE: 自定义TextInputFormat (旧版MapReduceAPI ok, 新版MapReduceAPI实现有BUG?)
我们的输入文件 hello0, 内容如下: xiaowang 28 shanghai@_@zhangsan 38 beijing@_@someone 100 unknown 逻辑上有3条记录, 它们以 ...
- ng-深度学习-课程笔记-11: 卷积神经网络(Week1)
1 边缘检测( edage detection ) 下图是垂直边缘检测的例子,实际上就是用一个卷积核进行卷积的过程. 这个例子告诉我们,卷积可以完成垂直方向的边缘检测.同理卷积也可以完成水平方向的边缘 ...
- Flask Web 开发 错误页面自定义
如果要自定义错误画面,无法大多数情况是自定义404和500的情况 首先,要在路由中设置 通过app.error_handler这个装饰器来绑定响应函数 @main.errorhandler(404) ...
- bzoj1622 / P2908 [USACO08OPEN]文字的力量Word Power
P2908 [USACO08OPEN]文字的力量Word Power 第一眼:AC自动机(大雾) 直接暴力枚举即可. 用<cctype>的函数较方便(还挺快) $isalpha(a)$:$ ...
- 百度语音识别vs科大讯飞语音识别
一.结果 从笔者试验的结果来看,科大讯飞的语音识别技术远超百度语音识别 二.横向对比 科大讯飞语音识别 百度语音识别 费用 各功能的前5小时免费 全程免费 转换精准率 非常高 比较低 linux ...
- fiddler几种功能强大的用法(二)
参考网址:http://blog.rekfan.com/articles/228.html http://www.cnblogs.com/tugenhua0707/p/4637771.html htt ...
- python 字典输出键值对
d = {, , } for dict_key, dict_value in d.items(): print(dict_key,'->',dict_value)