转载自:国外威客网站对比
最近开心的事
NSFetchedResultsController查询的对象不属于它的Section
当你使用NSFetchedResultsController来显示你数据库里的数据时,你一定被它的方便之处感动的飞起。但是如果你刚刚学会使用这个类,或者第一次用它来显示section,你可能遇到这个坑。
推荐阅读这里
[译]实现Twitter iOS 客户端的UI
继续填坑,原文在这里
[译]用UIBezierPath做弹性动画
继续填坑,原文在这里
[译]Reset, Checkout, and Revert
翻译自这篇文章
git reset
, get checkout
和 git revert
命令是你Git工具箱中最有用的几个工具。它们可以让你在仓库中撤销某些改变,前两个命令也可以用来处理提交或者单个的文件。
因为他们很相似,所以在特定的开发场景下,使用哪种命令就很容易混淆。在这篇文章中,我们将比较这三个命令常见的配置,希望你能自行的用这些命令去驾驭你的仓库。
这帮助我们去想每一个命令在这三个Git仓库主要组件(工作区,快照,提交历史)中的作用。当你读这篇文章的时候,时常回想这些组件。
提交层面的操作
你传给 git reset
和 git checkout
的参数决定了它们的作用域。当你不包含一个文件路径做参数时,它们作用于整个提交。这是我们在这一章节将要介绍的内容。注意 git revert
并没有文件层面对应的内容。
Reset
在提交层面,重设是移动分支末端到另一个不同的提交的一种方式。这能用来从当前分支移走一些提交。比如,下面的命令把 hotfix 分支向后移动两个提交。
1 | git checkout hotfix |
这两个位于hotfix末端的提交现在正在摇摆,也就是说,它们将会在Git下次执行垃圾收集的时候删除。换言之,你可以说你想要抛弃这些提交。下图看起来会比较直观:
git reset
的使用是一个简单的方式去撤销还未分享给他人的更改。这是你将要用到的命令当你已经开始在一个feature分支上工作,然后你发现自己一直在想,“卧槽,我在干啥?我应该从头开始。”
另外,移动当前分支时,你也可以通过传递一下的某个标识,让 git reset
去修改快照区和/或工作区。
1, –soft - 快照区和工作区不会被修改。
2, –mixed -快照区将会更新到特定的提交,但是工作区不会受影响。这是默认选项。
3, –hard -快照区和工作区都会更新到特定的提交。
当定义这个 git reset
操作的作用域时,它将会容易去思考这些模式。
这些标识常常和 HEAD
参数一起使用。比如 git reset --mixed HEAD
清空快照区,但是保留工作区的更改。另一方面,如果你想完全抛弃所有未提交的更改,你可以使用 git reset --hard HEAD
. 这是 git reset
最常用两种使用方式。
当传入的提交是 HEAD
以外的参数时,一定到小心,因为这将会重写当前分支的历史。正如在The Golden Rule of Rebasing中提到的,当工作在一个公共分支时,这将是一个大问题。
Checkout
到现在为止,你应该比较熟悉 git checkout
的提交层面。当传递一个分支名称时,它让你在不同分支间切换。
1 | git checkout hotfix |
本质上讲,这个命令所做的就是移动HEAD到另一个分支,并且更新工作区使之于其匹配。因为这有重写本地更改的风险,Git强制你提交或者暂存工作区里的任何更改,以防这些更改在checkout操作中丢失。并不像 git reset
那样,git checkout
并不会向前后移动任何分支。
你也可以检出任何提交通过传递一个提交引用而不是分支。这确实也像检出一个分支那样:它移动这个HEAD引用到特定的提交。比如,下面的命令将检出当前提交的父父层。
1 | git checkout HEAD~2 |
这对于快速查看项目中老的版本十分有用。但是,由于对于当前的HEAD并没有指定分支引用,这将把你放进一个临时的HEAD状态。如果此时你增加新的提交,那就会比较危险,因为当你切换到另一个分支之后,你就没有办法再找到它们。因为这个原因,在你增加新的提交到一个暂存的HEAD状态前,你应该新建一个新分支。
Revert
恢复原状通过提交一个新的提交去撤销一个提交。这是撤销改变的一个安全的方式,因为它不会改变或者重写提交的历史。比如,下面的命令将会找出最后两个提交的改变,创建新的提交去撤销那些改变,并且把这个新的提交钉在这个项目上。
1 | git checkout hotfix |
下图更直观:
和 git reset
做比较,这个命令并不修改已存在的提交历史。因为这个原因,git revert
应该在公共分支上使用来撤销更改,git reset
应该在个人分支上使用来撤销更改。
你也可以认为 git revert
是撤销已提交更改的工具,而 git reset HEAD
是撤销未提交更改的工具。
像 git checkout
,git revert
都有重写工作区文件的风险,所以当你进行这些操作时,都会被要求提交或缓存更改。
文件层面的操作
这个 git reset
和 git checkout
命令也允许一个可选的文件路径作为参数。这将修改它们的行为。代替操作整个快照区,这种方式将会限制它们操作在单个文件中。
Reset
当传递一个文件路径调用时, git reset
更新这个快照区去匹配特定提交的版本。比如,下面命令将会取得foo.py的倒数第二次提交的版本,并且在下一次提交时存储它。
1 | git reset HEAD~2 foo.py |
和提交层面的 git reset
一样,和HEAD搭配使用是比较常见的。git reset HEAD foo.py
将会取消暂存foo.py. 但是它所包含的更改在工作区中还是可见的。
这个 --soft
, --mixed
和 --hard
标识对文件层面的 git reset
并没有什么卵用。因为快照区一直在更新,而工作区从来不更新。
Checkout
检出一个文件和使用git reset
后面带一个文件路径是类似的,唯一的不同是,它更新的是工作区而不是暂存区。并不像提交等级的版本那样,这个命令并不会移动HEAD
的引用,这意味着你将不会切换分支。
比如,下面的命令将会使在工作区里的foo.py文件匹配倒数第二次提交的这个文件。
1 | git checkout HEAD~2 foo.py |
像提交等级的git checkout
命令一样,这被用来检查一个项目的老的版本——但是他的作用范围是指定的文件。
如果你暂存和提交这个检出的文件,这还会有回退到老文件的作用。注意这将移除所有随后的改变。但是git revert
命令仅仅撤销某个指定的提交的改变。
像git reset
一样,这个命令常常和HEAD一起使用。比如,git checkout HEAD foo.py
有丢弃未暂存的更改的作用。这有点类似git reset HEAD --hard
,但是它操作的是指定的文件。
总结
你现在应该拥有所有工具去撤销改变了。git reset
,git checkout
,git revert
命令可能是让人迷惑的,但是当你想一想它们对工作区,暂存区和提交历史的作用,对于那种命令适合哪种开发任务将会变的容易区别。
下面的表格总结一些常用的用例,确保把这个手册放在手边,因为在你的Git生涯中,无疑你会用到它们中的一个或多个。
Command | Scope | Common use cases | |
---|---|---|---|
git reset | Commit-level | Discard commits in a private branch or throw away uncommited changes | |
git reset | File-level | Unstage a file | |
git checkout | Commit-level | Switch between branches or inspect old snapshots | |
git checkout | File-level | Discard changes in the working directory | |
git revert | Commit-level | Undo commits in a public branch | |
git revert | File-level | (N/A) |
HEXO 重装记录
OSX EL Capitan 发布后神奇的是我的电脑无法正常升级,无奈重新做了安装盘重装了系统。这一装不要紧,最近写的博文都无法发表了。查看了hexo的版本号,发现我使用的是2.8.3的版本,而我重装的hexo是3.1.1的版本,看来不得不升级了。
在原Blog目录下折腾是没戏了。那么第一步是: 新建Blog文件夹,初始化Blog。
1 | mkdir Blog |
第二步是覆盖_config.yml
文件,这里面有一点要注意的是老的deploy标签下的type是github,新的改成了git。
老的:1
2
3deploy:
type: github
...
新的:1
2
3deploy:
type: git
...
第三步是拷贝你用到的module到node_modules目录下,我这里用到了一个hexo-tag-asset-res
库,是用来保持首页和详细页中的图片连接指向同一个资源。
1 | cp -R ../Blog_HEXO/node_modules/hexo-tag-asset-res node_modules |
第四步是覆盖source和themes文件夹,比较幸运的是我选的主题在新的框架下还能用,似乎更酷了。
1 | cp -R ../Blog_HEXO/source . |
OK, 这时候hexo g
一下,再hexo s
一下,打开浏览器输入http://0.0.0.0:4000/
, 很棒!所有的都没有丢失,还给你多加了一篇Hello World。
OK,开始发布到Github,于是你:
1 | hexo d |
于是终端告诉你…
1 | ERROR Deployer not found: git |
别担心,不会前功尽弃的,只要你:
1 | npm install hexo-deployer-git --save |
Enjoy :)
[译]如何用Node.js实现SSL/TLS
最近iOS9发布,强制App使用HTTPS传输,做为一个入坑多年的iOS程序员,还真是不了解这其中的来龙去脉,刚好订阅的Node.js周报中推送了这篇文章,赶紧翻译过来,既搞清了HTTPS又学习了Node.js,一举两得。
使用HTTPS正在变的越来越普遍,因此我们应该知道怎么在Node.js程序中实现SSL/TSL——不论是为了访问HTTPS资源还是为了提供加密的资源。HTTPS到底是什么意思呢?它暗示了什么?有什么限制和约束?我们将试着为所有的这些问题找到答案。
另外,我们不应该仅仅通过提供HTTPS来保护我们的客户端,而且我们也应该严格要求来自服务器的是加密过的连接。我们将会看到激活SSL/TLS层的可能性的存在,即使默认情况下不能激活。让我们先来浏览一下HTTPS的当前情况。
HTTPS Everywhere
在2015年2月17日,HTTP/2协议被IESG许可作为推荐的标准发布。这是一个大的里程碑。现在我们可以更新我们的服务器去使用HTTP/2。一个重要的方面是它与HTTP1.1和握手机制的向后的兼容性。虽然这个标准并没有指明要强制加密,但大部分浏览器将仅仅支持TLS之上的HTTP/2协议。这给了HTTPS另一方面的促进。最终,HTTPS everywhere!
那我们的协议栈看起来是怎样的呢?从一个在浏览器中跑的网站的透视来看,我们大致有下面的一些层到达IP层。
- 用户浏览器
- HTTP
- SSL/TLS
- TCP
- IP
对比SSL/TLS顶端的HTTP协议来说,HTTPS啥也不多。因此,所有对于HTTP的规则仍然适用。那额外的层给了我们什么呢?给了很多好处。我们通过拥有Keys和证书来获得授权。当连接以一种不对称的加密时,还有某种隐私和机密被保护。最后但不仅仅还有数据的真实性也会得到保护,比如,那些传输完成的数据在传输过程中是不能被改变的。
其中一个最普遍的错误观念是使用SSL/TLS需要太多的资源并且会拖慢服务器的速度。这无异是错误的。我们也不需要任何特制的拥有密码单元的硬件。甚至对于Google来说,SSL/TLS层的消耗也小于百分之一的CPU的加载。更进一步的讲,HTTPS的网络开支会低于HTTP的百分之二。总而言之,如果因为一点网络开支而放弃HTTPS,这是没有道理的。
最新的版本是TLS1.2(目前1.3版本作为工作草案是可用的)。TLS是SSL的继承者,在最新发布的SSL3.0中可以使用。从SSL到TLS的改变杜绝的互通性。但是基本的流程是不变的。我们有三种不同的加密途径。第一个是证书链公钥基础结构,第二个是提供公钥密码作为Key交换。最后,第三种是对称。这里我们对于数据传输有密码逻辑。
我们可以使用很多哈希算法,比如MD5,SHA1,SHA256. MD5已经被降级了,我们不应该使用它了。SHA1仍然是可接受的,但可能不久后也会被降级。比较好的是SHA256,它当前拥有更多的用户。用SHA256有一个问题是老的系统是否支持它,比如,在Window XP上,SHA256只能通过安装Service Pack 3才能使用。
HTTPS也正在获得更多客户端的关注。隐私和安全问题一直存在,但随着在线访问数据和服务人数日益增长都越来越关受注。一个有用的浏览器插件是 HTTPS Everywhere
,它可以加密我们与大多数网站之间的交流。
这个插件的作者认识到很多网站仅仅有一部分提供了HTTPS功能。这个插件允许我们重新请求这些只有部分支持HTTPS的网站。
可选的,我们也可以同时屏蔽HTTP请求(如上面的截图所示)
Basic Communication
这个证书的认证过程包括验证证书签名的有效性和过期时间。此外我们还要验证它链接到可信任的根证书。最后,我们需要去检测它是否已经被撤销。
HTTPS握手的流程图像下图一样。我们从客户端的初始化开始,伴随其后的是一条带有证书和Key交换的信息。在服务器返回完整的包之后,客户端开始Key交换和密码详情的传输。这时,客户端已经完成。最后服务器确认对密码详情的挑选,然后关闭握手。
这整个流程被触发独立于HTTP。如果我们决定使用HTTPS,仅仅改变的是对Socket的处理。客户端仍然发起的是HTTP请求,但是socket将会执行前面描叙的握手协议和数据加密。
所以,在Node.js中,什么包能处理SSL/TLS呢?下面我们将会简单的讲到三种标准的包。
ssl-root-cas
当我们在处理自定义的或过期的证书遇到问题时,ssl-root-cas
能够帮助我们。当许可证不可用时,它也很有帮助。
归结起来,大部分时间会用到下面的命令。这个inject
方法修改https.globalAgent.options.ca
去包含一系列的证书。
1 | require('ssl-root-cas').inject(); |
但是,有时也可能需要增加本地自定义的证书。
1 | require('ssl-root-cas').addFile('my-cert.crt'); |
从 ssl-root-cas
模块返回的这个对象是可串的,因此能够用来增加多个文件或注入多个标准文件在一次调用中。
https
类似于http
,我们可以使用https
. 这个主要的区别是如果我们需要发布我们的服务器,我们需要提供一个key。这将会在下一章节讨论。
现在我们仅仅看一下我们怎么创建一个HTTPS请求。
1 | var https = require('https'); |
基本上,https
提供和http
相同的功能。但是在最上层增加了SSL/TLS层。API大部分是相同的。
tls
tls
模块需要openssl
工具包,下一章节将会讨论openssl
工具包。这个模块为加密的流传输提供了SSL/TLS。本质上,https
也使用了tls
。所以,使用tls
API时感觉会和http
模块的方法相关就不是啥惊奇的事了。
下面简单的代码创建了一个在8000端口监听连接的服务器,进来的连接讲接收一个加密后的数据。
1 | var tls = require('tls'); |
类似的,我们也可以连接这样一个服务器。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16var tls = require('tls');
var fs = require('fs');
var options = {
key : fs.readFileSync('private.key'),
cert : fs.readFileSync('public.cert')
};
var client = tls.connect(8000, options, function () {
console.log(client.authorized ? 'Authorized' : 'Not authorized');
});
client.on('data', function (data) {
console.log(data.toString());
client.end();
});
现在,我们应该看一下怎样生成我们自己的key和证书文件。
Generating Certificates
从技术的角度上来看,证书并不是强制的。不过,由于网络的开放性,如果不增加证书,中间人攻击就会变得太平常。因此,一个被可信赖证书认证(CA)的证书是按需求而定的。CA确保了证书的持有者就是这个证书的创建者。
下面,我们会使用openssl
工具。这个程序将会给我们用RSA加密生成私有Key的能力。我们也能够发起一个证书签名的请求(CSR)。更进一步的,这个OpenSSL项目的核心库还能生成自签名的证书。这些证书可以用来做测试,它们不应该公开使用。
第一步是创建一个私有的Key。作为一个例子,我们可以使用下面的命令,生成一个叫server.enc.key的文件。
1 | openssl genrsa -des3 -out server.enc.key 1024 |
这个生成的RSA Key是一个1024字节的用三倍DES加密的key。这个文件是人类可读的。作为一个轻量的变形,我们也可以省略掉-des3
选项,并且改变加密的强度,比如2048
。虽然在这个例子中我们使用了1024字节的key,但是对于真是的Key,我们应该最少使用2048字节的长度。
一旦我们拥有一个生成的Key,我们需要发起一个证书签名的请求。一个证书可以用如下的命令生成:
1 | openssl req -new -key server.enc.key -out server.csr |
生成的CSR存在于server.csr文件中。我们需要对这个文件进行自签名。
到这时,当使用server.enc.key文件中的key时,我们需要输入一个密码。由于我们仅在内部使用这个证书,所以我们可以移除密码保护。移除3倍的DES加密用下面的命令。
1 | openssl rsa -in server.enc.key -out server.key |
现在这个原始加密的server.enc.key文件被转换成非加密的文件server.key。
最后,我们要对这个证书进行自签名。自签名的证书将会在浏览器中生成一个错误。这是因为这个自签名的证书的权威机构是未知的,因此不被信任。为了生成一个临时的证书server.crt,我们需要发送下面的命令。
1 | openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt |
这个证书将会在发出这个命令的365天内过期。
Integration with Express
使用HTTPS代替HTTP是可能的也是被期望的。我们将开始使用Express编写一个小的Node.js应用。
1 | var http = require('http'); |
启动HTTPS我们需要做啥更改呢?显然,我们需要导入一个不同的包。最后我们也需要提供正确的Key/证书。所有文件的内容需要被展现,它们被传递到https
包的createServer
方法。
让我们用SSL/TLS重写我们的Express例子:
1 | var fs = require('fs'); |
就是如此简单!在上面的例子中,我们假设key和证书都位于工作目录中。这仍然有很大的提升空间。一个可能性是放这段代码到创建server的module中。这个module将会根据选择不同的协议来选择正确的包。另外,这个端口,key和证书应该驱逐到一个settongs
对象中。
一个简单的实现可能看起来如下:
1 | var fs = require('fs'); |
关键的地方是settings
中的ssl
对象,如果这个对象存在并且有个叫active
的参数设置为true,那么我们将会用提供的Key/证书启动SSL/TLS。
Conclusions
在2015年,没有理由再去忽视HTTPS了。未来的方向是清晰可见的——到处都是HTTPS!在Node.js中, 我们有很多选择去管理SSL/TLS。我们可以发布我们HTTPS的网站,我们可以对加密的网站发起请求,我们也能授权哪怕不被信任的证书。
Helpful JS Resources Recommanded by Code School
完成了code school中的JS课程部分,纪录一些老师推荐的网站
Cocoa Autolayout: Content Hugging vs Content Compression Resistance Priority
###Intrinsic Content Size
The intrinsic content size is the size a view prefers to have for a specific content it displays. For example, UILabel has a preferred height based on the font, and a preferred width based on the font and the text it displays. A UIProgressView only has a preferred height based on its artwork, but no preferred width. A plain UIView has neither a preferred width nor a preferred height.
###Compression Resistance and Content Hugging
Each view has content compression resistance priorities and content hugging priorities assigned for both dimensions. These properties only take effect for views which define an intrinsic content size, otherwise there is no content size defined that could resist compression or be hugged.
Behind the scenes, the intrinsic content size and these priority values get translated into constraints. For a label with an intrinsic content size of { 100, 30 }, horizontal/vertical compression resistance priority of 750, and horizontal/vertical content hugging priority of 250, four constraints will be generated:
1 | H:[label(<=100@250)] |
If you’re not familiar with the visual format language for the constraints used above, you can read up about it in Apple’s documentation. Keeping in mind that these additional constraints are generated implicitly helps to understand Auto Layout’s behavior and to make better sense of its error messages.
Quick summary of the concepts:
- Hugging => content does not want to grow
Compression - Resistance => content does not want to shrink
and an example:
Say you’ve got button like this:
[ Click Me ]
and you’ve pinned the edges to a larger superview with priority 500.
Then, if Hugging priority > 500 it’ll look like this:
[Click Me]
If Hugging priority < 500 it’ll look like this:
[ Click Me ]
If superview now shrinks then, if the Compression Resistance priority > 500, it’ll look like this
[Click Me]
Else if Compression Resistance priority < 500, it could look like this:
[Cli..]
If it doesn’t work like this then you’ve probably got some other constraints going on that are messing up your good work!
E.g. you could have it pinned to the superview with priority 1000. Or you could have a width priority. If so, this can be helpful:
Editor > Size to Fit Content