转载作者 香蕉大大 (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语法糖 简单却不那么简单的更多相关文章

  1. 第十三节:实际开发中使用最多的监视锁Monitor、lock语法糖的扩展、混合锁的使用(ManualResetEvent、SemaphoreSlim、ReaderWriterLockSlim)

    一. 监视锁(Monitor和lock) 1. Monitor类,限定线程个数的一把锁,两个核心方法: Enter:锁住某个资源. Exit:退出某一个资源. 测试案例:开启5个线程同时对一个变量进行 ...

  2. Vue3 Composition API写烦了,试试新语法糖吧—setup script

    前言 Vue3发布近一年了,相信大家对Vue3的新特性,新语法都很熟悉了.那么在使用Composition API的过程中,有没有觉得整个过程比较繁琐.比如你的模板里用到了大量的state和方法的时候 ...

  3. C# 9 record 并非简单属性 POCO 的语法糖

    C# 9 record 并非简单属性 POCO 的语法糖 最近升级专案到大统一 .NET 5 并使用 C#9 语法尝试改写套件,发现之前以为 record 只是简单属性 POCO 的简化语法糖的认知是 ...

  4. iOS开发UI篇—UITableview控件简单介绍

    iOS开发UI篇—UITableview控件简单介绍 一.基本介绍 在众多移动应⽤用中,能看到各式各样的表格数据 . 在iOS中,要实现表格数据展示,最常用的做法就是使用UITableView,UIT ...

  5. 李洪强iOS开发Swift篇---12_NSThread线程相关简单说明

    李洪强iOS开发Swift篇---12_NSThread线程相关简单说明 一 说明 1)关于多线程部分的理论知识和OC实现,在之前的博文中已经写明,所以这里不再说明. 2)该文仅仅简单讲解NSThre ...

  6. qt-qml移动开发之在ios上开发和部署app流程简单介绍

    qt5.3已经全面支持移动开发,除了mac,windows,linux.还支持ios,android,wp,meego等移动平台,本教程是作者依据自己的经验,从头讲怎么样在ios上公布自己的app.因 ...

  7. 看看C# 6.0中那些语法糖都干了些什么(终结篇)

    终于写到终结篇了,整个人像在梦游一样,说完这一篇我得继续写我的js系列啦. 一:带索引的对象初始化器 还是按照江湖老规矩,先扒开看看到底是个什么玩意. 1 static void Main(strin ...

  8. C#语法糖,让编程更具乐趣

    一.什么是语法糖 语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法 ...

  9. Java语法糖1:可变长度参数以及foreach循环原理

    语法糖 接下来几篇文章要开启一个Java语法糖系列,所以首先讲讲什么是语法糖.语法糖是一种几乎每种语言或多或少都提供过的一些方便程序员开发代码的语法,它只是编译器实现的一些小把戏罢了,编译期间以特定的 ...

随机推荐

  1. POJ1523:SPF(无向连通图求割点)

    题目:http://poj.org/problem?id=1523 题目解析: 注意题目输入输入,防止PE,题目就是求割点,并问割点将这个连通图分成了几个子图,算是模版题吧. #include < ...

  2. STL学习笔记--算法

    关于STL算法需要注意的是: (1) 所有STL算法被设计用来处理一个或多个迭代器区间.第一个区间通常以起点和终点表示,至于其他区间,多数情况下只需提供起点即可,其终点可自动以第一区间的元素数推导出来 ...

  3. 分布式存储之MogileFS基于Nginx实现负载均衡(Nginx+MogileFS)

    MogileFS分布式文件系统特点: 1.具有raid的性能 2.不存在单点故障 3.简单的命名空间: 每个文件对应一个key:用于domain定义名称空间 4.不共享任何数据 5.传输中立,无特殊协 ...

  4. 2018-2019 ACM-ICPC, Asia Seoul Regional Contest

    ProblemA Circuits Solved. 题意: 有$n$个矩形,可以放两条平行与$x$轴的线,求怎么放置两条无线长的平行于$x$轴的线,使得他们与矩形相交个数最多 如果一个矩形同时与两条线 ...

  5. css 文档流中块级非替换元素水平区域的计算规则(1)

    最近在读<Basic Visual Formatting in CSS>,结合以前看的<css权威指南>和css标准.今天就做个笔记. 以前在遇到一些宽度不明确指明的一些布局的 ...

  6. 20145329 《网络对抗技术》 逆向及Bof基础实验

    1.实验内容 本次实践的对象是一个名为20145329的linux可执行文件.该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串.该程序同时包含另一个代码片段,ge ...

  7. FMC简介

    FMC简介 FMC ( FPGA Mezzanine Card ) 简而言之,是具有特定功能的子卡模块. Developed by a consortium of companies ranging ...

  8. IntelliJ IDEA 中配置lombok插件,编写简略风格Java代码

    1.打开IDEA的Settings面板,并选择Plugins选项,然后点击 “Browse repositories..” 2.开启注释处理 3.在pom.xml中添加lombox <!-- h ...

  9. splay入门教程

    笔者一个数据结构的蒟蒻还是奇迹般的搞明白了splay的基本原理以及实现方法,所以写下这篇随笔希望能帮到像我当初一脸懵逼的人. 我们从二叉查找树开始说起: 二叉查找树是一棵二叉树,它满足这样一个性质:所 ...

  10. MyBatis的简单入门学习

    一个新知识开始是最难学的.(万事开头难) MyBatis大体分三层,接口层,数据处理层,基础支撑层. 其中接口层不是java中的那个interface,而是框架和程序员之间的对接.一个API,程序员可 ...