Ezio's Blog

record


  • Home

  • Categories

  • Archives

  • Tags

  • About

iOS绕过HTTPS证书校验

Posted on 2016-12-17   |  

  iOS开发中使用的通信协议,除了聊天和物联网相关的APP可能会用到XMPP和MQTT,剩下的应用通常都只会用到HTTP和HTTPS这两种协议,而由于ATS的限制,iOS默认都是实用HTTPS,除非修改项目的info.plist:

对于HTTPS,熟悉HTTPS协议的人都知道,HTTPS基本上就是在HTTP协议的基础上加了一层SSL/TLS加密协议,这层加密协议在建立通信时除了HTTP本身的3次握手外,还会再经历额外的身份校验、数据加解密过程:

这些过程中会混合使用非对称加密、对称加密、证书校验和数字签名等手段,其中证书校验的过程:

  1. 首先,服务器的运营人员向数字证书认证机构提出公开密钥的申请。数字证书认证机构在判明提出申请者的身份之后,会对已申请的公开密钥做数字签名,然后分配这个已签名的公开密钥,并将该公开密钥放入公钥证书后绑定在一起。
  2. 服务器会将这份由数字证书认证机构颁发的公钥证书发送给客户端,以进行公开密钥加密方式通信。公钥证书也可叫做数字证书或直接称为证书。
  3. 接到证书的客户端可使用数字证书认证机构的公开密钥,对那张证书上的数字签名进行验证,一旦验证通过,客户端便可明确两件事:一,认证服务器的公开密钥的是真实有效的数字证书认证机构。二,服务器的公开密钥是值得信赖的。
  4. 此处认证机关的公开密钥必须安全地转交给客户端。使用通信方式时,如何安全转交是一件很困难的事。因此,多数浏览器开发商发布版本时,会事先在内部植入常用认证机关的公开密钥。

而通常在开发环境中服务端会使用自签名证书,或者即使在生产环境中可能也会使用免费的证书,这些证书的认证机构可信度通常低于那些收费的大型认证机构,这样,在步骤3的时候客户端对证书的认证可能就失败了。最近在开发公司的iOS SDK就碰到这个问题,直接调用HTTPS接口会报错:

HTTP load failed (kCFStreamErrorDomainSSL, -9843)

明白了原理后,解决方案就简单了,只需要客户端在校验时对使用的域名设置白名单就行了,以下是使用NSURLSession时需要在delegate上做的修改:

NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:Nil];


- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler{
    if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]){
        if([challenge.protectionSpace.host isEqualToString:@"recvapi.log.dtstack.com"]){
            NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
        } else {
            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
        }
    }
}

这样就可以解决开发时的证书校验失败的问题。

但这只限于开发阶段,治标不治本,不能在生产环境下使用,要想治本,最好还是更换服务器证书,找个可信度高的大型认证机构重新弄份证书。

服务端更换证书也简单,以Nginx为例,拿到证书后,修改Nginx的配置:

server { 
    listen 443 ssl;
    server_name example.com;

    ssl on;
    ssl_certificate /etc/ssl/private/example_com.crt;
    ssl_certificate_key /etc/ssl/private/example_com.key;
}

然后重启服务就行了:

nginx -t && nginx -s reload

iOS framework开发流程总结

Posted on 2016-12-10   |  

最近在做一个iOS的统计SDK,需要从零开始做一个framework,同时为了方便开发,花了点时间折腾,于是顺便总结一下iOS framework的开发流程,不同的Xcode版本流程会有些小区别,以下使用的是7.3.1。

建立framework工程

建framework工程之前,要先了解framework

framework和.a

iOS一直只对用户开放静态库,直到iOS8用户才能用动态库,然而这个动态库貌似也只能是进程内,无法跨进程共享。

我们用的更多的还是静态库,iOS静态库有两种类型,framework和.a,看过linux系统方面的人对.a和.so应该都不陌生,事实上苹果下的.a和linux下的.a从格式上来看不是同一个东西,一个是Mach-O,一个是ELF,但其实Mach-O只是苹果在ELF的基础上添加一些额外的段,可以认为基本一样。那么framework呢?可以认为framework只是对.a的一层额外的封装,类似苹果对ipa的封装,把.a文件包装进一个结构化的目录结构,这样就是一个framework。由于framework本身是一个目录,于是可以把属于framework内部的一些资源也放进去,比如头文件、图片、音视频文件等等,从封装的角度来看,framework是比.a更好的选择。

其实,我们不需要了解这么多,也不需要自己建这些目录层次,xcode已经帮我们做了大部分的工作,我们需要的只是改几个配置。

基本设置

新建framework工程:

填好framework名称,确定,就生成了一个完整的framework工程:

运行一下,红色的framework就变黑,说明framework已经生成了。但这个framework并不是我们想要的

这个framework只有arm7和arm64两种架构的指令内容,如果直接发布这个framework,开发者将无法在模拟器上编译,后续我们会说到多架构指令的必要。另外,这是一个动态库,我们需要的是静态库。

在Build Setting里设置以下几个参数



Architectures:包含哪些架构指令,这里我们需要添加armv7s架构
Build Active Architecture Only:是否只为当前架构编译
Dead Code Stripping:是否从framework中删除未使用的代码
Link With Standard Libraries:是否链接苹果标准库
Mach-O Type:这里有好几种类型,我们需要选中static library
Other Linker Flags:链接参数,如果framework中使用了category,最好加上ObjC、all_load,确保运行时系统会加载其中的category
Other C Flags:额外的C语言链接参数,如果需要支持bitcode,需要加上-fembed-bitcode
Generate Debug Symbols:生成Debug符号,设为Yes,这样作为依赖工程时断点才会生效

重新编译运行:

这离我们想要的framework不远了。

另外,我们新建一个类,毕竟,我们要做一个统计SDK

#import <Foundation/Foundation.h>

@interface DTTrackManager : NSObject

- (void)trackEvent:(NSString *)event;

@end

@implementation DTTrackManager

- (void)trackEvent:(NSString *)event {
    NSLog(@"you are tracking event: %@", event);
}

@end

我们想要把DTTrackManager开放给开发者,让他们能使用这个类,还需要做一点额外设置:

这样,打包出来的framework就包含了我们想要公开的头文件了

多架构和打包

不同的CPU使用不同的指令,我们一般称一套指令为一种架构,比如笔记本电脑的CPU和移动端手机的CPU使用不同的指令,类似的,32位CPU与64位CPU使用不同的指令,因此我们需要一个能包含所有架构指令的framework,这样,开发者才能在不同的CPU环境下都能使用我们的framework。

我们现在的framework包含了3种架构指令,armv7、armv7s、arm64,这些都是iOS系统使用的架构,macbook等macOS系统是无法使用这个framework的,这就导致开发者目前是无法用这个framework在模拟器上调试。

因此,我们需要再添加i386和x86_64这两种桌面端系统使用的架构。我们可以单独编译这两个架构,然后用lipo命令手工合成,但xcode提供了一个更好的方案。

选中刚创建的DTTrackerCombiner,在Build Phase下添加一个执行脚本:

脚本内容:

set -e

UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal


mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"


xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos  BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -arch x86_64 -arch i386 -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build


cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"


lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"


cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}"


open "${PROJECT_DIR}"

ps:
-arch x86_64 -arch i386
为模拟器编译的两个架构需要显式指定,否则编译报错

选择正确的scheme和目标,开始编译

如果编译成功,会弹出编译好的framework所在目录,检查下是不是包含了我们想要的全部架构

One More Thing!
把打包scheme的配置改为release

这样,我们只要把源文件放入这个工程里,设置好需要公开的头文件,就能编译出我们想要的framework了,非常方便。但是,实际开发中,我们需要一边开发framework,一边在使用这个framework的Demo工程里测试这个framework,如果每次都需要编译一遍framework工程,然后在Demo工程里替换framework,这会严重影响开发效率。

Demo工程

新建一个DTTrackerDemo工程,注意Deployment Target设置不要低于framework的。

接入framework工程

接入framework工程很简单,在Finder里找到DTTracker.xcodeproj,直接拖入DTTrackerDemo工程中就行了

这样,就可以直接在Demo工程里运行framework工程的target来编译framework了。注意,framework工程只能存在一份,额外的framework工程必须关掉,否则DTTrackerDemo工程里会找不到DTTracker.xcodeproj下的文件和target。

我们需要在每次运行Demo工程时先运行framework工程,这样才能获取最新代码,因此在Demo工程的Build Phase中添加对framework的依赖

这里的Target Dependencies选择DTTracker而不是DTTrackerCombiner只是因为可以缩短打包时间,毕竟DTTrackerCombiner需要把5份架构打进去,而DTTracker只需要打3份。至于为什么DTTracker明明不包含模拟器的架构却可以启动Demo APP,这个需要看下Demo APP的所在目录

Demo APP被放在Debug-iphonesimulator目录下,再看下该目录下的DTTracker.framework

没毛病,是模拟器需要的架构。

开发流程

万事具备,来测试一下我们的framework。

在Demo工程的ViewController.m引入framework头文件:

#import <DTTracker/DTTrackManager.h>

初始化一个DTTrackManager并调用trackEvent方法

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    DTTrackManager *tracker = [[DTTrackManager alloc] init];
    [tracker trackEvent:@"viewDidLoad"];
}

运行

完美!

那打包framework呢?直接在Demo工程里,选中DTTracker.xcodeproj,选中我们之前添加Aggregate target对应的scheme:DTTrackerCombiner,直接打包

至此,我们完成了

  1. framework工程的建立和优化,能独立编译可以直接发布的framework
  2. 在Demo工程添加对framework工程的依赖,建立了framework开发流程

这样,整个我们就可以愉快地开发framework了!

关于framework还有一些没提到的内容,比如bundle资源、添加framework自定义编译宏,后续有时间再写。

Invictus 不可征服

Posted on 2016-12-03   |  

  Out of the night that covers me, 透过覆盖我的深夜,

  Black as the Pit from pole to pole, 我看见层层无底的黑暗。

  I thank whatever gods may be 感谢上帝曾赐我,

  For my unconquerable soul. 不可征服的灵魂。

  In the fell clutch of circumstance 就算被地狱紧紧攫住,

  I have not winced nor cried aloud. 我不会畏缩,也不惊叫。

  Under the bludgeoninmgs of chance 经受过一浪又一浪的打击,

  My head is bloody, but unbowed. 我满头鲜血都不低头。

  Beyond this place of wrath and tear 在这满是愤怒和眼泪的世界之外,

  Looms but the Horror of the shade, 可怕的阴影在游荡。

  And yet the menace of the years 还有,未来的威胁,

  Finds, and shall find, me unafraid. 可我是毫不畏惧的。

  It matters not how strait the gate, 无论我将穿过的那扇门有多窄,

  How charged with punishments the scroll, 无论我将肩承怎样的责罚。

  I am the master of my fate: 我是命运的主宰,

  I am the captain of my soul. 我是灵魂的统帅。

常用Docker命令

Posted on 2016-11-26   |  

用Docker已经有段时间了,积累了一些常用命令,记录一下

启动容器

docker run -it lingwu/kafka

启动并进入容器控制台

docker run -it --rm -v /Users/ezio/docker_volume/webapp:/webapp -p 3000:80 webapp sh

以后台进程启动

docker run -d -v /Users/ezio/docker_volume/webapp:/webapp -p 3000:80 webapp

查看正在运行的容器

docker ps

查看所有容器(运行中和已停止)

docker ps -a

查看容器中的进程信息

docker top es

查看端口映射

docker port 9b7bb332ab88

查看log

docker logs 9b7bb332ab88

进入容器

docker exec -it 9b7bb332ab88 sh

停止容器

docker stop 9b7bb332ab88

重启容器

docker start 9b7bb332ab88

删除容器

docker rm 9b7bb332ab88

删除所有容器

docker rm docker ps -qa

删除镜像

docker rmi webapp

从容器生成镜像

docker commit -a 作者名字 -m 提交原因 容器ID 镜像名称:版本号 
docker commit -a "lingwu" -m "added vim" 13d26d692be1 lingwu/kafka:v1 

把镜像推送到仓库

docker login
docker push lingwu/kafka

参考: https://github.com/wsargent/docker-cheat-sheet

那些把我们坑惨了的bug

Posted on 2016-11-19   |  

说说我所碰到的几个比较折腾的bug

vpn + reachability

之前在开发宝宝拍拍app的时候,需要监控网络状态,一旦有网络,需要尽快把本地图片上传到阿里云OSS,因为上传图片的同时,还需要把SQLite记录上传到我们自己的服务器,所以就这么写了:

reach = Reachability reachabilityWithHostname:@"http://ibbpp.com/"
本地测试了下,没问题,于是就放心提交了。
后来客户反馈说在有网状态下,图片一直没上传。

首先怀疑是服务器挂了,结果发现http://ibbpp.com/首页能正常打开。用自己的手机测试了下,也没问题。

最终发现客户的截图上显示有挂VPN,于是挂上VPN测试,果然。同时,客户在国外没挂VPN也能复现这个问题。

于是猜测很可能是网络本身的问题,比如DNS解析服务。最终的解决方案:

reach = Reachability reachabilityWithHostname:@"www.baidu.com"
当然,当我们服务器挂了,只要阿里云OSS服务没挂,图片还是能正常上传,不会影响业务逻辑。

这里有个小问题。Reachability底层使用SCNetworkReachabilityRef来监测网络状况

+(Reachability*)reachabilityWithHostname:(NSString*)hostname
{
    SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]);
    if (ref) 
    {
        id reachability = [[self alloc] initWithReachabilityRef:ref];

        return reachability;
    }

    return nil;
}

而SCNetworkReachabilityRef本身是不准确的:

The SCNetworkReachability programming interface allows an application to determine the status of a system’s current network configuration and the reachability of a target host. A remote host is considered reachable when a data packet, sent by an application into the network stack, can leave the local device. Reachability does not guarantee that the data packet will actually be received by the host

在局域网没有连接互联网的情况下,比如家里 WiFi能连上但宽带欠费了,SCNetworkReachability还会显示网络可用。

最好的方案还是直接调用一个自定义的服务器接口,使用短超时和特定返回来监测网络状况。或者直接Ping也行。

messageid

在IM应用中,需要记录消息的id,这个id一般位数会比较长,比如64bit。后续从数据库中取出时需要经过JSON序列化,比如

NSJSONSerialization JSONObjectWithData:self options:NSJSONReadingAllowFragments|NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:error
而苹果的NSJSONSerialization在iOS7和iOS7以下的系统上转换大数值时会使用NSDecimalNumber,在iOS8上会使用CFNumber。

而苹果在设计NSDecimalNumber时,只保证53bit的精度,所以任何超过这一精度的数值在JSON序列化之后,如果直接通过unsignedLongLongValue方法来获取时都可能会出错。

解决方案,先转化为字符串再转成数值:

[[decimalNumber description] longLongValue]

保存Git用户名密码

Posted on 2016-11-12   |  

在部署服务时,一般都会有jenkins等工具来完成一键部署,但有时还是免不了需要登录远程主机手工部署,这时,如果能在远程主机上保存下Git的用户名密码,就可以提供不少工作效率。

一般我们使用HTTPS协议来clone Git仓库,这样每次pull都需要输入用户名密码,
很不方便,我们可以保存这些信息

git config --global credential.helper store

这样,只需要输入一次就行了。

但以上方法会把用户名密码以明文的方式保存在.gitcredentials文件中,很不安全,使用以下命令可以把用户名信息在内存中保存3600秒,这样,即可以保证安全性,也能避免经常输用户名密码

git config --global credential.helper "cache --timeout=3600"

缺点就是,每过3600秒或者主机重启后都要重新输入。

但是,如果你的主机是MAC PRO就没这个问题了,

git config --global credential.helper osxkeychain

这样就把敏感信息保存在钥匙串中了。windows也有类似的工具。但是,我们常用的linux貌似没有类型的工具。

另外一种方法就是使用SSH协议,利用密钥的方式来更好的兼顾安全和效率。

ssh-keygen -t rsa -C "name@dtstack.com"

然后克隆仓库时需要使用SSH协议就好了。

常用shell命令

Posted on 2016-11-07   |  

top

查看某进程的资源消耗情况
top -pid 60653

ps

查看所有python进程
ps aux | grep python

netstat

查看当前主机所有打开的端口
netstat -anL

查看某端口连接情况
netstat -an | grep -w 9092

lsof

查看某端口打开的文件情况
lsof -i:80

查看当前主机所有打开文件
lsof -ni | grep LISTEN

查看所有python进程
lsof -nP -iTCP -sTCP:LISTEN | grep python

查看指定端口
lsof -nP -iTCP:8877 -sTCP:LISTEN

输出占用该端口的 PID
lsof -nP -iTCP:8877 |grep LISTEN|awk ‘{print $2;}’

traceroute

查看数据到达目标主机的路由情况
traceroute www.baidu.com

ssh

ssh登录
ssh root@114.55.10.42

获取ssh key
pbcopy \< /.ssh/idrsa.pub

scp

从本地复制到远程
scp /home/space/music/1.mp3 root@www.cumt.edu.cn:/home/root/others/music

从远程复制到本地
scp root@www.cumt.edu.cn:/home/root/others/music /home/space/music/1.mp3

LD_DEBUG(linux)

查看nginx命令lib搜索路径
LD_DEBUG=libs nginx

ulimit

查看系统限制的最大文件描述符数
sysctl -a | grep maxfiles

查看当前限制的最大文件描述符数
ulimit -n

设置当前限制的最大文件描述符数
ulimit -n 4863

COP VS POP

Posted on 2016-11-05   |  

软件架构关注对系统的分割和如何让分隔后的各部分交互,至于如何分割和如何交互,取决于对系统不同特性的关注程度的取舍。而不同的编程思想对架构的选型和建立影响很大。

编程思想

PO(Process Oriented)
面向过程:对业务的顺序的抽象,更关注流程的顺序

OO(Object Oriented)
面向对象:对业务的责任的抽象,更关注各个部分所承担的责任,也就是责任的划分。而架构关注系统的分割,两者都是关注与如何“化整为零”,所以设计架构时很容易就会采用OO的编程思想,即使语言设计之初时并没有考虑面向对象的JS也利用自己的特性实现了一种“非主流”的面向对象方式。

AO(Aspect Oriented)
面向切面:对业务的扩展性的抽象,更关注如何扩展、替换业务属性

SO (Service Oriented)
严格来说,SO并不属于编程思想,它针对的粒度更大,更关注业务的模块化、稳定性和部署要求

编程思想影响着架构设计,同时,不同的实现有不同的侧重点和易用性,语言本身对编程思想的实现也对架构设计影响不小。

下面就说说COP(Class Oriented Programming)和 POP(Protocol Oriented Programming)作为OO面向对象的两种实现,各自的优缺点。

COP?

COP(Class Oriented Programming),说白了就是以Class作为业务各个角色的模型,不同的角色拥有不同属性,体现在Class上就是不同的属性和方法。

COP非常强调身份:你就是你,我就是我,你不是我们家族,具有强烈的“阶层意识”。于是在业务上,能够清晰地区分出角色的差异,也就是上面说的,专注于划分角色。

POP?

POP(Protocol Oriented Programming),说白了就是大家按照Protocol协议来做事,更强调角色的行为。

一个很形象的说明就是duck typing https://en.wikipedia.org/wiki/Duck_typing:

When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck

相对来说,COP就是严格的typing。

COP VS POP

面向对象有三大特性:封装、继承、多态。下面就来看看两者对这三大特性的实现情况。

前面说的很大一部分都可以看做是封装上的区别:COP封装的是类型、角色,POP封装的是行为。

COP中,子类拥有一切父类的属性和方法,无论子类是否需要,对编程人员来说,很容易就无意地覆盖了父类的属性和方法,苹果自身的框架可以通过文档来说明,如果是自己的或者第三方的代码,就得沿着继承链挨个找,这就带来了额外的风险和负担;另外,每个子类的实例在初始化时除了初始化自身的属性和方法,还会把继承链上所有父类的属性方法都初始化一份,即使同名属性也一样,这显然会增大无谓的内存消耗。

POP中,你只需要实现所声明协议的属性和方法,不需要的付出额外的代价。

两者都能符合里氏替换原则,POP能以弱耦合的方式完成,而COP就会导致强耦合。

关于多态,其实,POP更倾向于使用组合代替继承,所以,尽量少用多态。

关于组合和继承,其实苹果也意识到这个问题,所以为OC实现了category的特性,的确避免了一部分“类爆炸”的问题。

Swift是第一门原生支持POP的语言,苹果的Swift标准库负责人 Dave Abrahams,在WWDC2015上历数了COP的几大罪状,感兴趣的可以看看:https://www.youtube.com/watch?v=g2LwFZatfTI,其中有两点我觉得有点“栽赃”的嫌疑:

  • implicit sharing:共享变量
  • lost type relations:丢失类型关联

我并不觉得共享变量是COP独有的问题,这个和是不是COP或者POP无关,严格来说,POP中的protocol也是一种类型,只不过是一种更“弱”的Class;同样,类型关联丢失也只是语法糖的问题。

POP对架构的助力

计算机发展初期,各大操作系统和硬件厂商都按照Class的方式来生产,带来了很大的市场推广阻力,因为各个系统不能互相通信。最终,通过制定操作系统和网络中的各种协议protocol,使得各种异构系统能够以弱耦合的方式相互交互和通信,这才为互联网的诞生奠定了基础。

协议的最大作用就在于弱化耦合关系,更多关注行为而非类型,这样我们才能专注实现需求。

POP弱化了静态语言的严格的类型检查,为语言增加了更大的动态性,同时也有利于降低内存消耗,对于移动开发具有一定优势,更重要的是它弱化了各个子系统的耦合,对于关注分割和交互的架构设计在解耦上有不错的效果。

一些看过的书

Posted on 2016-10-29   |  

总结一些看过的书,粗略梳理一下自己的知识体系,当作MindMap好了,找找知识盲点。
书的排名没有先后,后续有时间把部分书的阅读笔记发上来。

操作系统

  1. 深入理解计算机系统:https://book.douban.com/subject/5333562/
  2. Linux/UNIX系统编程手册:https://book.douban.com/subject/25809330/
  3. 程序员的自我修养 : 链接、装载与库 :https://book.douban.com/subject/3652388/
  4. 汇编语言:https://book.douban.com/subject/25726019/
  5. Linux命令行与shell脚本编程大全:https://book.douban.com/subject/11589828/
  6. 深入解析Mac OS X & iOS操作系统:https://book.douban.com/subject/25870206/
  7. 鸟哥的Linux私房菜:https://book.douban.com/subject/4889838/

网络

  1. 图解HTTP:https://book.douban.com/subject/25863515/
  2. 图解TCP:https://book.douban.com/subject/24737674/
  3. TCP/IP详解 卷1:协议:https://book.douban.com/subject/1088054/
  4. iOS网络高级编程:https://book.douban.com/subject/25919485/

特定领域

iOS & macOS

  1. Advanced Mac OS X Programming:https://book.douban.com/subject/4242442/
  2. Cocoa Programming for OS X:https://book.douban.com/subject/26359201/
  3. Cocoa Design Patterns:https://book.douban.com/subject/3688896/
  4. iOS Animations by Tutorials :https://book.douban.com/subject/26369511/
  5. iOS Core Animation:https://book.douban.com/subject/25716177/
  6. Objective-C编程之道 :https://book.douban.com/subject/6920082/
  7. Objective-C高级编程 : iOS与OS X多线程和内存管理:https://book.douban.com/subject/24720270/
  8. iOS 7 Programming Pushing the Limits:https://book.douban.com/subject/25804280/
  9. Effective Objective-C 2.0 : 编写高质量iOS与OS X代码的52个有效方法
    :https://book.douban.com/subject/25829244/
  10. NSHipster : Obscure Topics in Cocoa & Objective C:https://book.douban.com/subject/25788850/
  11. CFHipsterRef :https://book.douban.com/subject/26365320/
  12. The NSHipster Fake Book:https://book.douban.com/subject/26372793/

web 前端

  1. JAVASCRIPT语言精髓与编程实践:https://book.douban.com/subject/3012828/
  2. JavaScript高级程序设计:https://book.douban.com/subject/10546125/
  3. Maintainable JavaScript : Writing Readable Code:https://book.douban.com/subject/10547007/
  4. Learning JavaScript Design Patterns:https://book.douban.com/subject/10750116/
  5. Async JavaScript:https://book.douban.com/subject/10745151/
  6. High Performance JavaScript:https://book.douban.com/subject/4183808/
  7. JavaScript DOM高级程序设计:https://book.douban.com/subject/3082278/
  8. 精通CSS与HTML设计模式:https://book.douban.com/subject/3158926/
  9. 编写高质量代码 : Web前端开发修炼之道:https://book.douban.com/subject/4881987/
  10. 大巧不工 : Web前端设计修炼之道:https://book.douban.com/subject/4914146/
  11. CSS Mastery:https://book.douban.com/subject/1583135/

web 后端

  1. Python编程实战:https://book.douban.com/subject/25955274/
  2. 编写高质量代码:改善Python程序的91个建议:https://book.douban.com/subject/25910544/
  3. Python核心编程:https://book.douban.com/subject/3112503/
  4. Django Design Patterns and Best Practices:https://book.douban.com/subject/26410236/
  5. Two Scoops of Django:https://book.douban.com/subject/26578004/
  6. Node Web开发:https://book.douban.com/subject/10586326/

数据库

  1. 高性能MySQL:https://book.douban.com/subject/23008813/(还没来得及细看,不过是公司CTO翻译,大神级的DBA人手一本,应该值得一看)

  2. SQLite权威指南:https://book.douban.com/subject/7061934/

安全

  1. iOS应用逆向工程:https://book.douban.com/subject/25826902/
  2. 白帽子讲Web安全:https://book.douban.com/subject/10546925/

架构

  1. 大型网站技术架构 : 核心原理与案例分析:https://book.douban.com/subject/25723064/
  2. 淘宝技术这十年:https://book.douban.com/subject/24335672/
  3. 构建高性能Web站点:https://book.douban.com/subject/10812787/
  4. 软件架构设计:https://book.douban.com/subject/10797944/
  5. 软件架构的艺术:https://book.douban.com/subject/3669563/
  6. 大话设计模式:https://book.douban.com/subject/2334288/
  7. 设计模式:https://book.douban.com/subject/1099305/
  8. 反模式 : 危机中软件架构和项目的重构:https://book.douban.com/subject/2364818/
  9. Software Architecture Patterns :https://book.douban.com/subject/26797547/

软件工程

  1. 构建之法 : 现代软件工程:https://book.douban.com/subject/25965995/
  2. 编写可读代码的艺术:https://book.douban.com/subject/10797189/
  3. 代码大全:https://book.douban.com/subject/1477390/
  4. 代码整洁之道:https://book.douban.com/subject/4199741/
  5. 解析极限编程 : 拥抱变化:https://book.douban.com/subject/6828074/
  6. 面向对象的系统分析:https://book.douban.com/subject/1975337/
  7. 修改代码的艺术:https://book.douban.com/subject/2248759/
  8. 重构 : 改善既有代码的设计:https://book.douban.com/subject/4262627/
  9. 人月神话:https://book.douban.com/subject/1102259/
  10. 人件:https://book.douban.com/subject/1108725/

IT历史

  1. 浪潮之巅:https://book.douban.com/subject/6709783/
  2. 黑客与画家 :https://book.douban.com/subject/6021440/
  3. 文明之光系列:https://book.douban.com/subject/25902942/

认知心理学 & 个人管理

  1. 少有人走的路:https://book.douban.com/subject/1775691/
  2. 思考,快与慢:https://book.douban.com/subject/10785583/
  3. 聪明人是如何思考的:https://book.douban.com/subject/26362196/
  4. 麦肯锡工作法:https://book.douban.com/subject/25873066/
  5. 影响力:https://book.douban.com/subject/1786387/
  6. 暗时间:https://book.douban.com/subject/6709809/
  7. 如何阅读一本书:https://book.douban.com/subject/1013208/
  8. 程序员的职业素养:https://book.douban.com/subject/11614538/
  9. 你的灯亮着吗? : 发现问题的真正所在https://book.douban.com/subject/1135754/
  10. 程序员的思维修炼 : 开发认知潜能的九堂课:https://book.douban.com/subject/5372651/
  11. 自控力:https://book.douban.com/subject/10786473/
  12. 咨询的奥秘 : 寻求和提出建议的智慧:https://book.douban.com/subject/25785829/
  13. 高效程序员的45个习惯 : 敏捷开发修炼之道:https://book.douban.com/subject/4164024/
  14. 高效能人士的七个习惯:https://book.douban.com/subject/1048007/
  15. 卓有成效的程序员:https://book.douban.com/subject/3558788/
  16. 拆掉思维里的墙 : 原来我还可以这样活:https://book.douban.com/subject/4953695/
  17. 活法:https://book.douban.com/subject/4112632/
  18. 禅与摩托车维修艺术:https://book.douban.com/subject/6811366/

全方位的关怀

  1. 软技能:https://book.douban.com/subject/26835090/

Arsos — a lib search engine for coder

Posted on 2016-10-22   |  

Arsos,本来是二战时期同盟国执行的一项搜寻德国原子核实验地点行动的名称,由于这项行动,同盟国才真正了解了德国的原子核计划的真实进展,并成功破坏了其重水的来源。

同时,Arsos也是一个为工程师量身定做的搜索库和组件的Mac APP。

由来

Arsos来源于某天看到公司的前端工程师在查找一个js库,步骤非常繁琐:先打开浏览器,输入网址,然后输入angular,得到一长串结果,然后还要根据版本号筛选,如果想要找到angular下的cookie组件,还得Command + F,接下来输入cookie …脑细胞已阵亡。

作为一个熟练使用Alfred、Popclip、BTT的效率小能手(check 我自制的 Alfred workflow 、 Popclip extension ),简直不能忍,于是就萌生了自己做一个工具来简化这个流程。

整体架构


服务端由两个Server和一个Database组成(缓存没太大必要,文件存储暂时没太大需求,暂时Droplr够用):Data Server负责收集数据并按照Service Server中定义的model的格式把数据保存到DB中,Service Server目前主要扮演API网关的角色,为Mac APP提供API接口,另外还会兼职Web Site中的展示和数据源后台管理。

客户端由Mac APP和Web Site组成:Mac APP主要对外提供搜索和下载服务,Web Site对外提供产品介绍的同时对内提供数据源管理服务,方便管理员编辑数据。

功能介绍

作为一个Alfred重度患者,为了向Alfred致敬(是的,这不叫抄袭),UI设计和交互方式基本都是参照它来设计的,所以对用过Alfred的朋友来说是非常友好的,如果没用过Alfred也没关系,下面简单介绍下现有的功能。

快速唤起

下载安装后(下载地址),运行Arsos,然后切换到其它应用,比如Atom或者sublime,按下快捷组合键:

Shift + 空格(自定义)

即可唤起Arsos进行搜索。

搜索

搜索功能使用非常简单,输入的关键词以空格分割,回车后就会返回所有模糊匹配成功的结果。

复制

在搜索结果列表中,使用上下箭头选中结果,回车即可复制选中结果到剪贴板中

另外,如果回车的同时按住option键,即可复制带有标签的结果

Alfred workflow

同时还给Alfred的重度患者提供一个workflow,作为Arsos Mac APP的精简版,下载地址

后续计划

和几个朋友聊了下,收集了一些需求,加上自己也有些想法,于是功能列表变得越来越长

我目前对这个工具的定位是一个纯粹的搜索工具,作为所有库和组件的搜索入口,所以不仅仅限于前端的内容,后续还会添加OC、Swift、Python、Ruby、Go等内容。
最后,有朋友对这个工具有什么建议可以留言。

12345
Ezio

Ezio

44 posts
© 2017 Ezio
Powered by Hexo
Theme - NexT.Mist