LAZY 修饰符和 LAZY 方法

由 王巍 (@ONEVCAT) 发布于 2015/10/07

延时加载或者说延时初始化是很常用的优化方法,在构建和生成新的对象的时候,内存分配会在运行时耗费不少时间,如果有一些对象的属性和内容非常复杂的话,这个时间更是不可忽略。另外,有些情况下我们并不会立即用到一个对象的所有属性,而默认情况下初始化时,那些在特定环境下不被使用的存储属性,也一样要被初始化和赋值,也是一种浪费。

在其他语言 (包括 Objective-C) 中延时加载的情况是很常见的。我们在第一次访问某个属性时,判断这个属性背后的存储是否已经存在,如果存在则直接返回,如果不存在则说明是首次访问,那么就进行初始化并存储后再返回。这样我们可以把这个属性的初始化时刻推迟,与包含它的对象的初始化时刻分开,以达到提升性能的目的。以 Objective-C 举个例子 (虽然这里既没有费时操作,也不会因为使用延时加载而造成什么性能影响,但是作为一个最简单的例子,可以很好地说明问题):

// ClassA.h
@property (nonatomic, copy) NSString *testString; // ClassA.m
- (NSString *)testString {
if (!_testString) {
_testString = @"Hello";
NSLog(@"只在首次访问输出");
}
return _testString;
}

在初始化 ClassA 对象后,_testString 是 nil。只有当首次访问 testString 属性时 getter 方法会被调用,并检查如果还没有初始化的话,就进行赋值。为了方便确认,我们还在赋值时打印了一句 log。我们之后再多次访问这个属性的话,因为 _testString 已经有值,因此将直接返回。

在 Swift 中我们使用在变量属性前加 lazy 关键字的方式来简单地指定延时加载。比如上面的的代码我们在 Swift 中重写的话,会是这样:

class ClassA {
lazy var str: String = {
let str = "Hello"
print("只在首次访问输出")
return str
}()
}

我们在使用 lazy 作为属性修饰符时,只能声明属性是变量。另外我们需要显式地指定属性类型,并使用一个可以对这个属性进行赋值的语句来在首次访问属性时运行。如果我们多次访问这个实例的str 属性的话,可以看到只有一次输出。

为了简化,我们如果不需要做什么额外工作的话,也可以对这个 lazy 的属性直接写赋值语句:

lazy var str: String = "Hello"

相比起在 Objective-C 中的实现方法,现在的 lazy 使用起来要方便得多。

另外一个不太引起注意的是,在 Swift 的标准库中,我们还有一组 lazy 方法,它们的定义是这样的:

func lazy<S : SequenceType>(s: S) -> LazySequence<S>

func lazy<S : CollectionType where S.Index : RandomAccessIndexType>(s: S)
-> LazyRandomAccessCollection<S> func lazy<S : CollectionType where S.Index : BidirectionalIndexType>(s: S)
-> LazyBidirectionalCollection<S> func lazy<S : CollectionType where S.Index : ForwardIndexType>(s: S)
-> LazyForwardCollection<S>

这些方法可以配合像 map 或是 filter 这类接受闭包并进行运行的方法一起,让整个行为变成延时进行的。在某些情况下这么做也对性能会有不小的帮助。例如,直接使用 map 时:

let data = 1...3
let result = data.map {
(i: Int) -> Int in
print("正在处理 \(i)")
return i * 2
} print("准备访问结果")
for i in result {
print("操作后结果为 \(i)")
} print("操作完毕")

这么做的输出为:

// 正在处理 1
// 正在处理 2
// 正在处理 3
// 准备访问结果
// 操作后结果为 2
// 操作后结果为 4
// 操作后结果为 6
// 操作完毕

而如果我们先进行一次 lazy 操作的话,我们就能得到延时运行版本的容器:

let data = 1...3
let result = data.lazy.map {
(i: Int) -> Int in
print("正在处理 \(i)")
return i * 2
} print("准备访问结果")
for i in result {
print("操作后结果为 \(i)")
} print("操作完毕")

此时的运行结果:

// 准备访问结果
// 正在处理 1
// 操作后结果为 2
// 正在处理 2
// 操作后结果为 4
// 正在处理 3
// 操作后结果为 6
// 操作完毕

对于那些不需要完全运行,可能提前退出的情况,使用 lazy 来进行性能优化效果会非常有效。

from: http://swifter.tips/

Swift lazy 修饰符和方法的更多相关文章

  1. 【iOS】Swift LAZY 修饰符和 LAZY 方法

    延时加载或者说延时初始化是很常用的优化方法,在构建和生成新的对象的时候,内存分配会在运行时耗费不少时间,如果有一些对象的属性和内容非常复杂的话,这个时间更是不可忽略.另外,有些情况下我们并不会立即用到 ...

  2. .NET C#基础(2):方法修饰符 - 给方法叠buff

    0. 文章目的   本文面向有一定.NET C#基础知识的学习者,介绍C#中的方法修饰符的含义和使用以及注意事项.   1. 阅读基础   理解C#基本语法(如方法声明)   理解OOP基本概念(如多 ...

  3. java中的类修饰符、成员变量修饰符、方法修饰符。

    类修饰符: public(访问控制符),将一个类声明为公共类,他可以被任何对象访问,一个程序的主类必须是公共类. abstract,将一个类声明为抽象类,没有实现的方法,需要子类提供方法实现. fin ...

  4. java中的类修饰符、成员变量修饰符、方法修饰符

    类修饰符:  public(访问控制符),将一个类声明为公共类,他可以被任何对象访问,一个程序的主类必须是公共类. abstract,将一个类声明为抽象类,没有实现的方法,需要子类提供方法实现. fi ...

  5. 037——VUE中表单控件处理之表单修饰符:lazy/number/trim

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. Java接口成员变量和方法默认修饰符

     Java的interface中,成员变量的默认修饰符为:public static final 所以我们在interface中定义成员变量的时候,可以 1:public static final S ...

  7. java接口中成员变量和方法的默认修饰符(转)

    Java的interface中,成员变量的默认修饰符为:public static final 所以我们在interface中定义成员变量的时候,可以 1:public static final St ...

  8. C#学习笔记06--类/对象/访问修饰符/方法

    编程思想   1.面向过程   面向过程是要把问题解决的过程分成有一定顺序的不同步骤, 然后按照步骤一步步的将问题解决.   2.面向对象   面向对象解决问题的思路是先分析问题中所涉及的对象, 然后 ...

  9. vue修饰符 .lazy .number .trim

    .lazy 在输入框中,v-model 默认是同步数据,使用 .lazy 会转变为在 change 事件中同步 , 也就是在失去焦点 或者 按下回车键时才更新 <template> < ...

随机推荐

  1. WordPress公布新文章Email通知注冊用户

    非常多WordPress博客都开放了用户注冊的功能,用户能够參与到博客的内容建设其中来.也就是一个博客由多个用户来写.如今有这种需求,怎样实如今某一个用户发表文章后.其它用户都能收到Email通知?以 ...

  2. PL/SQL Developer 在windows7 64位系统下连Oaracle11g64位系统的解决经验

    PL/SQL Developer 在windows7 64位系统下连Oaracle11g64位系统的解决经验 一.问题现象及解决方法 现象: 1.PL/SQL 无法登录64位数据库 2.在PL/SQL ...

  3. 基于Linux系统的病毒

    虽然在Linux里传播的病毒不多,但也是存在一些,我从一些安全网站搜集了一些资料. 1.病毒名称: Linux.Slapper.Worm 类别: 蠕虫 病毒资料: 感染系统:Linux 不受影响系统: ...

  4. 解决Visual Studio 2010新建工程时出现『1>LINK : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt』错误

      VS2010在经历一些更新后,建立Win32 Console Project时会出"error LNK1123" 错误. 解决方案为: 第一步:将:项目|项目属性|配置属性|清 ...

  5. Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(四)

    这一章大象将详细分析web层代码,以及使用Spring MVC的注解及其用法和其它相关知识来实现控制器功能.     之前在使用Struts2实现MVC的注解时,是借助struts2-conventi ...

  6. iOS 并行编程:GCD Dispatch Queues

    1 简介 1.1 功能          Grand Central Dispatch(GCD)技术让任务并行排队执行,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务.任务可以是一个函数 ...

  7. Java代码安全测试解决方案

    Java代码安全测试解决方案: http://gdtesting.com/product.php?id=106

  8. cobbler部署

    1.cobbler介绍 Cobbler是一个快速网络安装linux的服务,而且在经过调整也可以支持网络安装windows.该工具使用python开发,小巧轻便(才15k行python代码),使用简单的 ...

  9. eclipse引入jar类包的源代码

    为了方便查看源代码,有时候需要对jar类包,引入源代码. 下载源代码 源代码是zip或者rar的压缩包 引入到项目中

  10. 万网免费主机wordpress快速建站教程-wordpress下载及安装

    进入wordpress官网(http://cn.wordpress.org)下载最新的wordpress安装程序,下载完成后解压到任意电脑目录. 解压完毕后,使用FTP管理工具上传安装文件至主机htd ...