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__NSCFStringaaaaaa
可见,如果传入的是 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 letfunc 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 UIKitclass 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语法糖系列,所以首先讲讲什么是语法糖.语法糖是一种几乎每种语言或多或少都提供过的一些方便程序员开发代码的语法,它只是编译器实现的一些小把戏罢了,编译期间以特定的 ...
随机推荐
- git-flow工作流程
什么是 git-flow? 一旦安装安装 git-flow,你将会拥有一些扩展命令.这些命令会在一个预定义的顺序下自动执行多个操作.是的,这就是我们的工作流程! git-flow 并不是要替代 Git ...
- SimpleDateFormat实现String与Date之间的转换
基本用法: java.text.SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd"); java.util.Date ...
- java之throw和throws
抛出异常有三种形式,一是throw,一个throws,还有一种系统自动抛异常.下面它们之间的异同. 一.系统自动抛异常 当程序语句出现一些逻辑错误.主义错误或类型转换错误时,系统会自动抛出异常:(举个 ...
- zw版【转发·台湾nvp系列Delphi例程】HALCON MoveRectangle2
zw版[转发·台湾nvp系列Delphi例程]HALCON MoveRectangle2 procedure TForm1.Button1Click(Sender: TObject);var img ...
- 【android】开发中遇到的一些问题
1:华为输入法,输入框为ACTION_DONE模式,ActionId是 UNSPECIFIED EditText对象.setImeOptions(EditorInfo.IME_ACTION_DONE) ...
- nats
NATS is a family of open source products that are tightly integrated but can be deployed independent ...
- springcloud12---sidecar
Sidecar:异构平台整合.做了一个桥 package com.itmuch.cloud; import org.springframework.boot.SpringApplication; im ...
- C++虚函数分析
1.虚函数(impure virtual) c++虚函数主要是提供“运行时多态”,父类提供虚函数的默认实现,子类可以虚函数进行重写. 2.纯虚函数(pure virtual) c++纯虚函 ...
- AVAudioFoundation(5):音视频导出
本文转自:AVAudioFoundation(5):音视频导出 | www.samirchen.com 本文主要内容来自 AVFoundation Programming Guide. 要读写音视频数 ...
- 安装Git【转】
本文转载自:http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 最早Git是在Linu ...