Allen Chiang

iOS程序猿的blog

© 2014. All rights reserved.

Vultr Setup Shadowsocks

搭建shadowsocks

注意

考虑到后期使用锐速加速,其支持的系统内核版本有限。 这里系统版本最好选择cnetos 6的版本

安装shadowsocks

yum install m2crypto python-setuptools
easy_install pip
pip install shadowsocks
vi  /etc/shadowsocks.json
{
    "server":"0.0.0.0",
    "server_port":443,
    "local_address": "127.0.0.1",
    "local_port":1080,
    "password":"123456",
    "timeout":300,
    "method":"aes-256-cfb",
    "fast_open": false
}

如果你的服务端运行在CentOS 6及以上版本的话,这时候你配置好客户端上的shadowsocks后,发现还是连不上Google,原因是由于CentOS默认开启了防火墙,需要手动加入相应规则。

iptables -F
iptables -A INPUT -p tcp --dport 8388 -j ACCEPT

启动命令

ssserver -c /etc/shadowsocks.json

后台运行命令

nohup ssserver -c /etc/shadowsocks.json

锐速加速

wget -N --no-check-certificate https://raw.githubusercontent.com/91yun/serverspeeder/master/serverspeeder-all.sh && bash serverspeeder-all.sh

serverspeeder破解版

适配3d-touch

适配3d-touch

3d-touch含有3种feature功能,压力感应(Press Sensitivity)、Peek和Pop手势、快捷方式(Quick Actions)

需要xcode7 GM和iOS9以上版本才能支持开发该功能

官方文档说明模拟器还不支持3d-touch的功能,不过github真是牛人比较多,也有解决办法模拟器调试quick action功能。

https://github.com/DeskConnect/SBShortcutMenuSimulator

3d-touch & Force-touch

你之前可能在iWatch上听说过类似的技术叫Force-touch,那跟现在的3d-touch一样的,还是有什么区别呢?

相对Force-touch来说,3d-touch有更灵敏的感应度,更快的响应速度。

另外Force-touch只有轻点和轻按,3d-touch多了重按。

快捷方式

申明Quick Action有两种方式:静态和动态

静态是在plist文件中申明,动态则是在代码中注册,系统支持两者同时存在。

-系统限制每个app最多显示4个快捷图标,包括静态和动态

静态

在app的plist文件中增加如下申明:

<key>UIApplicationShortcutItems</key>
<array>
<dict>

	<key>UIApplicationShortcutItemIconType</key>
	<string>UIApplicationShortcutIconTypeSearch</string>

	<key>UIApplicationShortcutItemSubtitle</key>
	<string>shortcutSubtitle1</string>

	<key>UIApplicationShortcutItemTitle</key>
	<string>shortcutTitle1</string>

	<key>UIApplicationShortcutItemType</key>
	<string>First</string>
 
	<key>UIApplicationShortcutItemUserInfo</key>
	<dict>
    <key>firstShorcutKey1</key>
    <string>firstShortcutKeyValue1</string>
   </dict>

</dict>
</array>

UIApplicationShortcutItemType:其实是快捷方式的id

UIApplicationShortcutItemTitle:标题

UIApplicationShortcutItemSubtitle:副标题(什么时候会显示暂时我也不知道,因为还没有真机可以模拟)

UIApplicationShortcutItemIconType:图标

系统自带7种图标样式分别是:Compose,Play,Pause,Add,Location,Search,Share,在plist配置的时候应该就是前面加UIApplicationShortcutIconType了,比如上面UIApplicationShortcutIconTypeSearch

UIApplicationShortcutItemIconFile: 自定义图标,上面IconType定义将被忽略。图标格式35x35像素单色。

UIApplicationShortcutItemUserInfo:额外信息

动态

UIApplication对象多了一个支持快捷方式的数组

@property(nonatomic, copy) NSArray <UIApplicationShortcutItem *> *shortcutItems

如果需要增加快捷方式,可以赋值给shortcutItems属性。

如果静态和动态方式同时使用的话,赋值的时候也不会覆盖静态方式申明的快捷方式,不用担心。

UIApplicationShortcutItem对象init方法

(instancetype)initWithType:(NSString *)type 
      localizedTitle:(NSString *)localizedTitle
   localizedSubtitle:(NSString *)localizedSubtitle
                icon:(UIApplicationShortcutIcon *)icon
            userInfo:(NSDictionary *)userInfo`

各个字段跟上面静态方式申明的时候意义一样。

其中定义快捷方式图标UIApplicationShortcutIcon,有3种init方法:

`

// 根据系统预置图标类型
-(instancetype)iconWithType:(UIApplicationShortcutIconType)type

// 根据app bundle里面的图标名称自定义
-(instancetype)iconWithTemplateImageName:(NSString *)templateImageName

// 根据通讯录联系人名称
-(instancetype)iconWithContact:(CNContact *)contact`

处理Quick Action

冷启动

顾名思义即app在没有后台进程情况下启动

demo中的做法比较值得推荐,在不打断原有应用启动顺序的情况下处理快捷方式。

-其实这里有一个疑问,

application:performActionForShortcutItem:completionHandler:

在UIApplicationDelegate的生命周期中处于哪个环节?

热启动

application:performActionForShortcutItem:completionHandler:

UIAppDelegate类的上述方法中处理快捷方式,打开对应的页面

处理成功或者失败调用block:completionHandler(YES)

参考文档

Add iOS 9’s Quick Actions shortcut support in 15 minutes right now !

3d-touch官方文档

15分钟搞定iOS9 Quick Actions

Auto Layout - iOS.6.by.tutorials笔记

因为接下来的其实是原作者Matthijs Hollemans对于Auto Layout的进阶篇内容,所以建议先阅读一下作者另外两篇关于Auto Layout基础的 在著名的raywenderlish上面有,链接如下:

Beginning Auto Layout in iOS 6: Part 1/2

Beginning Auto Layout in iOS 6: Part 2/2

魔法程式

A = B*m + c

view1.attribute = view2.attribute * multiplier + constant

同时中间的等于号你也可以使用>=或者<=来代替

通过代码添加约束

通过NSLayoutConstraint的类方法来创建一个约束:

+ (instancetype)constraintWithItem:(id)view1 
 attribute:(NSLayoutAttribute)attr1 
 relatedBy:(NSLayoutRelation)relation 
    toItem:(id)view2 
 attribute:(NSLayoutAttribute)attr2 
multiplier:(CGFloat)multiplier 
  constant:(CGFloat)c

上面constraint语法格式的含义,参考上面提到的魔法程式

image

  • 禁止添加Autoresizing mask

    translateAutoresizingMaskIntoConstraints = NO;

  • 只有当你添加一条约束的时候,Auto Layout才会生效

    [view addConstraint:constraint];

  • 设置控件自身的宽度和高度约束

    button1.width = nil * 1.0f + 200.0f

简单来看就是

button1.width = 200.0f
  • 约束的优先级

NSLayoutConstraint有一个属性名称:priority

@property UILayoutPriority priority

enum {
	UILayoutPriorityRequired = 1000,
	UILayoutPriorityDefaultHigh = 750,
	UILayoutPriorityDefaultLow = 250,
	UILayoutPriorityFittingSizeLevel = 50,
};
typedef float UILayoutPriority;	

可以看到这其实是一个float的数字,在iOS上应该介于0~1000之间。数字越大的约束将优先于数字小的生效。

部分系统控件默认带有保持自身固有尺寸的约束,比如button(个人感觉这里跟Android的wrapcontent有点像)。这个默认约束的优先级是250,也就是priority=250。所以如果你添加的控件自身尺寸大小的约束要大于250才能生效;另外系统也提供了一个方法来降低这个默认约束的优先级:

setContentHuggingPriority:forAxis:
  • 调试约束的私有api: _autolayoutTrace

添加约束的规则

  1. 如果是一个view和他的superview的约束,添加到他的superview;
  2. 是同一个superview下的两个view的约束,添加到这个superview;
  3. 只是针对一个view的约束,添加给他自己。比如width=height之类的

VFL = Visual Format Language

NSLayoutConstraint同样支持使用vfl来创建一个约束,目的是比上面的更简洁

+ (NSArray *)constraintsWithVisualFormat:(NSString*)format 
options:(NSLayoutFormatOptions)opts 
metrics:(NSDictionary *)metrics 
  views:(NSDictionary *)views

一些相对经典的vfl语句

|-[deleteButton]-(>=8)-[cancelButton]-[nextButton]-|

|-5-[deleteButton]-(>=8)-[cancelButton]-30-[nextButton]-|

|-[deleteButton]-(>=8)-[cancelButton(120)]-[nextButton(30)]-|

|-[deleteButton(==nextButton@700)]-(>=8)- [cancelButton(==nextButton@700)]-[nextButton]-|

  • 其中的deleteButton/cancelButton/nextButton等元素名称需要通过NSDictionary传入,你可以使用系统提供的宏来创建这个NSDictionary:

#define NSDictionaryOfVariableBindings(...) _NSDictionaryOfVariableBindings(@"" # __VA_ARGS__, __VA_ARGS__, nil)

  • 含有metric的vfl语句

V:[nextButton]-distance-|

其中的distance需要通过metrics dictionary传入

constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[nextButton]-distance-|" 	options:0 
metrics:@{ @"distance": @50 }
  views:viewsDictionary];`

动态布局

前面都是静态的自动布局,一旦确定了约束就确定了控件的位置,无法改变。

但是实际情况中,我们的控件往往是需要响应用户的事件,并展现出如位置、大小等的变化。以前我们大都通过setFrame等方式来实现,那伴随约束的情况下又如何实现呢?

为了便于对约束的管理和维护,我们应该把所有的约束统一的写在重载了UIViewController的updateViewConstraints方法,或者UIView的updateConstraints方法中。

- (void)updateConstraints
- (void)updateViewConstraints

每当布局展现之前,系统会自动调用上述方法。

对于UIView你也可以通过手动调用- setNeedsUpdateConstraints方法,来告诉系统布局约束需要被更新,系统会在将来自动调用上面- updateConstraints方法。

但是对于UIViewController好像就没有手动触发的方法了,可能要直接调用- updateViewConstraints方法了。

动画约束

之前做动画可能都是通过设置frame的绝对位置来实现,但是在使用了Auto Layout以后该怎么实现动画效果呢?

有如下两种方法:

1.去除旧的约束,添加新的约束

我们通过删除旧的约束,添加新的约束来实现变化,至于普通的动画么,我们也可以使用简单的方法:

[UIView animateWithDuration:0.3f animations:^{
	[self.view layoutIfNeeded];
}

2.改变已有动画的常量值

还记得上面的方程式么?A = B*m + c

我们可以通过改变c值的大小来实现动画的效果

  • -(void)setNeedsLayout和-(void)layoutIfNeeded方法的区别
  • 类似的还有如:
    • -(void)displayIfNeeded / -(void)setNeedsDisplay
    • -(void)updateConstraintsIfNeeded / setNeedsUpdateConstraints

区别在于:xxxIfNeeded方法是立即执行,而setNeedsxxx则是延迟到UIKit的下一个空闲时间片,参考RunLoop的概念。

自定义view的固有尺寸

通过重写UIView的-(CGSize)intrinsicContentSize方法返回内部尺寸大小。则Auto Layout会使用这个尺寸大小来计算布局。

iphone-device-compatibility

iphone-device-compatibility

多个SSH key的配置

应该很多大部分程序猿朋友都见过ssh,比如你在访问github之类的git代码管理工具的时候。

什么是SSH

SSH是Secure shell的缩写,即“安全外壳协议”,专为远程登录会话和其他网络服务提供安全性的协议,是一项计算机上的安全协议。

简单说,SSH是一种网络协议,用于计算机之间的加密登录。如果一个用户从本地计算机,使用SSH协议登录另一台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码也不会泄露。

最早的时候,互联网通信都是明文通信,一旦被截获,内容就暴露无疑。1995年,芬兰学者Tatu Ylonen设计了SSH协议,将登录信息全部加密,成为互联网安全的一个基本解决方案,迅速在全世界获得推广,目前已经成为Linux系统的标准配置。

需要指出的是,SSH只是一种协议,存在多种实现,既有商业实现,也有开源实现。本文针对的实现是OpenSSH,它是自由软件,应用非常广泛。

SSH的基本使用

最基本的用法比如远程登录。

假定您的用户名是xiaoming,登录远程主机baidu.com,那么一般是下面这条命令。

ssh xiaoming@baidu.com

上述命令默认连接端口22,这也是ssh协议的默认端口;当然你可以指定连接的端口,比如:

ssh -p 1212 xiaoming@baidu.com

SSH的安全验证方式

  • 基于密码

当通过账号和密码登录远程主机后,说传输的数据都会被加密,但是仍不可避免中间人攻击。

  • 基于密钥

在本地创建一对密钥(公有密钥:id_rsa.pub、私有密钥:id_rsa),把共有密钥放在需要访问的服务器上。这样每次客户端请求数据就用私钥加密,服务端拿到加密后的数据,再用服务端有的公钥解密还原真实内容。

git中SSH的使用

git中使用SSH也是先在本地创建一对密钥,然后把公钥放在服务器上。如粘贴id_rsa.pub的内容至你的github账户中的SSH Keys中,这样就建立了本地、远程认证关系。

当向服务器发送请求时,如git push origin master,推送主分支到远程仓库。会通过你发送过来的共有密钥和服务器上的共有密钥进行比较,如果两个密钥一致则服务器验证通过。这样就避免了中间人攻击。

第一次生成ssh key

  1. 生成ssh key,使用ssh-keygen命令

    ssh-keygen

运行上面的命令以后,系统会出现一系列提示,可以一路回车。

  1. 查看ssh生成的key文件,应该分别是公钥文件id_rsa.pub和私钥文件id_rsa。

    cd ~/.ssh

    ls

  2. 复制公钥文件id_rsa.pub的内容并保存到服务器端。

sshkeys

多个网站的配置

也许你刚刚配好了github的,但是现在你又要使用gitcafe做一个个人博客了,亦或者现在你的team用的却是gitlab做的代码管理,这都意味着你可能需要同时跟多个网站建立起良好的SSH关系了。

当然你可以把上面生成的id_rsa.pub的内容全部copy到上述各个网站的ssh-key管理页面上。但是作为一个有洁癖的程序员一般都鄙视这么干,这感觉就好比多个人共用了一双筷子。

于是我们需要生成多个key并分别针对不同的服务器使用不同的key,how?

  1. 生成第二个key

    ssh-keygen

当系统提示你键入文件名的时候,输入一个不同于默认(id_rsa)的名字,比如我们可以叫id_rsa_gitcafe

  1. 把id_rsa_gitcafe.pub内容复制到服务器上保存

  2. 配置不同的服务器使用不同的key

    cd ~/.ssh

在~/.ssh目录下新建一个config文件

vi config

添加如下内容

# github
Host github.com
  HostName github.com
  PreferredAuthentications publickey
  IdentityFile ~/.ssh/id_rsa

# gitcafe
Host gitcafe.com
  HostName gitcafe.com
  PreferredAuthentications publickey
  IdentityFile ~/.ssh/id_rsa_gitcafe
  1. 测试

    ssh -T git@gitcafe.com

success

done


参考资料: http://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.html http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html http://www.cnblogs.com/BeginMan/p/3544493.html