单星号与双星号(*和**)在python函数中的应用

 python  单星号与双星号(*和**)在python函数中的应用已关闭评论
9月 042019
 

想不到单星号还能用于解压参数列表!!

在python的函数中经常能看到输入的参数前面有一个或者两个星号:例如

这两种用法其实都是用来将任意个数的参数导入到python函数中。

单星号(*):*args
将所以参数以元组(tuple)的形式导入:
例如:

双星号(**):**kwargs
将参数以字典的形式导入

此外,单星号的另一个用法是解压参数列表:(这种用法让人惊艳!)

当然这两个用法可以同时出现在一个函数中:例如

CentOS系统中常用查看系统信息和日志命令

 centos  CentOS系统中常用查看系统信息和日志命令已关闭评论
9月 042019
 

一、系统日志文件(可以通过cat或tail命令来查看)

/var/log/message # 系统启动后的信息和错误日志,是Red Hat Linux中最常用的日志之一

/var/log/secure # 与安全相关的日志信息

/var/log/maillog # 与邮件相关的日志信息

/var/log/cron # 与定时任务相关的日志信息

/var/log/spooler # 与UUCP和news设备相关的日志信息

/var/log/boot.log # 守护进程启动和停止相关的日志消息

二、系统信息

uname -a # 查看内核/操作系统/CPU信息

cat /etc/issue

cat /etc/redhat-release # 查看操作系统版本

cat /proc/cpuinfo  # 查看CPU信息

hostname # 查看计算机名

lspci -tv # 列出所有PCI设备

lsusb -tv # 列出所有USB设备

lsmod # 列出加载的内核模块

env # 查看环境变量

三、资源

free -m # 查看内存使用量和交换区使用量

df -h # 查看各分区使用情况

du -sh <目录名> # 查看指定目录的大小

grep MemTotal /proc/meminfo # 查看内存总量

grep MemFree /proc/meminfo # 查看空闲内存量

uptime # 查看系统运行时间、用户数、负载

cat /proc/loadavg # 查看系统负载

 

四、磁盘和分区

mount | column -t # 查看挂接的分区状态

fdisk -l # 查看所有分区

swapon -s # 查看所有交换分区

hdparm -i /dev/hda # 查看磁盘参数(仅适用于IDE设备)

dmesg | grep IDE # 查看启动时IDE设备检测状况

五、网络

ifconfig # 查看所有网络接口的属性

iptables -L # 查看防火墙设置

route -n # 查看路由表

netstat -lntp # 查看所有监听端口

netstat -antp # 查看所有已经建立的连接

netstat -s # 查看网络统计信息

六、进程

ps -ef # 查看所有进程

top # 实时显示进程状态(另一篇文章里面有详细的介绍)

七、用户 

w # 查看活动用户

id <用户名> # 查看指定用户信息

last # 查看用户登录日志

cut -d: -f1 /etc/passwd # 查看系统所有用户

cut -d: -f1 /etc/group # 查看系统所有组

crontab -l # 查看当前用户的计划任务

八、服务

chkconfig –list # 列出所有系统服务

chkconfig –list | grep on # 列出所有启动的系统服务

九、程序

rpm -qa # 查看所有安装的软件包

 

来自:https://blog.csdn.net/twc829/article/details/75284332

Linux下文件分割与合并(split, cat)(转)

 linux  Linux下文件分割与合并(split, cat)(转)已关闭评论
9月 032019
 

1、前记

Linux学习系列主要侧重数据处理的命令实战学习,包括但不限于awk,grep,sed等命令的实战学习。

2、文件分割(split)

2.1 命令语法

split [--help][--version][-<行数>][-b <字节>][-C <字节>][-l <行数>][要切割的文件][输出文件名]

参数解释

  • -a:指定输出文件名的后缀长度,默认为2个(aa,ab…);
  • -d:指定输出文件名的后缀用数字代替;
  • -l<行数>:行数分割模式,指定每多少行切成一个小文件;
  • -b<字节>:二进制分割模式,指定每多少字切成一个小文件,支持单位:m,k;
  • -C<字节>:文件大小分割模式,与-b参数类似,但切割时尽量维持每行的完整性;
  • –help:显示帮助;
  • –version:显示版本信息;
  • [输出文件名]:设置切割后文件的前置文件名,split会自动在前置文件名后再加上编号。

2.2 使用实例

(1)查看文件总行数

wc -l seven.sql

输出:3307194 seven.sql,即约330万行,分割时以30万行为单位。

(2)分割文件

split -l 300000 seven.sql /home/kinson/Desktop/test1/seven_
--解释:
--参数"l"表示按行分割;
--"300000"表示每个文件30w行
--"seven.sql"为将分割文件;
--"/home/kinson/Desktop/test1/seven_"为分割后的文件路径与命名。

(3)分割结果

分割结果

3、文件合并(cat)

cat命令的用途是连接文件或标准输入并打印。这个命令常用来显示文件内容,或者将几个文件连接起来显示,或者从标准输入读取内容并显示,它常与重定向符号配合使用。

cat主要有如下三大功能:

  • 一次显示整个文件:cat filename;
  • 从键盘创建一个文件:cat > filename 只能创建新文件,不能编辑已有文件;
  • 将几个文件合并为一个文件:cat file1 file2 > file。

3.1 命令语法

cat [-AbeEnstTuv] [--help] [--version] fileName 

参数解释

  • -A:–show-all,等价于 -vET;
  • -b: –number-nonblank,对非空输出行编号;
  • -e:等价于 -vE;
  • -E: –show-ends,在每行结束处显示 $;
  • -n:–number,对输出的所有行编号,由1开始对所有输出的行数编号;
  • -s:–squeeze-blank,有连续两行以上的空白行,就代换为一行的空白行;
  • -t:与 -vT 等价;
  • -T:–show-tabs,将跳格字符显示为 ^I;
  • -v:–show-nonprinting,使用 ^ 和 M- 引用,除了 LFD 和 TAB 之外。

3.2 使用实例

(1)合并全部已分割文件并检验行数

cat test1/seven_* >newseven
wc -l newseven

输出:3307194 newseven,与原文件seven.sql行数一致。

(2)合并部分已分割文件并检验行数

cat test1/seven_aa > seven_part
cat test1/seven_ab >> seven_part
cat test1/seven_ac >> seven_part
wc -l seven_part 

>>表示追加,输出900000 seven_part,即合并了3个文件,每个30万行,所以合并后文件总行数为90万行。

转自链接:https://www.jianshu.com/p/014ec71b0215

linux下分别使用find和grep进行查找

 linux  linux下分别使用find和grep进行查找已关闭评论
8月 302019
 

网上的资料,这个介绍的很详细,收藏下:

在使用linux时,经常需要进行文件查找。其中查找的命令主要有find和grep。两个命令是有区的。

区别:(1)find命令是根据文件的属性进行查找,如文件名,文件大小,所有者,所属组,是否为空,访问时间,修改时间等。

(2)grep是根据文件的内容进行查找,会对文件的每一行按照给定的模式(patter)进行匹配查找。

一.find命令

    基本格式:find  path expression

1.按照文件名查找

(1)find / -name httpd.conf  #在根目录下查找文件httpd.conf,表示在整个硬盘查找
(2)find /etc -name httpd.conf  #在/etc目录下文件httpd.conf
(3)find /etc -name ‘*srm*’  #使用通配符*(0或者任意多个)。表示在/etc目录下查找文件名中含有字符串‘srm’的文件
(4)find . -name ‘srm*’   #表示当前目录下查找文件名开头是字符串‘srm’的文件

2.按照文件特征查找

(1)find / -amin -10   # 查找在系统中最后10分钟访问的文件(access time)
(2)find / -atime -2   # 查找在系统中最后48小时访问的文件
(3)find / -empty   # 查找在系统中为空的文件或者文件夹
(4)find / -group cat   # 查找在系统中属于 group为cat的文件
(5)find / -mmin -5   # 查找在系统中最后5分钟里修改过的文件(modify time)
(6)find / -mtime -1   #查找在系统中最后24小时里修改过的文件
(7)find / -user fred   #查找在系统中属于fred这个用户的文件
(8)find / -size +10000c  #查找出大于10000000字节的文件(c:字节,w:双字,k:KB,M:MB,G:GB)
(9)find / -size -1000k   #查找出小于1000KB的文件

3.使用混合查找方式查找文件

 参数有: !,-and(-a),-or(-o)。

(1)find /tmp -size +10000c -and -mtime +2   #在/tmp目录下查找大于10000字节并在最后2分钟内修改的文件
(2)find / -user fred -or -user george   #在/目录下查找用户是fred或者george的文件文件
(3)find /tmp ! -user panda  #在/tmp目录中查找所有不属于panda用户的文件

二、grep命令

   基本格式:find  expression

 1.主要参数

[options]主要参数:
-c:只输出匹配行的计数。
-i:不区分大小写
-h:查询多文件时不显示文件名。
-l:查询多文件时只输出包含匹配字符的文件名。
-n:显示匹配行及行号。
-s:不显示不存在或无匹配文本的错误信息。
-v:显示不包含匹配文本的所有行。

pattern正则表达式主要参数:
\: 忽略正则表达式中特殊字符的原有含义。
^:匹配正则表达式的开始行。
$: 匹配正则表达式的结束行。
\<:从匹配正则表达 式的行开始。
\>:到匹配正则表达式的行结束。
[ ]:单个字符,如[A]即A符合要求 。
[ – ]:范围,如[A-Z],即A、B、C一直到Z都符合要求 。
.:所有的单个字符。
* :有字符,长度可以为0。

2.实例

(1)grep ‘test’ d*  #显示所有以d开头的文件中包含 test的行
(2)grep ‘test’ aa bb cc    #显示在aa,bb,cc文件中包含test的行
(3)grep ‘[a-z]\{5\}’ aa   #显示所有包含每行字符串至少有5个连续小写字符的字符串的行
(4)grep magic /usr/src  #显示/usr/src目录下的文件(不含子目录)包含magic的行
(5)grep -r magic /usr/src  #显示/usr/src目录下的文件(包含子目录)包含magic的行

(6)grep -w pattern files :只匹配整个单词,而不是字符串的一部分(如匹配’magic’,而不是’magical’),

 

转自:https://www.cnblogs.com/xudong-bupt/archive/2013/03/23/2976793.html

CentOS 7 下安装 MySQL 5.7

 centos, mysql  CentOS 7 下安装 MySQL 5.7已关闭评论
8月 212019
 

原文链接:https://blog.csdn.net/u011886447/article/details/79796802

从 CentOS 7 系统开始,MariaDB 成为 yum 源中默认的数据库安装包。在 CentOS 7 及以上的系统中使用 yum 安装 MySQL 包将无法使用 MySQL。您可以选择使用完全兼容的 MariaDB,或依照本文介绍配置来继续使用 MySQL。本文以在 CentOS 7 下安装 MySQL 5.7.21 为例。

 

  1. 检查 MariaDB 是否安装

yum list installed | grep mariadb

 

 

 

  1. 卸载全部MariaDB 相关

yum -y remove mariadb*

 

  1. 下载 MySQL 的 YUM 源

进入到要下载到的路径:cd /usr/local/src

 

下载:wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm

 

  1. 安装MySQL 的 YUM 源

rpm -ivh mysql57-community-release-el7-11.noarch.rpm

 

  1. 检查MySQL 的 YUM 源是否安装成功

yum repolist enabled | grep “mysql.*-community.*”

 

 

 

如图所示则安装成功。

 

  1. 查看 MySQL 版本

yum repolist all | grep mysql

 

 

 

  1. 安装 MySQL

yum install mysql-community-server

 

一直输 y 就可以了。

 

  1. 启动 MySQL 服务

systemctl start mysqld

 

  1. 测试连接 MySQL 服务

mysql -u root 或者 mysql

 

——————————————————————————–

 

提示:

 

刚安装的 MySQL 是没有密码的,这时如果出现:

 

ERROR 1045 (28000): Access denied for user ‘root’@’localhost’ (using password: NO),解决如下:

 

① 停止 MySQL 服务:systemctl stop mysqld

 

② 以不检查权限的方式启动 MySQL: mysqld –user=root –skip-grant-tables &

 

③ 再次输入 mysql -u root 或者 mysql,这次就可以进来了。

 

④ 更新密码:

 

MySQL 5.7 以下版本:UPDATE mysql.user SET Password=PASSWORD(‘123456′) where USER=’root’;

 

MySQL 5.7 版本:UPDATE mysql.user SET authentication_string=PASSWORD(‘123456′) where USER=’root’;

 

⑤ 刷新:flush privileges;

 

⑥ 退出:exit;

 

设置完之后,输入 mysql -u root -p,这时输入刚设置的密码,就可以登进数据库了。

 

——————————————————————————–

 

  1. 防火墙设置

远程访问 MySQL,需要开放 3306 端口:

 

firewall-cmd –permanent –zone=public –add-port=3306/tcp

 

firewall-cmd –permanent –zone=public –add-port=3306/udp

 

firewall-cmd –reload

 

如果是 CentOS 7,需要将 MySQL 服务加入防火墙,然后重启防火墙:

 

firewall-cmd –zone=public –permanent –add-service=mysql

 

systemctl restart firewalld

 

——————————————————————————–

 

提示:

 

在输入 firewall-cmd –permanent –zone=public –add-port=3306/tcp 时可能会报 ‘FirewallD is not running’,是说防火墙本身就没有打开,解决方法:

 

① 查看防火墙状态:systemctl status firewalld,会发现状态是 dead,即防火墙未开启。

 

② 打开防火墙:systemctl start firewalld

 

③ 再次查看防火墙状态:systemctl status firewalld,这时会发现状态变为 running,即防火墙开启成功。

 

 

 

 

 

 

这时再输入开放 3306 端口的命令就没有问题了。

 

——————————————————————————–

 

  1. 设置允许远程访问

默认情况下 MySQL 是不允许远程连接的,所以在 Java 项目或者 MySQLWorkbench 等数据库连接工具连接服务器上的 MySQL 服务的时候会报 “Host ‘x.x.x.x’ is not allowed to connect to this MySQL server”。可以通过下面的设置解决。详细可以参考之前写的一篇文章 XXX is not allowed to connect to this MySQL server。

 

① grant all privileges on *.* to root@”%” identified by ‘0’;

 

② flush privileges;

 

——————————————————————————–

 

提示:

 

在执行第一条命令的时候,可能会报:

 

‘ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.’ 需要让我们重置密码。原因是因为我刚刚的命令中设置的数据库密码是0,这个密码过于简单,不符合 MySQL 的安全要求。只要重新设置一个复杂点的密码就可以了:

 

mysql> SET PASSWORD = PASSWORD(‘xxx’);   //xxx 是重置的新的复杂的密码

 

——————————————————————————–

 

思考:

 

之前设置简单密码是没有问题的,可能原因:

 

① 可能目前环境是 CentOS 7 + MySQL 5.7.21,安全性有所提升。

 

② 也有可能是之前的数据库设置过

 

mysql> set global validate_password_policy=0;

 

mysql> set global validate_password_length=1;

 

允许设置简单密码。

 

  1. 相关命令

MySQL 相关:

 

systemctl start mysqld    #启动mysql

 

systemctl stop mysqld    #停止mysqld

 

systemctl restart mysqld    #重启mysqld

 

systemctl enable mysqld    #设置开机启动

 

systemctl status mysqld    #查看 MySQL Server 状态

 

防火墙相关:

 

systemctl status firewalld    #查看防火墙状态

 

systemctl start firewalld    #打开防火墙

 

systemctl stop firewalld    #关闭防火墙

 

systemctl restart firewalld    #重启防火墙

 

 

您不能安装“Network Link Conditioner”偏好设置。“Network Link Conditioner”偏好设置是随 macOS 安装,不能被替换。

 mac  您不能安装“Network Link Conditioner”偏好设置。“Network Link Conditioner”偏好设置是随 macOS 安装,不能被替换。已关闭评论
8月 162019
 

其实出现这个提示,基本都是以前使用过Network Link Conditioner, 后来关闭后,Network Link Conditioner从“系统设置”里看不到了,然后再次从“Additional_Tools_for_Xcode_xxxx.dmg”中的Hardware目录里点击Network Link Conditioner .prefPane出现这样的提示, 其实这个程序已经安装了,可以通过操作spotlight找到并打开:

  • 按住 Command + Space 打开 spotlight 全局搜索
  • 搜索 Network Link Conditioner
  • 在结果列表里双击打开
  • 自动添加到设置面板并打开

DONE!

Swift中的!和?, 问号 和叹号 的使用和区别介绍

 swift  Swift中的!和?, 问号 和叹号 的使用和区别介绍已关闭评论
8月 132019
 

一般我们在一下两种情况下会遇到!和?的使用
1.声明变量时

var number :Int?
var str : String

2.在对变量操作时

number?.hashValue
str!.hashValue

由于这两种情况的意义不同,所以分开进行解释:

1.声明变量时
在声明一个变量时如果不手动初始化,Swift不会自动初始化该变量为一个默认值的。

var a : String
var b = a           //error:因为没有初始化a,a没有值

但是对于Optional的变量则不同,Optional的变量在声明时如果不初始化,Swift会自动将该变量初始化为nil。声明变量时在类型后添加?或者!就是告诉编译器这个一个Optional的变量,如果没有初始化,你就将其初始化为nil

var a : String?           //a 为nil
var b : String!           //b 为nil
var a_test = a            //a_test为nil
var b_test = b            //b_test为nil

但是这两者之间还是有一些区别的,介绍后面之后再讲。
Optional事实上是一个枚举类型,从下图可以看出,Optional包含None和Some两种类型,而nil就是Optional.None,非nil就是Optional.some。如果Optional变量在声明时不初始化,Swift会调用init()来初始化变量为nil,而用非nil的值初始化变量时,会通过Some(T)把该原始值包装,所以在之后使用的时候我们需要通过解包取出原始值才能使用。

请输入图片描述

2.对变量进行操作时

var arrayCount = dataList?.count

这时问号的意思类似于isResponseToSelector,即如果变量是nil,则不能响应后面的方法,所以会直接返回nil。如果变量非nil,就会拆Some(T)的包,取出原始值执行后面的操作。

var arrayCount = dataList!.count

这里的叹号和之前的问号则不同,这里表示我确定dataList一定是非nil的,所以直接拆包取出原始值进行处理。因此此处如果不小心让dataList为nil,程序就会crash掉。

回到上面声明时?和!区别的问题上去
声明变量时的?只是单纯的告诉Swift这是Optional的,如果没有初始化就默认为nil,而通过!声明,则之后对该变量操作的时候都会隐式的在操作前添加一个!。

总结

  1. 问号?
    a.声明时添加?,告诉编译器这个是Optional的,如果声明时没有手动初始化,就自动初始化为nil
    b.在对变量值操作前添加?,判断如果变量时nil,则不响应后面的方法。
  2. 叹号!
    a.声明时添加!,告诉编译器这个是Optional的,并且之后对该变量操作的时候,都隐式的在操作前添加!
    b.在对变量操作前添加!,表示默认为非nil,直接解包进行处理

 

来自:https://segmentfault.com/a/1190000000533936。

Swift闭包的用法,简介, IN用法

 swift  Swift闭包的用法,简介, IN用法已关闭评论
8月 072019
 

非常好的资料https://www.jianshu.com/p/7dcecea05dbb

 

本篇将详细总结介绍Swift闭包的用法;
闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift中的闭包与C和 Objective-C中的代码块(blocks)以及其他一些编程语言中的匿名函数比较相似。

主要内容:
1.闭包表达式
2.闭包的使用与优化
3.值捕获
4.逃逸闭包
5.自动闭包

一、闭包表达式

Swift闭包的三种存在形式:
1.全局函数是一个有名字但不会捕获任何值的闭包
2.嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包
3.闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的匿名闭包
闭包表达式的语法一般有如下的一般形式:

{ (parameters) -> returnType in
    statements
}

说明:
1.闭包的外层是一个大括号,先写的参数和返回值,然后操作部分之前使用in;
2.闭包就相当于OC中的block, 也可以看做是匿名函数;
3.闭包表达式参数可以是in-out参数,但不能设定默认值;
4.闭包的函数体部分由关键字in引入,该关键字表示闭包参数和返回值类型已经完成,闭包函数体开始;

二、闭包的使用与优化

下面,我们使用Swift标准库中的sorted(by:)方法来测试闭包的使用。sorted(by:)方法允许外部传入一个用于排序的闭包函数将已知类型数组中的值进行排序,完成排序之后,该方法会返回一个与原数组大小相同,包含同类型元素已正确排序的新数组:

//定义一个整型数组
var someInts: [Int] = [5,9,7,0,1,3]
//定义一个排序函数
func biggerNumFirst(num1:Int, num2:Int) -> Bool{
    return num1 > num2
}
//普通用法:将biggerNumFirst函数传入sorted函数,实现排序
var sortInts = someInts.sorted(by: biggerNumFirst)
print(sortInts)     //[9, 7, 5, 3, 1, 0]

//闭包用法:为sorted函数参数传入一个闭包,实现排序
sortInts = someInts.sorted(by:{ (a:Int, b:Int) -> Bool in
    return a > b
})
print(sortInts)     //[9, 7, 5, 3, 1, 0]

注意:因为闭包不会在其他地方调用,所以不使用外部参数名

闭包使用起来十分灵活,我们可以在某些特定情况下对齐进行优化,下面是对上述闭包的优化:

2.1.根据上下文推断类型,省略参数类型与括号

由于排序闭包函数是作为sorted(by:)方法的参数传入的,Swift可以推断其类型和返回值类型。所以sorted(by:)方法被一个Int类型的数组调用,其参数必定是(Int,Int)->Bool类型的函数。最后,根据上下文推断类型,我们可以省略参数类型和参数周围的括号。

sortInts = someInts.sorted(by: {a,b in
    return a > b
})
print(sortInts)

2.2.对于不会发生歧义的闭包,可将其写成一行

sortInts = someInts.sorted(by:{a,b in return a > b})
print(sortInts)

2.3.单行闭包表达式,省略return关键字

省略return关键字的条件:
sorted(by:)方法的参数类型明确了闭包必须返回一个Bool类型值
单行闭包表达式中,其返回值类型没有歧义

sortInts = someInts.sorted(by: {a,b in a > b})
print(sortInts)

2.4.使用参数名缩写(不推荐使用)

Swift 自动为内联闭包提供了参数名称缩写功能,你可以直接通过$0,$1,$2 来顺序调用闭包的参数,以此类推。
如果我们在闭包表达式中使用参数名称缩写, 我们就可以在闭包定义中省略参数列表,并且对应参数名称缩写的类型会通过函数类型进行推断。in关键字也同样可以被省略,因为此时闭包表达式完全由闭包函数体构成:

sortInts = someInts.sorted(by: {$0>$1})
print(sortInts)

2.5.使用运算符简化闭包(不推荐使用)

Swift的Int类型定义了关于大于号(>)的字符串实现,其作为一个函数接受两个Int类型的参数并返回Bool类型的值。而这正好与sorted(by:)方法的参数需要的函数类型相符合。可以使用大于号来代替闭包

sortInts = someInts.sorted(by: >)
print(sortInts)

2.6.尾随闭包,解决长闭包的书写问题

如果你需要将一个很长的闭包表达式作为最后一个参数传递给函数,可以使用尾随闭包来增强函数的可读性。
尾随闭包的写法:将闭包书写在函数括号之后,函数会支持将其作为最后一个参数调用,使用尾随闭包,不需要写出它的参数标签。

func someFunctionThatTakesAClosure(closure: () -> Void) {
    //函数体部分
    closure(); //调用闭包
}

//不使用尾随闭包进行函数调用
someFunctionThatTakesAClosure(closure: {
    //闭包主体部分
})

//使用尾随闭包进行函数调用
someFunctionThatTakesAClosure() {
    //闭包主体部分
}

//注意:如果闭包表达式是函数或方法的唯一参数,则当你使用尾随闭包时,你甚至可以把 () 省略掉:
someFunctionThatTakesAClosure {
    print("Hello World!")    //打印:Hello World!
}

总结Swift闭包主要的四种优化方法:
1.利用上下文推断参数和返回值类型,省略参数类型与括号
2.隐式返回单表达式闭包,即单表达式闭包可以省略return关键字
3.参数名称缩写
4.尾随闭包语法

三、值捕获

闭包可以在其被定义的上下文中捕获常量或变量。即使定义这些常量和变量的原作用域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。Swift会为你管理在捕获过程中涉及到的所有内存操作。

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

代码分析:
1.makeIncrementer函数以amount为参数,以()->Int作为返回值类型,其函数体中还嵌套了另一个函数incrementer。
2.如果我们把incrementer单独拿出来,会发现其中runingTotal和amount变量都无法使用,因为这两个变量的引用是incrementer从外部捕获的。
3.Swift会负责被捕获变量的所有内存管理工作,包括对捕获的一份值拷贝,也包括释放不再需要的变量。

现在再来测试makeIncrementer函数的使用:

let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen();    //10
incrementByTen();    //20

let incrementBySeven = makeIncrementer(forIncrement: 7)
incrementBySeven()   //7
incrementBySeven();  //14

let alsoIncrementByTen = incrementByTen
alsoIncrementByTen() //30

代码分析:
1.incrementByTen与incrementBySeven,是通过makeIncrementer函数传入不同的增量参数amount而创建的;
2.两个函数都有属于各自的引用,其中的runningTotal变量都是从makeIncrementer中捕获的,但是已经各自没有关系;
3.函数和闭包都是引用类型,将其赋值给变量或者常量,都只是操作的它们的引用,而不会改变闭包或者函数本身;

四、逃逸闭包

当一个闭包作为参数传到一个函数中,但是这个闭包在函数返回之后才被执行,我们称该闭包从函数中逃逸。
逃逸闭包:在定义接受闭包作为参数的函数时,我们需要在参数名之前标注@escaping,以此表明这个闭包是允许”逃逸”出这个函数的。

var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    //代码1:执行闭包,不需要添加@escaping
    //completionHandler();
    //代码2:函数外部对闭包进行了操作
    completionHandlers.append(completionHandler)
 }

代码分析:
someFunctionWithEscapingClosure(_:) 函数接受一个闭包作为参数,该闭包被添加到一个函数外定义的数组中。如果不将这个参数标记为@escaping,就会得到一个编译错误。

4.1.逃逸闭包的使用

逃逸闭包和非逃逸闭包在使用上有所不同。将一个闭包标记为@escaping(即逃逸闭包)后,在调用这个闭包时就必须在闭包中显式地引用 self。一个示例如下:

//定义一个带有非逃逸闭包参数的函数
func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}

//定义一个可以使用闭包的类
class SomeClass {
    var x = 10
    func doSomething() {
        //调用逃逸闭包:必须在闭包中显式引用self
        someFunctionWithEscapingClosure { self.x = 100 }
        //调用非逃逸闭包:可以隐式引用self
        someFunctionWithNonescapingClosure { x = 200 }
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x)         //打印出 "200”

五、自动闭包

自动闭包:一种自动创建的闭包,用与包装传递给函数作为参数的表达式;自动闭包的特点:
1.自动闭包不接受任何参数;
2.自动闭包被调用的时候,会返回被包装在其中的表达式的值;
3.自动闭包是用一个普通的表达式来代替显式的闭包,能够省略闭包的花括号;

其实,我们经常调用采用自动闭包的函数,但是却少去实现这样的函数,assert函数就是其中之一:

 assert(condition:, message:)

assert函数中的condition参数可以接受自动闭包作为值,condition参数仅会在debug模式下被求值,在condidtion被调用返回值为false时,message参数将被使用。

5.1.自动闭包的基本使用

自动闭包能够实现延迟求值,直到调用这个闭包时,代码才会被执行。这对于有副作用或者高计算成本的代码来说是有益处的;下面的代码展示了自动闭包实现延时求值的具体做法:

var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)    //打印出 “5"

//自动闭包不接受参数,只是一个表达式
let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)    //打印出 “5"

//调用自动闭包
print("Now serving \(customerProvider())!")   // Prints "Now serving Chris!"
print(customersInLine.count)               //打印出 "4”

代码分析:闭包实现了移除第一元素的功能,但是在闭包被调用之前,这个元素是不会被移除的。这就实现了延迟的作用

5.2.自动闭包在函数中的使用

现在将闭包作为参数传递给一个函数,同样可以实现延时求值行为。下面的serve函数接受了一个闭包参数(具有删除第一个元素且返回这个元素的功能)。

//customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: () -> String) {
    print("Now serving \(customerProvider())!")
}

//以闭包的形式传入参数
serve(customer: { customersInLine.remove(at: 0) } )  //打印出"Now serving Alex!”

现在使用自动闭包来实现上述函数功能,使用@autoclosure关键字,标明参数使用的是自动闭包,具体示例如下:

// customersInLine is ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \(customerProvider())!")
}
//由于标明了自动闭包,这里直接省略了闭包的花括号
serve(customer: customersInLine.remove(at: 0))  //打印出"Now serving Ewa!\n"

注意:
过度使用 autoclosures 会让你的代码变得难以理解。上下文和函数名应该能够清晰地表明求值是被延迟执行的。

5.3.可”逃逸”的自动闭包

一个自动闭包可以“逃逸”,这时候应该同时使用 @autoclosure 和 @escaping 属性,下面举例说明:

// customersInLine is ["Barry", "Daniella"]
var customerProviders: [() -> String] = []
func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
    customerProviders.append(customerProvider)
}
//调用collectCustomerProviders,向数组中追加闭包
collectCustomerProviders(customersInLine.remove(at: 0))
collectCustomerProviders(customersInLine.remove(at: 0))
print("Collected \(customerProviders.count) closures.")   //打印 "Collected 2 closures."
//循环数组中闭包,并且执行
for customerProvider in customerProviders {
    print("Now serving \(customerProvider())!")
}
// 打印 "Now serving Barry!"
// 打印 "Now serving Daniella!”

代码分析:
作为逃逸闭包:
collectCustomerProviders函数中,闭包customerProvider被追加到customerProviders中,而这个数据是定义在函数作用域范围之外的,这意味数组内的闭包能够在函数返回之后被调用,所以customerProvider必须允许
“逃逸”出函数作用域。

作为自动闭包:
调用collectCustomerProviders函数时,传入的闭包是表达式的形式,自动闭包省略了闭包花括号

 

xcode 10.2.1 里修改文件名,提示”rename failed”的解决方法

 mac, xcode  xcode 10.2.1 里修改文件名,提示”rename failed”的解决方法已关闭评论
8月 062019
 

新建xcode文件时,类名和文件名都起错了,文件里的类名可以修改(refactor->rename),但修改文件名时报错: rename failed,
可通过下面方式解决(此法似乎对类名修改报错也有效):

1.关闭 xCode
2.进入 ~/Library/Developer/Xcode/DerivedData 目录并删除包含 “ModuleCache”名的目录.
3.重新打开xcode
4.再尝试该名下。

Good Luck!

virtualbox 里使用itunes步骤及注意事项

 virtualBox  virtualbox 里使用itunes步骤及注意事项已关闭评论
8月 022019
 

在virtualbox 里想使用itunes,会发现插入usb端口,设备连接了但发现不了iphone设备等问题, 网上找到一篇英文等资料,有详细步骤及注意事项,大家可以参考下(我遇到的问题就是原来打开的是USB 1.0,实际需要打开:USB 2.0 EHCI controller ):

Ok, for the record, I’m not the biggest fan of iTunes for Windows, and that’s why when I needed to use iTunes I decided to install it within an Oracle Virtualbox virtual machine.

This configuration provides the benefit of portability and it also prevents Apple iTunes from wreaking havoc on your host PC.

Hooray for no iTunes on my host machine!!!

Anyway, this is how you do it,

How to set it up

  1. Download and install Oracle VirtualBox from https://www.virtualbox.org/
  2. Open VirtualBox and click MACHINE > NEW to create a new virtual machine.
  3. Select your OS and memory allocation. In my case I chose Microsoft Windows 7 32 bit
    Oracle VirtualBox Screenshot
  4. Choose option Create a virtual hard drive now. You can use the defaults for the next prompts. It’s advisable that you  allocate more hard disk space if you are going to store your media files within the Virtual Machine. In my situation I created a shared folder on my host which I mapped to the Virtual Machine.
  5. Plug in your iDevice to your PC.
  6. You should now see your Virtual Machine in the VirtualBox Manager window. Click SETTINGS to configuring your VM.
    Oracle VirtualBox screenshot
  7. You’ll need to mount the OS storage media within the Storagepanel to install your OS.
  8. Enable the Network Adapter in Bridged Mode so that you have internet access.
  9. In the USB pane, ensure the USB 2.0 EHCI controller is enabled otherwise your iDevice will not operate correctly. If you plugged in your iDevice then click the green ‘+’ button and select your iDevice, this will ensure that control of your device is passed straight to your VM automatically each time you start your VM. Otherwise you can manually ‘pass through’ the device once the VM is started.
    Oracle VirtualBox Screenshot
  10. It’s also advisable to enable 2D hardware acceleration and add additional Video Memory for improved performance.
  11. Click OK to save your changes
  12. Start your Virtual Machine and install the OS and Apple iTunes
  13. Setup your iTunes library to find your media files. It’s recommended that you use the ‘Consolidate Files‘ library option in iTunes to store all your media files in one single location, that way it’ll be easier for you to relocate your Virtual Machine in future to another PC.
  14. If you need access to the CD Drive on your host machine, simply start your Virtual Machine and ‘pass through’ control of your CD drive to your Virtual Machine through the DEVICES > CD/DVD DEVICES > HOST DRIVE option
  15. iTunes should now see your device and should sync successfully.
    iTunes Screenshot

Issues that I encountered

I had iTunes setup to consolidate all media files to an external USB drive. I experienced device ‘timeout‘ issues and ‘Could not connect to lockdown port‘ errors while syncing with my iPhone. After much hair pulling I realised that the timeouts were occurring only when I configured VirtualBox to ‘pass through’ my USB drive to the Virtual Machine. The issue was solved by instead creating a Shared Machine Folder within the Virtual Machine settings mapping to my USB drive.

I would certainly suggest that you create a snapshot of your Virtual Machine once you’ve created it incase anything goes wrong and you need to rollback to an earlier time.