shel_command_grep

作用

Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来。grep全称是Global Regular Expression Print,表示全局正则表达式版本,它的使用权限是所有用户。

格式

grep [options]

options 主要参数:

  1. -c:只输出匹配行的计数。
  2. -I:不区分大 小写(只适用于单字符)。
  3. -h:查询多文件时不显示文件名。
  4. -l:查询多文件时只输出包含匹配字符的文件名。
  5. -n:显示匹配行及 行号。
  6. -s:不显示不存在或无匹配文本的错误信息。
  7. -v:显示不包含匹配文本的所有行。
  8. -E 使用扩展正则表达式
  9. pattern正则表达式主要参数:
  10. \: 忽略正则表达式中特殊字符的原有含义。
  11. ^:匹配正则表达式的开始行。
  12. $: 匹配正则表达式的结束行。
  13. \<:从匹配正则表达 式的行开始。
  14. >:到匹配正则表达式的行结束。
  15. [ ]:单个字符,如[A]即A符合要求 。
  16. [ - ]:范围,如[A-Z],即A、B、C一直到Z都符合要求 。
  17. 。:所有的单个字符。
  18. * :有字符,长度可以为0。

grep命令的简单实例

  1. $ grep ‘test’ d*

    显示当前目录下所有以d开头的文件中包含test的行

  2. $ grep ‘test’ file1 file2 file3

    显示指定文件file1,file2,file3中包含test的行

  3. $ grep ‘[a-z]{5}‘ file

    显示指定文件file中至少包含连续5个小写字母的行

  4. $ grep ‘w(es)t.*\1’ file

    如果west被匹配,则es就被存储到内存中,并标记为1,然后搜索任意个字符(.*),这些字符后面紧跟着 另外一个es(\1),找到就显示该行。如果用egrep或grep -E,就不用”\”号进行转义,直接写成’w(es)t.*\1′就可以了。

5.简单实例

# grep 'the' size.txt 
the test file 
their are files 

# grep '\<the' size.txt 
the test file 
their are files 

# grep 'the\>' size.txt 
the test file 

# grep '\<the\>' size.txt 
the test file 

I# grep '\<[Tt]he\>' size.txt 
the test file

grep命令的复杂实例

  1. $ grep xm ~/Desktop/*

    在’~/Desktop’目录下搜索带字符串’xm’的文件,结果如下:

1
2
3
4
5
6
7
8
9
10
11
./xmpp.txt~:<?xmlversion='1.0'?>
./xmpp.txt~:xmlns='jabber:client'
./xmpp.txt~:xmlns:stream='http_etherx_jabber_org/streams'
grep: ./you-第三阶段: Is a directory
grep: ./服装搭配资料: Is a directory
grep: ./毕设: Is a directory
Binary file ./毕设文档.docx matches
Binary file ./王志飞论文.doc matches
grep: ./简历: Is a directory
grep: ./课件: Is a directory
grep: ./项目: Is a directory
默认情况下,’grep’只搜索当前目录。如果 此目录下有许多子目录,’grep’会以如下形式列出:

grep: sound: Is a directory

明确要求搜索子目录:grep -r
或忽略子目录:grep -d skip

如果有很多 输出时,您可以通过管道将其转到’less’上阅读:
$ grep magic /usr/src/Linux/Documentation/* | less
  1. 命令行参数

    grep -i pattern files :不区分大小写地搜索。默认情况区分大小写,

    grep -l pattern files :只列出匹配的文件名,

    grep -L pattern files :列出不匹配的文件名,

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

    grep -C number pattern files :匹配的上下文分别显示[number]行,

    grep pattern1 | pattern2 files :显示匹配 pattern1 或 pattern2 的行,

    grep pattern1 files | grep pattern2 :显示既匹配 pattern1 又匹配 pattern2 的行。

    grep -n pattern files 即可显示行号信息

    grep -c pattern files 即可查找总行数

    这里还有些用于搜索的特殊符号:

    \< 和 > 分别标注单词的开始与结尾。

    例如:

    grep man * 会匹配 ‘Batman’、’manic’、’man’等,

    grep ‘\<man’ * 匹配’manic’和’man’,但不是’Batman’,

    grep ‘\’ 只匹配’man’,而不是’Batman’或’manic’等其他的字符串。

    ‘^’:指匹配的字符串在行首,

    ‘$’:指匹配的字符串在行 尾,

    grep命令参数

shell_command_awk

简介

awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。

awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。

使用方法

awk '{pattern + action}' {filenames}

尽管操作可能会很复杂,但语法总是这样,其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。 pattern就是要表示的正则表达式,用斜杠括起来。

awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。

通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。

条用awk的三种方式

  1. 命令行方式
1
awk [-F field-separator] 'commands' input-file(s)

其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。

  1. shell脚本方式
    将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。
    相当于shell脚本首行的:#!/bin/sh
    可以换成:#!/bin/awk

  2. 将所有的awk命令插入一个单独文件,然后调用:

1
awk -f awk-script-file input-file(s)

其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。

范例

  1. 如果只是显示最近登录的5个帐号
1
2
3
4
5
6
#last -n 5 | awk '{print $1}'
root
root
root
dmtsai
root

awk工作流程是这样的:读入有’\n’换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。默认域分隔符是”空白键” 或 “[tab]键”,所以$1表示登录用户,$3表示登录用户ip,以此类推。

  1. 如果只是显示/etc/passwd的账户
1
2
3
4
5
#cat /etc/passwd |awk -F ':' '{print $1}'
root
daemon
bin
sys

这种是awk+action的示例,每行都会执行action{print $1}。

-F指定域分隔符为’:’。

  1. 如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以tab键分割
1
2
3
4
5
#cat /etc/passwd |awk -F ':' '{print $1"\t"$7}'
root /bin/bash
daemon /bin/sh
bin /bin/sh
sys /bin/sh
  1. 如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加”blue,/bin/nosh”。
1
2
3
4
5
6
7
8
cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END {print "blue,/bin/nosh"}'
name,shell
root,/bin/bash
daemon,/bin/sh
bin,/bin/sh
sys,/bin/sh
....
blue,/bin/nosh

awk工作流程是这样的:先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。

  1. 搜索/etc/passwd有root关键字的所有行
1
2
#awk -F: '/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash

这种是pattern的使用示例,匹配了pattern(这里是root)的行才会执行action(没有指定action,默认输出每行的内容)。

搜索支持正则,例如找root开头的: awk -F: ‘/^root/‘ /etc/passwd

  1. 搜索/etc/passwd有root关键字的所有行,并显示对应的shell
1
2
# awk -F: '/root/{print $7}' /etc/passwd
/bin/bash

这里指定了action{print $7}

vim_command_sed

简介

sed是非交互式的编辑器。它不会修改文件,除非使用shell重定向来保存结果。默认情况下,所有的输出行都被打印到屏幕上。

sed编辑器逐行处理文件(或输入),并将结果发送到屏幕。具体过程如下:首先sed把当前正在处理的行保存在一个临时缓存区中(也称为模式空间),然后处理临时缓冲区中的行,完成后把该行发送到屏幕上。sed每处理完一行就将其从临时缓冲区删除,然后将下一行读入,进行处理和显示。处理完输入文件的最后一行后,sed便结束运行。sed把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会修改原文件。

定址

定址用于决定对哪些行进行编辑。地址的形式可以是数字、正则表达式、或二者的结合。如果没有指定地址,sed将处理输入文件的所有行。

以下例子一下面的文件内容测试

test.vim

hello word !
this is a test ?
asdfghjkl
qwertyuiop
zxcvbnm
come on
he he he he
ha ha ha ha 
  1. 地址是一个数字,则表示行号,是“$”符号,则表示最后一行。
1
2
3
4
sed -n '4p' test.vim
终端只打印第四行,即:qwertyuiop
sed -n '$p' test.vim
终端只打印最后一行,即:ha ha ha ha
  1. 只显示指定行范围内的文件内容
1
2
sed -n '3,6p' test.vim
只查看文件的第3行到第6行的文件内容
  1. 逗号做分隔符,对行范围内的内容的做作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sed '2,3d' test.vim
删除第二行到第五行的内容,执行命令后的结果
//hello word !
qwertyuiop
zxcvbnm
come on
he he he he
ha ha ha ha
sed '/zx/,/he/d' test.vim
删除包含‘zx’的行到包含‘he’的行,执行命令后的结果
//hello word !
this is a test ?
asdfghjkl
qwertyuiop
ha ha ha ha
sed '/is/,4d' test.vim
删除包含‘is’的行到第四行的内容

命令与选项

sed命令告诉sed如何处理由地址指定的各输入行,如果没有指定地址则处理所有的输入行。

1. sed命令

命令 功能
a\ 在当前行后添加一行或多行。多行时除最后一行外,每行末尾需用“\”续行
c\ 用此符号后的新文本替换当前行中的文本。多行时除最后一行外,每行末尾需用”\”续行
i\ 在当前行之前插入文本。多行时除最后一行外,每行末尾需用”\”续行
d 删除行
h 把模式空间里的内容复制到暂存缓冲区
H 把模式空间里的内容追加到暂存缓冲区
g 把暂存缓冲区里的内容复制到模式空间,覆盖原有的内容
G 把暂存缓冲区的内容追加到模式空间里,追加在原有内容的后面
I 列出非打印字符
p 打印行
n 读入下一输入行,并从下一条命令而不是第一条命令开始对其的处理
q 结束或退出sed
r 从文件中读取输入行
! 对所选行以外的所有行应用命令
s 用一个字符串替换另一个
g 在行内进行全局替换
w 将所选的行写入文件
x 交换暂存缓冲区与模式空间的内容
y 将字符替换为另一字符(不能对正则表达式使用y命令)

2. sed选项

选项 功能
-e 进行多项编辑,即对输入行应用多条sed命令时使用
-n 取消默认的输出 //无-n时默认打印出文件的全部内容
-f 指定sed脚本的文件名

退出状态

sed不向grep一样,不管是否找到指定的模式,它的退出状态都是0。只有当命令存在语法错误时,sed的退出状态才不是0。

正则表达式元字符

与grep一样,sed也支持特殊元字符,来进行模式查找、替换。不同的是,sed使用的正则表达式是括在斜杠线”/“之间的模式。

如果要把正则表达式分隔符”/“改为另一个字符,比如o,只要在这个字符前加一个反斜线,在字符后跟上正则表达式,再跟上这个字符即可。例如:sed -n ‘\o^Myop’ datafile

元字符 功能 实例
^ 行首定位符 /^me/ 匹配所有以me开头的行
$ 行尾定位符 /me$/ 匹配所有以me结束的行
. 匹配换行符以外的单个字符 /m..e/ 匹配包含字母m,后跟两个任意字符,再跟字母y的行
* 匹配零个或多个前导字符 /my*/ 匹配包含字母m,后跟零个或多个e字母的行
[] 匹配指定字符组内的任一字符 /[Mm]y/ 匹配包含My或my的行
[^] 匹配不在指定字符组内的任一字符 /[^Mm]y/ 匹配包含y,但y之前的那个字符不是M或m的行
\(..\) 保存已匹配的字符 1,20s/(you)self/\1r/ 标记元字符之间的模式,并将其保存为标签1,之后可以使用\1来引用它。最多可以定义9个标签,从左边开始编号,最左边的是第一个。此例中,对第1到第20行进行处理,you被保存为标签1,如果发现youself,则替换为your。
& 保存查找串以便在替换串中引用 s/my/**&**/ 符号&代表查找串。my将被替换为**my**
\< 词首定位符 /\<my/ 匹配包含以my开头的单词的行
\> 词尾定位符 /my>/ 匹配包含以my结尾的单词的行
x\{m\} 连续m个x /9{5}/ 匹配包含连续5个9的行
x\{m,\} 至少m个x /9{5,}/ 匹配包含至少连续5个9的行
x{m,n\} 至少m个,但不超过n个 /9{5,7}/ 匹配包含连续5到7个9的行

范例

eg:

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
//-n 取消默认输出 分隔符也可以用
//s 命令的分隔符可以用除反斜杠,换行符以外的字符代替
sed '/he/p' test.vim //默认情况,sed把文件的所有输入行都打印在标准输出上,如果匹配he,p命令在把符合匹配规则的行再打印一便
sed -n '/he/p' test.vim //只打印匹配行
sed -n '$d' test.vim //删除最后一行
sed -n '/he/d' test.vim //删除包含 he 的行
sed -n 's/^he/me/g' test.vim (或sed -n 's#^he#me#g' test.vim )//g:全局查找,将以he开头的he替换成me
sed -n 's/he/me/g' test.vim //全局查找,将所有的he替换成me
sed -n ’1,4s/he$/me/gp' test.vim //将第一行到第四行所有以he结尾的行最后的最后一个he替换成me,并打印到屏幕上
sed -n '1,4d' -e 's/me/he/g' test.vim //e多重编译,先删除第一行到第四行的所有内容,在将所有me替换为he 注意:顺序影响最终输出结果
sed -n '/he/r text.txt' test.vim //-r 指定在特定位置读入新内容。该行命令表示:在test.vim中所有he所在行后读入text.txt文件的内容
sed -n '/he/w me.text' test.vim //将test.vim文件中包含he行写入me.txt文件中,文件me.txt不存在则创建
sed -n '/^he/a\
>adfsaf
>sdfsgf' test.vim //在以he开头的行后追加两行
sed '/hrwang/{n;s/My/Your/;}' test.vim //sed使用该命令获取输入文件的下一行,并将其读入到模式缓冲区中,任何sed命令都将应用到匹配行紧接着的下一行上。注:如果需要使用多条命令,或者需要在某个地址范围内嵌套地址,就必须用花括号将命令括起来,每行只写一条命令,或这用分号分割同一行中的多条命令。
sed '1,20y/hrwang12/HRWANG^$/' test.vim //该命令与UNIX/Linux中的tr命令类似,字符按照一对一的方式从左到右进行转换。例如,y/abc/ABC/将把所有小写的a转换成A,小写的b转换成B,小写的c转换成C. 将1到20行内,所有的小写hrwang转换成大写,将1转换成^,将2转换成$。正则表达式元字符对y命令不起作用。与s命令的分隔符一样,斜线可以被替换成其它的字符。
sed -e '/hrwang/h' -e '$G' test.vim
sed -e '/hrwang/H' -e '$G' test.vim //通过上面两条命令,你会发现h会把原来暂存缓冲区的内容清除,只保存最近一次执行h时保存进去的模式空间的内容。而H命令则把每次匹配hrwnag的行都追加保存在暂存缓冲区。
sed -e '/hrwang/H' -e '$g' test.vim
sed -e '/hrwang/H' -e '$G' test.vim //通过上面两条命令,你会发现g把暂存缓冲区中的内容替换掉了模式空间中当前行的内容,此处即替换了最后一行。而G命令则把暂存缓冲区的内容追加到了模式空间的当前行后。此处即追加到了末尾。
sed '/hrwang/{s/hrwang/HRWANG/;q;}' test.vim //q命令将导致sed程序退出,不再进行其它的处理。

sed 脚本

sed脚本就是写在文件中的一列sed命令。脚本中,要求命令的末尾不能有任何多余的空格或文本。如果在一行中有多个命令,要用分号分隔。执行脚本时,sed先将输入文件中第一行复制到模式缓冲区,然后对其执行脚本中所有的命令。每一行处理完毕后,sed再复制文件中下一行到模式缓冲区,对其执行脚本中所有命令。使用sed脚本时,不再用引号来确保sed命令不被shell解释。例如sed脚本script:

1
2
3
4
5
6
#handle test.vim
3i\
~~~~~~~~~~~~~~~~~~~~~
3,$s/\(hrwang\) is \(mjfan\)/\2 is \1/
$a\
We will love eachother forever!!
1
2
3
4
5
6
7
#sed -f script test.vim
My name is hrwang
Your name is mjfan
~~~~~~~~~~~~~~~~~~~~~
mjfan is hrwang's husband. #啦啦~~~
mjfan is hrwang's wife.
We will love eachother forever!!

create_certificate

others’ blog

生成certSigningRequest文件

该文件是MAC系统生成的,用于在Apple网站上申请推送证书文件。

打开应“钥匙串访问”软件,菜单->钥匙串访问->证书助理->从证书颁发机构请求证书,填写邮箱和名称(随便写),选择保存到磁盘,此时会生成一个CertificateSigningRequest.certSigningRequest文件。

注册一个支持Push的app id

进入developer.apple.com,选择member center-certificates,Identifier & profiles-identifiers-App ids,注册app id,设置app id名称。同时qpp id suffix一栏选择explicit app id,设置bundle id。勾选App Services中得Push Notifications,这样就可以注册一个支持push app id。

生成cer文件

该文件用于生成服务端需要的文件。

生成过程:进入developer.apple.com,选择member center-certificates,Identifier & profiles-certificates,然后创建certificate,类型分为Development 和 Product。eg:Development,选择Apple Push Notification service SSL (Sandbox) ,选择之前生成的支持push的Appid,然后提交之前创建的CSR文件,生成cer文件,保存到本地。

生成服务器端的证书文件

如果使用网上的mac版PushMeBaby工具,在Mac机器上进行推送使用上面的cer就可以了,如果使用PHP、java/c#开发服务端,需要将cer转换生成pem或p12文件。

在应用服务器采用php的方式将消息推送给APNS,

php连接APNS也是需要证书的,打开终端,对上面的证书做如下处理,

cd  进入证书所在目录

把.cer文件转换成.pem文件:

$ openssl x509 -in aps_developer_identity.cer -inform der
-out PushCert.pem
把私钥Push.p12文件转换成.pem文件:

$ openssl pkcs12 -nocerts -out PushKey.pem -in Push.p12
Enter Import Password:
MAC verified OK
Enter PEM pass phrase:
Verifying – Enter PEM pass phrase:
你首先需要为.p12文件输入passphrase密码短语,这样OpenSSL可以读它。然后你需要键入一个新的密码短语来加密PEM文件。还是使用”pushchat”来作为PEM的密码短语。你需要选择一些更安全的密码短语。

注意

如果你没有键入一个PEM passphrase,OpenSSL将不会返回一个错误信息,但是产生的.pem文件里面将不会含有私钥。

最后。把私钥和证书整合到一个.pem文件里:

$ cat PushCert.pem PushKey.pem > ck.pem
为了测试证书是否工作,执行下面的命令:

$ telnet gateway.sandbox.push.apple.com 2195
Trying 17.172.232.226Connected to gateway.sandbox.push-apple.com.akadns.net.
Escape character is ‘^]’.
它将尝试发送一个规则的,不加密的连接到APNS服务。如果你看到上面的反馈,那说明你的MAC能够到达APNS。按下Ctrl+C 关闭连接。如果得到一个错误信息,那么你需要确保你的防火墙允许2195端口。

然后再次连接,这次用我们的SSL证书和私钥来设置一个安全的连接:

$ openssl s_client -connect gateway.sandbox.push.apple.com:2195
-cert PushChatCert.pem -key PushChatKey.pem
Enter pass phrase for PushChatKey.pem:
你会看到一个完整的输出,让你明白OpenSSL在后台做什么。如果连接是成功的,你可以键入一些字符。当你按下回车后,服务就会断开连接。如果在建立连接时有问题,OpenSSL将会给你一个错误消息,

ck.pem文件就是我们需要得到php连接APNS 的文件,将ck.pem和push.php放入同一目录上传到服务器。

生成Xcode使用的provisioning文件

该文件用于真机调试。

生成过程:进入developer.apple.com,选择member center-certificates,Identifier & profiles-provisioning profiles,然后创建provi file。选择iOS App Development->AppId->选中之前生成的支持push的appid->选中支持的push的certi->勾选支持的device id->设置provisioning文件的文件名,即完成provisioning文件的生成。

Local/Romote_Notification

Apple 关于本地通知和远程通知的官方文档

简介

远程通知(remote notification)和本地通知(local notification)是两种用户通知类型,远程通知又称为推送通知(push notification)。这两种通知都可以实现当不在前台运行的APP通知使用该APP的用户新信息,这消息可以是消息,临近的日历,或来自远端服务器的新数据等。当操作系统呈现这些通知时,可以显示一个alert提醒或是app icon提醒。在提醒的时候也可以有声音的提示。

当用户点击通知时可以启动APP查看通知详情,也可选择不打开APP忽略通知。

注意

不管是远程通知合适本地通知都与广播通知(NSNotificationCenter)和KVO(key value observe)无关。

本地通知

Xcode 6本地通知接收不到

出现提示信息:

  1. Attempting to schedule a local notification
  2. with an alert but haven’t received permission from the user to display alerts
  3. with a sound but haven’t received permission from the user to play sounds

原因在于在iOS8系统上需要注册本地通知,这样才能正常使用

iOS8注册本地通知

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {
        [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert categories:nil]];
    }

    return YES;
}

- (IBAction)registerLocationNotification:(id)sender {

UILocalNotification *locationNotification = [[UILocalNotification alloc]init];
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:5];
locationNotification.fireDate = date;
locationNotification.timeZone = [NSTimeZone defaultTimeZone];
locationNotification.repeatInterval = NSCalendarUnitSecond;
locationNotification.alertBody = @"通知来了。。。";
locationNotification.alertAction = @"通知";
locationNotification.alertLaunchImage = @"3.png";
locationNotification.userInfo = @{@"user":@"lfx"};
locationNotification.soundName = @"sound.caf";
locationNotification.applicationIconBadgeNumber = 10;
[[UIApplication sharedApplication] scheduleLocalNotification:locationNotification];
}

回调方法

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
    //取消通知的注册
    [application cancelLocalNotification:notification];
}

远程通知(Push通知)

APNS推送机制(Apple Push Notification Service)

image

Provider:程序的后台服务器。

上图分为三阶段:

第一阶段:应用程序的服务器端把要发送的消息、目的iPhone的标识打包,发给APNS。

第二阶段:APNS在自身的已注册Push服务的iPhone列表中,并把消息发送到iPhone。

第三阶段:iPhone把发来的消息传递给应用程序,并按照规定弹出Push通知。

APNS推送通知的详细流程

image

  1. APP注册APNS消息推送,iOS向APNS Server 请求获取device token
  2. APNS向APP发送device token ,APP接受device token
  3. APP向程序的服务器端发送device token
  4. 程序服务器端发送Push通知到APNS
  5. APNS向APP发送Push通知

远程推送操作过程

  1. APP启动过程中,注册远程通知
1
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert| UIRemoteNotificationTypeSound];
  1. 若注册成功,回调方法
1
2
3
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
NSLog(@"%@", deviceToken);
}
  1. App获取device token 后,将device token 发送到自己的服务端。
  2. APNS服务器得到JSON串后,向App发送通知消息,App调用回调方法
1
2
3
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
NSLog(@"%@", userInfo);//从userInfo获得推送信息内容
}

客户端的开发

cer文件 provisioning文件的生成

下载生成的cer文件和provi文件,双击导入Xcode,在build setting中code signing一栏中选择这两个文件的名称,这样就可以将支持push的app部署到真机中。然后消息推送:

客户端对推送消息的处理分为两种情况

  1. 在App没有运行的情况下,系统受到推送消息,用户点击推送消息,启动App。此时,不会执行前面提到的didReceiveRemoteNotification方法,而是App的applicationDidFinishLaunching方法中进行推送处理,通过以下代码可以获取推送消息中数据:

    Dictionary *userInfo =[launchOptions objectForKey:UIApplicationLaunchOp
    tionsRemoteNotificationKey];

  2. 当App处于前台,系统受到推送消息,此时系统不会推送消息提示,会直接触发application:(UIApplication )application didReceiveRemoteNotification:(NSDictionary )userInfo方法,推送数据在userInfo中。
    当App处于后台时,如果系统收到推送消息时,当用户点击推送消息时,会执行application: (UIApplication )application didReceiveRemoteNotification:(NSDictionary )userInfo方法,此时AppDelegate中方法的执行顺序为:applicationWillEnterForegroundapplicationWillEnterForegroundapplicationDidBecomeActive

LLDB

Xcode调试基础

如下图:调试视图包括顶部调试命令栏,左边变量视图,右边控制台。
调试器工具栏从左到右功能分别是:断点是否有效,跳到下一个断点,单步执行,进入方法内部,跳出当前方法到上一个方法

image

定制断点

满足条件的断点

image

i == 500 时代码暂停执行

image

根据以上选项可选择不同提示,Log Message 将消息写入日志,Sound 播放声音,若勾选Automatically continue after evaluating ,则会在播放声音或写入日志后不暂停执行代码

条件综合使用的断点

image

该断点的作用是:当 i == 500,打印self.view的信息,同时ls查看根路径下的目录,输出a的值,并且播放声音且不停止执行代码

断点类型

image

符号断点(Symbolic Breakpoint)

该断点用于捕获特定方法或函数的所有方法

image

image

捕获viewDidLoad方法

异常断点 (All Exceptions)

image

异常断点,在发生异常时触发。通常会通过设置一个全局的异常断点,可提供比崩溃更详细的栈跟踪信息。有时候,异常断点能直接指出崩溃的根源。调试期间可以始终确保有一个全局的异常断点是一种最佳的实践。

LLDB调试

  • p (printf)打印标量表达式(eg a+b)或结构(CGRect)的值。po (print object)打印对象及其描述,可以查看特定内存的地址,也可以指定对象名。
  • list X:打印指定行后的10行代码。通过参数 -X可以指定断点前多少行代码
  • step (S)下一行
  • continue(C)越过断点继续执行
  • fin 执行到当前方法末尾
  • kill 终止执行程序

image

background_task

简述

iOS于2008年⾯面世时,只能有⼀一个第三⽅方应⽤用处于活动状态(位于前台)。这意味着应⽤用需要执 ⾏行的任务都必须位于前台的时候完成,否则任务将暂停并在应⽤用下次启动的时候执⾏行。iOS4推 出后,向第三⽅方应⽤用提供了后台功能。鉴于iOS设备的系统资源有限,以及省电,对后台处理有 ⼀一些限制,就是不能干扰前台应⽤用,也不能消耗太多电量。

iOS支持后台任务处理方式:

  1. 在后台完成耗时任务。这种方式适用于完成大量数据的下载或更新等任务,他们需要的时间超过了用户与应用交互的时间。
  2. 执行iOS允许的后台活动,如播放音乐、与蓝牙设备互交、监测GPS数据以获得位置发生重大变化、位置永久性网络连接让VoIP型应用能够正常运行。

检查设备是否支持后台任务

在编写使用多任务功能的代码时,必须检查设备是否支持多任务

1
2
3
4
5
6
UIDevice* device = [UIDevice currentDevice];
if (! [device isMultitaskingSupported])
{
NSLog(@"当前设备不⽀支持多任务.");
return;
}

在后台完成任务

要在后台执⾏行任务,应告诉应⽤用这项任务需要能够在后台运⾏行。另外,还应考虑需要多少内存 以及多⻓长时间才能完成。如果任务完成需要的时间超过10-15分钟,很可能任务还未完成应⽤用就 被终⽌止了。所以任务应该包含处理提前终⽌止的逻辑,并能够在重新启动应⽤用后继续执⾏行。操作 系统给应⽤用指定⼀一段时间,供它完成后台任务,但如果如果操作系统发现资源紧缺,也可能提 早终⽌止应⽤用。

后台任务的通用执行过程:

  1. 向应用请求后台任务标识符,并指定一个用来处理终止程序的快。
  2. 仅当应⽤用完了后台时间,或系统发现资源使用率过⾼进⽽决定终⽌应⽤时,终⽌处理程序才会被调⽤用。
  3. 执⾏后台任务逻辑。这包括从请求后台任务标识符到结束后台任务之间的所有代码。
  4. 让应用结束后台任务,并让后台标识符失效。
获取后台任务标识符

获取后台任务标识符同时制定终止处理程序块,使用__block 是为了block内部要对其修饰的变量修改。

1
2
3
4
5
__block NSInteger counter = 0;
__block UIBackgroundTaskIndentifier bTaskIndentifier = [[UIApplication shareApplication] beginBackgroundTaskWithExpirationHandler:
^{
...
}];
终止处理程序

系统在指定的时间或资源⽤完后,将调⽤后台任务的终止处理程序。应用即将关闭前,将在主程中调⽤用终处理程序。给终⽌止处理程序提供的时间不多(最多几秒),所以它执⾏行的操作应尽可能少。

1
2
3
4
5
__block UIBackgroundTaskIdentifier bTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:
^{
[[UIApplication sharedApplication] endBackgroundTask:bTask];//让应用指导后台任务结束
bTask = UIBackgroundTaskInvalid;//让后台任务标识符失效
}];
执行后台任务

获取后台任务标⽰符后,就可以开始在后台执⾏行任务了。再执⾏行后台任务过程中,注意从应⽤那⾥获取后台任务余下的时间。可据此决定是否接着执⾏其他的代码。通常在余下的时间还有几秒时终⽌止后台任务,让它有时间执⾏行扫尾工作。后台任务完成后,还需要做两项重要⼯作: 1. 对共享应⽤用实例调用endBackgroundTask 让应⽤用知道后台任务已结束;2. 将变量bTask设置为UIBackgroundTaskInvalid ,让这个后台任务标⽰示符⽆无效。从获取后台任务标示符到结束后台任务之间的所有代码将在后台执行。

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
__block UIBackgroundTaskIdentifier bTask =
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:
^{
[[UIApplication sharedApplication] endBackgroundTask:bTask];//让应用指导后台任务结束
bTask = UIBackgroundTaskInvalid;//让后台任务标识符失效
}];
NSInteger timeDuration = 1 * 60;
NSLog (@"Background task starting , task ID is %u",bTask);
for (int counter = 0; counter <= timeDuration;counter ++ )
{
[NSThread sleepForTimeInterval:1];
//剩余运行时间
NSTimerInterval remainingTime = [[UIApplication sharedApplication] backgroundTimeRemaining];
if (remainingTime == DBL_MA){
NSLog(@"Background Processed %d. Still in foreground.",counter);
}else {
NSLog(@"Background Processed %d. Time remaining is: %f",counter,remainingTime);
}
}
dispatch_sync(dispatch_get_main_queue()
{
[self.backgroundButton setEnabled:YES];
[self.backgroundButton setTitle:@"Start Background Task" forState:UIControlStateNorm];
}
[[UIApplication sharedApplication] endBackgroundTask:bTask];
bTask = UIBackgroundTaskInvalid;

实现后台任务

iOS⽀支持⼀组具体的后台任务,这些活动可不断地进⾏下去,不像使⽤后台任务标示符那样受到限制。这些活动不受时间上的限制,注意这些活动不应使用过多的系统资源,以避免被操作系统强⾏终⽌止。

后台活动类型
  • 后台播放音频
  • 跟踪设备位置
  • 支持ip语音应用
  • 现在‘报刊杂志’应用的新内容
  • 与外置或蓝牙配件通信
  • 在后台取回内容
  • 使用推送通知启动后台下载

SVN

svn 查看log

$ svn log

查看SVN信息

$ svn info

查看当前SVN关联目录下的文件改动

$ svn st

提交代码

$ svn ci file.m file2.m -m “提交file.m 和 file2.m”

比较某个文件与SVN上代码的改动

$ svn diff file.m //查看file.m 的变化,此命令只显示代码段的不同

注释 比较两个文件或两个工程的差异,可使用Xcode工具filemerge
打开方式:右击Xcode -> open developer tool -> filemerge

删除svn服务器代码的某个文件

$ svn del file.m //删除file.m这个文件,之后需要svn ci -m “提交删除的文件”

增加一个新文件

$ svn add file.m //并提交

注意
添加或删除某些名称中带@符号的文件,需要在其后面加个@,
eg:添加scree@2x.png的命令
$ svn add screen@2x.png@

cocoapods

简介

cocoapods

CocoaPods项目源码

安装

  1. 使用MAC自带的ruby下的gem命令:
1
2
$ sudo gem install cocoapods
$ pod setup
在执行pod setup时,会输出Setting up CocoaPods master repo,但是会执行很长时间,在此期间CocoaPods将它的信息下载到~/.cocoapods目录下,此时可以cd到该目录,使用du -sh 命令查看下载进度。使用镜像索引可以提高下载速度(下面有介绍)。
  1. 将ruby源替换成国内淘宝源
1
2
3
4
$ gem sources --remove https://rubygems.org/
$ gem sources -a http://ruby.taobao.org/
查看源是否替换成功
$ gem sources -l
  1. 如果安装的CocoaPods不能使用,可以尝试更新gem (sudo gem update —system),更新Iterm(删除原有的iterm,下载并安装新版本的iterm)。

镜像索引

所有的项目的PodSpec文件都托管在podSpec。第一次执行pod setup时,将这些索引文件更新到本地~/.cocoapods/目录下。该文件比较大,所以第一次更新比较慢。

akinkiu在gitcafeocchina上建立了CocoaPods索引镜像。gitcafe和occhina都是国内服务器,在执行索引更新操作时会比较快。

CoaoaPods设置成gitcafe镜像:

1
2
3
$ pod repo remove master
$ pod repo add master https://gitcafe.com/akuandev/Specs.git
$ pod repo update

将以上url改为http://git.oschina.net.akuandev/Specs.git即可使用occhina镜像。

用法

  1. cd到以创建的项目的目录下执行以下命令

    • pod init (生成Podfile文件,编辑该文件,添加所要加入的第三方库的名称版本(版本可以不用加))

      eg:

      pod ‘AFNetworking’, ‘~> 2.0’

      pod ‘JSONKit’

    • pod install (自动将加入的第三方库源码下载下来,且为项目设置号好相应的系统依赖和编译参数)

      注意

    • 使用CocoaPods生成的*.xcworkspace文件打开工程,而不是以前的*.xcodeproj文件。

    • 每次修改了Podfile文件,都需要执行一次pod update命令。

    • pop install之后还生成的另一个文件Podfile.lock,该文件不能放在.gitignore文件中。该文件用来锁定当前各依赖库的版本,之后及时多次执行pod install也不会更改版本,只有执行pod update才会改变Podfile.lock文件。该文件可以在多人协作时,防止第三方库升级造成大家各自的第三方库的版本不一致。Podfile.lock

  2. 查找第三方库

查找CocoaPods管理是否有你想要的库,执行命令 pod search

eg: pod search json 可查找与接送有关的所有库

  1. 生成第三方库帮助文档

使用CocoaPods生成第三方库的帮助文档并集成到Xcode中,可使用brew安装appledoc即可:

1
brew install appledoc

其优点:将帮助文档集成到Xcode中,在敲代码时可以按住opt键查看相应帮助文档

  1. 不更新podspec

CocoaPods在执行pod install 和 pod update 时,会默认更新podspec索引。禁止更新podspec的命令:

1
2
$ pod install --no-repo-update
$ pod update --no-repo-update

原理

CocoaPods的原理是将所有的依赖库都放到一个名为Pods的项目中,然互让主项目依赖Pods项目。

  1. Pods项目最终会编译成一个名为libPods.a的文件,主项目只需要依赖.a这个文件即可。
  2. 对于资源文件,CocoaPods提供了一个名为Pods-resources.sh的bash脚本,该脚本在每次项目编译的时候都会执行,将第三方的各个资源文件复制到目标目录中。
  3. CocoaPods通过一个名为Pods.xcconfig的文件在编译的时候设置所有的参数和依赖。

viewController

1.UIViewController生命周期几种方法调用时机

  1. - (id)initWithNibName:(NSString )nibNameOrNil bundle:(NSBundle )nibBundleOrNil;
    当UIViewController在初始化加载xib文件时,该方法被调用。
  2. - (void)loadView;
    当每次访问UIViewController的view(比如controller.view,self.view)并且view为nil,该方法就会被调用。
  3. - (void)viewWillUnload;
  4. - (void)viewDidUnload;
  5. - (void)viewDidLoad;
    不管是通过xib文件还是重写loadView创建UIViewController的view,在view创建完毕后,最终都会调用该方法。
  6. - (void)viewWillAppear:(BOOL)animated;
    当view将要呈现在UI界面上时会调用该方法。
  7. - (void)viewDidAppear:(BOOL)animated;
    当view已经完全过渡到屏幕上时会调用该方法。
  8. - (void)viewWillDisappear:(BOOL)animated;
    当view将要消失,或被覆盖、隐藏时会调用该方法。
  9. - (void)viewDidDisappear:(BOOL)animated;
    当view已经完全消失,或被覆盖、隐藏时会调用该方法。

2.UIViewController xib的加载过程

loadView默认实现就是在自定义的UIViewController类里不重写loadView方法,或者重写后只是在方法里简单实现[super loadView]。默认实现做了如下几个工作:

  1. 它会先去查找与UIViewController相关联的xib文件,通过加载xib文件来创建UIViewController的view
    如果在初始化UIViewController指定了xib文件名,就会根据传入的xib文件名加载对应的xib文件
    [[UIViewController alloc] initWithNibName:@”ViewController” bundle:nil];
    如果没有明显地传xib文件名,就会加载跟UIViewController同名的xib文件
    [[UIViewController alloc] init]; // 加载UIViewController.xib
  2. 如果没有找到相关联的xib文件,就会创建一个空白的UIView,然后赋值给UIViewController的view属性,大致如下:
    self.view = [[[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame] autorelease];

3.几种控制器容器的优缺点

1.UITabBarController(Tabbar底部标签式:Instagram、微信、微博)

UITabBarController作为一种容器适合管理底部标签式(TabBar 如: Instagram、微信、微博)这种结构的APP

优点

  1. 清楚当前所在的入口位置
  2. 轻松在各入口间频繁跳转且不会迷失方向
  3. 直接展现最重要入口的内容信息(默认首页)

缺点

功能入口过多时,该模式显得笨重不实用(超过5个的时候会将其他控制器添加到一个更多界面)

2.UINavigationController (Springboard跳板式:星巴克)

UINavigationController作为一种容器适合管理跳板式(SpringBoard 如: 星巴克)这种结构的APP

优点

  1. 清晰展现各入口
  2. 容易记住各入口位置,方便快速找到

确定

  1. 无法在多入口间灵活跳转,不适合任务操作
  2. 容易形成更深的路径
  3. 不能直接展现入口内容
  4. 不能显示太多入口次级内容

3.UINavigationController做整体,融合TabBarController(List Menu列表式:知乎)

优点

  1. 层次展示清晰
  2. 可展示内容较长的标题
  3. 可展示标题的次级内容

缺点

  1. 同级内容过多时,用户浏览容易产生疲劳
  2. 排版灵活性不是很高
  3. 只能通过排列顺序、颜色来区分各入口重要程度

4.UIScrollvIewController融合pageControl (Carousel旋转木马式:豆瓣同城)

优点

  1. 单页面内容整体性强
  2. 线性的浏览方式有顺畅感、方向感

缺点

  1. 不适合展示过多页面
  2. 不能跳跃性地查看间隔的页面,只能按顺序查看相邻的页面
  3. 由于各页面内容结构相似,容易忽略后面的内容

5. Drawer抽屉式:豆瓣小组

优点

  1. 兼容多种模式(页面内自有组织)
  2. 扩展性好

缺点

  1. 隐藏框架中其他入口
  2. 对入口交互的功能可见性(affordance)要求高
  3. 对排版要求高

6. Plus点聚式:Path

优点

  1. 灵活
  2. 展示方式有趣
  3. 使界面更开阔

缺点

  1. 隐藏框架中其他入口
  2. 对入口交互的功能可见性(affordance)要求高

7.Gallery陈列馆式:多看,豆瓣电影

优点

  1. 直观展现各项内容
  2. 方便浏览经常更新的内容

缺点

  1. 不适合展现顶层入口框架
  2. 容易形成界面内容过多,显得杂乱
  3. 设计效果容易呆板

8.Waterfall瀑布式

优点

  1. 浏览时产生流畅体验

缺点

  1. 缺乏对整体内容的体积感,容易发生空间位置迷失
  2. 浏览一段时间后,容易产生疲劳感