如何让pod update快到飞起?

想成为一个好的程序员,翻墙是必备技能,查个资料、搜个问题啥的,百度实在是渣(不是黑百度),可以说编程,不翻墙没法活。

至于如何翻墙,方法很多,有自己买VPN的,有公司自己配的,也有走代理的。个人最喜欢shadowsocks,可惜现在已经找不到正规的下载地址了,但只要用心找找,总还是有好人分享的。如果您用的是mac,实在下载不到,可以在评论中把邮箱留下,我发给你。

有了翻墙软件,固然神清气爽,但pod update等终端命令发起的网络请求却不能走代理,几乎停滞的下载速度让人窒息,有时候项目稍微大一点,一个pod update命令能跑一上午,这还编什么程序,如果pod update能快到飞起,那是怎样令人神往的感觉?

办法总是有的,这就是这个时代最迷人的地方。

前提

再说一遍前提,必须得先能翻墙,并且翻墙后的网速得比较快。

准备起飞了

安装proxychains

  • 先安装proxychains

打开Mac的terminal,并输入一下命令:

1
brew install proxychains-ng

查看更多

分享到 评论

再见土木,hello world!


从07年至今,算下来,我学土木也近十年。十年的浸润,不敢说造诣很深,但至少基础坚实,如果继续努力,相信结果不坏。如今突然离开,跨越至IT,十年的成长轮为羁绊,又回到起点的感觉,惶惶不安。

其实我并不是一个爱冒险的人,而且结构工程师、设计院,也是不少人梦寐以求的,在社会上颇受尊重,但自己身在其中,总有太多的烦躁相伴,痛苦相随。痛苦是很有价值的感受,因为无论你怎么偏离你命中注定的航线,它都会一点一点地将你校正到正确的方向,即使你不勇敢,它也会让你变得义无反顾。

当初进省院一所时,我曾经说自己很适合这个行业,我相信不少人也一直坚定的这么认为,连我自己也不例外,因为我比较宅、爱钻研、情商低、不善言辞。但理所当然的事却没有发生,机械式的画图、挥之不去的强条、冷酷无情的修改,让我精疲力尽、无言以对。仔细回想,除了偶有的绘图技巧提高带来的成就感外,竟难找到一丝专业的乐趣。即使建筑落成,行走其中,内心也并不以是自己设计的而汹涌澎湃。除了令人垂涎的稳定,自己实在找不到继续前行的理由。这才发现,原来自己本就不属于这里!

查看更多

分享到 评论

闭包捕捉(closure capture)浅析

根据Swift官方文档,闭包(closure)会自动捕捉其所在上下文中的外部变量,即使是定义这些变量的上下文已经消失。寥寥数字,其实已经将闭包捕捉说的足够清晰明了,只是其中隐含的诸如捕捉的具体含义、捕捉的时机、被捕捉变量的特性和捕捉列表的意义等细节,如不详加研究,使用闭包还是会错误百出,难以挥洒自如。

本文中所有代码均在playground中运行,若欲在实际项目中测试,需做部分修改,但基本逻辑和结论不变

————– 本文部分结论和例子根据部分读者意见做了修正更新,感谢他们 ————–

捕捉的含义

闭包捕捉等同于copy

闭包捕捉某个变量就意味着copy一份这个变量,值类型的变量直接复制值,引用类型的变量复制引用。复制后的变量名同被捕捉的变量,复制后的变量仍为变量,常量仍为常量。

看例子

值类型捕捉

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import UIKit
struct Pet {
var name: String
init(name: String) {
self.name = name
}

func printNameClosure() -> () -> Void {
return {
print(self.name)
}
}
}

var pet: Pet = Pet(name: "旺旺")
let cl = pet.printNameClosure() //1
pet.name = "强强"
cl() //2

结构体Pet的实例方法printNameClosure()返回一个捕捉了self实例本身的闭包,Pet为值类型,因此//1行代码执行完成后,闭包cl复制了一份存储在变量pet中名为旺旺的Pet实例,那么当存储在变量pet的Pet实例改名为强强时,闭包cl所捕捉的Pet实例不变,名字仍为旺旺,因此输出结果为:

1
旺旺

查看更多

分享到 评论

iOS并发(concurrency)概念浅析

在进行iOS开发过程中,我们常会遇到网络请求、复杂计算、数据存取等比较耗时的操作,如果处理不合理,将对APP的流畅度产生较大影响。除了优化APP架构,并发(concurrency)是一个常用且较好的解决方法,但并发涉及串行、并发、并行、同步、异步、多线程、GCD、NSOperation和NSOperationQueue等诸多容易混淆的概念,为求概念清晰明了,还请茗茶静坐,听我徐徐道来。

线程和任务

线程(thread) 和任务(task)是其他并发概念的基础,因此也是首要需理清的概念,以下是其要点,详细可参考Thread (computing)Task (computing))。

任务(task)

a)任务(task)是从程序中划分出来,可以独立执行的代码片段;
b)任务间可以添加依赖关系,如B任务依赖A任务,taskB.addDependency(taskA),这意味着B任务的执行以A任务完成为前提。

需要注意的是一个任务是否可以添加依赖,完全取决于任务封装类和其相关管理类的具体实现,GCD不支持任务依赖,NSOperationQueue就支持任务依赖。

下面的代码是对一个任务的简单封装,并支持任务间的依赖。

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
//Task是一个任务的简单封装类
class Task {
let taskBlock: () -> ()
var dependencies = [Task]()

init(block: () -> ()) {
taskBlock = block
}

func addDependency(task: Task) {
dependencies.append(task)
}
}

//初始化两个自定义任务
var taskA = Task(){
//自定义任务A,自定义需要执行的代码
...
}
var taskB = Task(){
//自定义任务B,自定义需要执行的代码
...
}
//添加依赖关系
taskB.addDependency(taskA)

查看更多

分享到 评论

排序算法之Swift实践

当我们站在历史的今天,往过去回顾,总会发现一些在当下习以为常的观念,惊讶在过去竟然没人意识到,比如生产力决定生产关系,比如自由平等,这就是所谓的进步。我生于上世纪九十年代初,年纪尚轻,这些观念的巨大变革,我大多从书上学来的,如果要找一些真正有切身体会的,我想就是当下有点烂大街的用户体验。与过去单纯讲究功能性的时代相比,用户体验绝对是完全颠覆的,它完全变换了产品的核心,给人一种醍醐灌顶的顿悟感,想及此,还是要感谢乔布斯和他的苹果。

算法与用户体验看似没有关系,其实算法是上佳用户体验的基础,因为没有高效的算法,机子会卡。我至今仍是编程小白,为加深对算法的理解,本文尝试用Swift实现大部分常用的排序算法。

经典排序算法

插入排序

1
2
3
4
5
6
7
8
9
10
11
12
13
//不改变输入数组的状态,返回排序完成的降序数组
func insertionSort(var arr:[Int]) -> [Int] {
for var i = 1; i < arr.count; i++ {
let key = arr[i]
var j = i - 1
while j >= 0 && arr[j] > key {
arr[j+1] = arr[j]
j--
}
arr[j+1] = key
}
return arr
}

插入排序为原址排序,总耗时与输入的分布有关,当输入为倒序时,为最坏输入分布,排序时间为Θ(n^2),当输入为正序时,为最佳输入分布,排序时间为Θ(n),其中n是输入规模。

冒泡排序

1
2
3
4
5
6
7
8
9
10
11
12
func bubleSort(var arr: [Int]) -> [Int] {
for var i = arr.count - 1; i > 0; i-- {
for var j = 0; j < i; j++ {
if arr[j] > arr[j + 1] {
let temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
return arr
}

冒泡排序为原址排序,总耗时与输入的分布无关,耗时O(n^2)

查看更多

分享到 评论

翻转二叉树之Swift实践

Google: 90% of our engineers use the software you wrote(HomeBrew), but you can’t invert a binary tree on a whiteboard so fuck off.

HomeBrew作者,天才程序员Max Howell兴致盎然地去Google面试(估计是刚好路过),结果却因不会在白板上翻转二叉树被Google粗鲁地拒绝了,舆论甚是哗然,其中缘由知乎上也讨论的热火朝天。谁料,始作俑者翻转二叉树这道题目,一时也热地不要不要的。作为程序员小白的我,从未翻过二叉树。最近闲来无事,闲暇之余,想及至此,就顺手用Swift翻转了二叉树。

如果您对二叉树的概念不甚清晰,可以先到维基百科上(不推荐百度百科,因为要养成良好的搜索习惯)再温习温习二叉树相关知识。

二叉树定义

先定义一个二叉树类Tree,主要定义树的三个必要属性,关键值key,左子树leftTree和右子树rightTree

1
2
3
4
5
6
7
8
9
10
11
//define Tree class
class Tree {
var key: Int
var leftTree: Tree?
var rightTree: Tree?

init(key: Int) {
self.key = key
}

}

递归翻转

用递归的方式翻转二叉树,主要分为两步:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//invert binary tree using recursive
func invertBinaryTreeWithRecursive(root: Tree) {
//1
let tempT = root.leftTree
root.leftTree = root.rightTree
root.rightTree = tempT

//2
if let leftT = root.leftTree {
invertBinaryTreeWithRecursive(leftT)
}
if let rightT = root.rightTree {
invertBinaryTreeWithRecursive(rightT)
}
}

第1步:翻转本树的左子树和右子树,需要借助一个零时变量tempT
第2步:判断左右树是否存在,如存在,则递归调用进行翻转。

递归翻转二叉树每个节点只访问1次,在每个节点上的耗时是常数,因此总耗时Θ(n),n是树的节点树。

查看更多

分享到 评论

typealias理解小误区

alias在英语中是别名之意,那typealias,顾名思义,是指类型的别名。Swift的官方文档中对typealias关键词的演示,也是以赋值的形式,给一个现有类型取一个恰当的别名,便于在上下文中使用:

1
2
3
4
5
6
7
8
9
10
11
protocol Container {
typealias ItemType
//some other things

}

struct IntStack: Container {
typealias ItemType = Int
//some other things

}

如果ItemType的类型不是已有类型,还需另外定义:

1
2
3
4
5
6
struct SomeType { }
struct SomeStack: Container {
typealias ItemType = SomeType
//some other things

}

typealias的两种用法

根据上述typealias关键词的演示可知,typealias的使用一般分为两步:

  1. 独立定义一个目标类型SomeType
  2. 将目标类型SomeType=的形式赋值给typealias别名。

typealias的两步使用法,结构清晰,意义明了,但也略显啰嗦。如果目标类型SomeType比较轻,是一些简单的类型,则两步可以合为一步,直接在实现Container protocol的类型中,定义一个与别名同名的类型即可:

查看更多

分享到 评论

不可不信缘-2015年度总结

回顾2015,我一直试图告别土木工程,寻找属于我的江湖。

谈及我与土木的相遇,完全是因为高考成绩考砸了的缘故。但相遇即是一种缘分,因此我把这份缘分延续到了现在,可是这是一段不会有结果的旅程。回忆这八年,土木就像是我注定不爱的姑娘,一开始相识并不觉得什么,偶尔牵牵手还有点小愉快,可后来真的在一起了,才发觉一切都那么不自在,每个深夜满心的离开。其实我也不是现在才察觉,只是以前年轻,没有到迫在眉睫非彼即此的境地。现在工作都快整两年了,我也已经25了,我想这是最后的机会,去寻找自己的城。因此,这一年我做了两个大尝试。

一个是创业,一个是学编程。

2014年7月,戴瑞珠宝创业项目正式立项,前前后后累计7个人的小团队,当时干的也是风风火火轰轰烈烈。但后来起起伏伏,坎坷不断,2015年8月7日,我正式退出团队。一年有余的兼职创业,虽然没有期许的结果,却让我深刻的体会到,互联网才是年轻人龙争虎斗的天地,那里有梦想,有远方,有希望。而我所处的建筑行业,已然渐近荒原,很难说得上值得拼搏。我虽非大才,但也不甘沉沦,离开土木工程,跨入心向往之的互联网行业势在必行。只是在互联网行业,我去能干什么呢?八年的土木工程生涯,漫长的浸润,已经快把我体制化了。除了画CAD,似乎我什么都不会。隔行如隔山,此时我方体会至深,我该怎么办呢?

2015年6月10日,我打开刚刚入手不久的Macbook,在知乎上搜索,“如何入门iOS编程?”,按照排名最高的答案,下载了Ray Wenderlich经典入门教程iOS Apprentice 1- bull’s eye,再根据教程里的介绍,下载了Xcode,然后新建了我人生的第一个iOS 项目,从此开始了我的iOS探索旅程。回想起来,人生如梦,一切都是缘分。那时我买MacBook,只是因为七岁有余的Lenovo ideapad年迈力衰,行动迟缓,想换个MacBook,换个电脑,换个系统,换个体验,哪知它在我最迷茫的时候映入眼帘,哪知它在我最彷徨的时候,适时出现,指明路的方向,不可不信缘。接下来自然是我羞于提起却十分拿手的刻苦努力,四个月后,我基本入门。整个编程之路,风光旖旎,我很enjoy。也才发现,学习一个完全摸不着头脑的新事物,是多么的惊心动魄,趣味盎然。

《lost》电视剧有一句台词,我印象十分深刻,“Everybody is born with a destiny”。每个人生来都注定了自己的宿命,难道不是吗?总有一件事你最擅长,最热爱,最能让你疯狂。我想编程和做产品,就是我的宿命。在你最在意的事情上,倾注100%的努力。

在这次转变中,没能够尽力为公司付出,拿了钱,却不好好尽责,甚是惭愧,所以对2015年的省院一所,我真诚的说一句,“抱歉”。也希望,2016年,我能早日离开。

分享到 评论