Kenny 肉桂的主页

记录自己的进步


  • 首页

  • 归档

  • 标签

  • 搜索
close

Xocde插件失效解决[转载]

发表于 2015-06-05   |   分类于 开发环境相关   |  

context

XCode的插件大大丰富了XCode的功能,而且有了Alcatraz,插件的管理也非常容易,像我这种Vim党完全离不开XVim。但是有个非常恼人的问题:一旦升级XCode,插件就失效!
之前XCode升级到6.2的时候遇到过插件失效的问题,Google之后把一段很长命令复制到Terminal后运行一下即可,当时一看解决了, 顿时觉得满足感爆棚,自己可以拯救地球了~就没有再深入,结果升级到6.3时又遇到了。“同样的招式对圣斗士是不能使用第二次的!”,同样的坑对有节操的 程序员是不能掉进去第二次的!因此这一次一定要搞清楚为什么会这样,以后再次遇到了如何解决。

阅读全文 »

Tip9 以类族模式隐藏实现细节

发表于 2015-06-04   |   分类于 iOS Tips   |  

context

类族是一种很有用的模式,可以隐藏抽象基类背后的细节.OC的系统框架中,普遍使用这个模式.

一个例子: UIButton

1
UIButton * button = [UIButton buttonWithType];

该方法返回的对象类型取决于传入的 type ,不同的type决定了这个 button 将来的一些属性的不同(或者说可供设置的属性的不同)

要实现类似的功能,如果不用类族,那么还可能是一个类中的枚举.比如:

1
2
3
4
5
6
7
8
- (void) drawRect:(CGRect)rect{
if(_type == typeA){
//绘制一个 typeA 类型的 Button
}else if (_type == typeB){
//绘制一个 typeB 类型的 Button
}

}

这是一个简单的类型,这么看来没有问题,但是如果类型太多,这样就显得非常笨拙了.

稍微聪明一点的程序员,会把这样的代码重构.不同的实现放到子类中,父类中存放公共代码.但是这样也有一个缺点,就是开发者需要知道所有的子类.

现在类族的好处就显而易见了.

一个自定义的类族

假设我们有一个 Person 类,Person 分为不同的职业.有老师,学生,医生.那么类族的实现应该是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef NS_ENUM(NSUInteger,PersonType) {
PersonTypeDoctor,
PersonTypeTeacher,
PersonTypeStudent
};

+ (Person *) personWithType:(PersonType)type{
switch(type){
case PersonTypeDoctor:
return [[PersonDoctor alloc]init];
break;
case PersonTypeTeacher:
return [[PersonTypeTeacher alloc]init];
break;
case PersonTypeStudent:
return [[PersonTypeStudent alloc]init];
break;

}

}

Currying

发表于 2015-06-03   |   分类于 Swift进阶   |  

context

最近开始读喵神的书,书是好书,就是非常概略,不利于 Swift 基础薄弱的童鞋,所以,借着自己阅读的理解和查阅的资料,把每个知识点扩充一下.

Currying

Currying就是把一个多参数的方法,拆解为只有第一个参数的方法,这个方法的返回值不是一个具体的值,而是一个新的方法,这个方法的参数是原先的方法刨去第一个参数后的“剩下的方法的片段”,可以理解为,把一个多参数方法只作为某一种模板

基本写法

基本结构:

func function name (parameters)(parameters)->return type{
statements
}

一个 Currying

1
2
3
func add(originValue: Int)(inputValue: Int) -> Int {
return originValue + inputVlue
}

这个写法就是 currying 函数的基本写法,originValue 是他的固定的基数(或者说基础参数). inputValue是以后调用的不同的输入值.基础参数构建了一个类似模板的东西,而输入值构建了我们想要的最终结果.

使用:

1
2
let addWith10 = add(10)
let addWith100 = add(100)

以上,分别构建了一个以 10 和100 为基数的方法.它们都是新的方法,但是是我们最开始方法的一部分,如果要使用:

1
2
let result1 = addWith10(inputValue: 1)
let result2 = addWith100(inputValue: 1)

result1的结果是 11
result2的结果是 101

以上就是 Currying 的一个小剖析,下面我们从一般函数入手,看看Currying到底是怎么演化的.

从函数开始

1
2
3
4
func sum(a: Int,b: Int) -> Int {
return a + b
}
sum(1, 2) //输出3

这是一个非常简单的函数,如果用 Currying 的写法,会变成:

1
2
3
4
5
func sum(a: Int)(b: Int) -> Int {
return a + b
}
var sumByFirst = sum(1)
sumByFirst(b: 4) //输出5

只需要传入第一个参数,返回的sumByFirst是一个函数,它包含剩余的其他参数,以及刚刚传入进去的那个1,接着以它自己作为方法传入第二个参数b就行了。
如果是三个参数就像这样:

1
2
3
4
5
6
func sum(a: Int)(b: Int)(c: Int) -> Int {
return a + b + c
}
var sumByFirst = sum(1)
var sumBySecond = sumByFirst(b: 4)
sumBySecond(c: 10) //输出15

除了第一个参数以外,其他的参数都要显式地写上参数标签,并且要按参数排列的顺序调用。
一个括号中放两个参数也可以:

1
2
3
4
5
func sum(a: Int)(b: Int, c: Int) -> Int {
return a + b + c
}
var sumByFirst = sum(1)
sumByFirst(b: 4,c: 10) //输出15

在某些情况下,你可能会用某个相同的参数重复调用某个方法,那么利用柯里化会使代码更易于维护:

1
2
3
4
5
6
7
func sum(a: Int)(b: Int) -> Int {
return a + b
}
var sumWithFive = sum(5)
sumWithFive(b: 5)
sumWithFive(b: 10)
sumWithFive(b: 15)

因为 Swift 的 Selector 只能通过字符串生成,这会面临一个很严重的问题,就是难以重构,并且无法在编译期间进行检查,这是非常危险的行为.但是利用方法的 Currying ,我们可以解决这个问题.

参考网址:

http://blog.csdn.net/zhangao0086/article/details/38851759

http://www.tuicool.com/articles/bMBjUfn

新版多说的配置

发表于 2015-06-03   |   分类于 主页维护记录   |  

context

最近给博客更换了一款主题,但是发现多说评论失效了,用一期的配置方法进行配置,还报错.现在重新整理

前提

已经注册多说开发者帐号,并且创建了应用.

步骤

  1. 取消HEXO博客根目录中的 _config.yml 中 disqus_shortname: ,暂时不用这个功能,直接永久开启多说评论。(如果没有此参数,可以忽略)

  2. 打开 themes\light\layout_partial\comment.ejs (如果没有,请创建)将你的通用代码粘贴进来,并修改三处地方:

data-thread-key="<%= page.path %>
data-title="<%= page.title %>"
data-url="<%= page.permalink %>"

最终我的完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- 多说评论框 start -->
<div class="ds-thread" data-thread-key="<%= page.path %>" data-title="<%= page.title %>" data-url="<%= page.permalink %>"></div>
<!-- 多说评论框 end -->
<!-- 多说公共JS代码 start (一个网页只需插入一次) -->
<script type="text/javascript">
var duoshuoQuery = {short_name:"guiqingblog"};
(function() {
var ds = document.createElement('script');
ds.type = 'text/javascript';ds.async = true;
ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//static.duoshuo.com/embed.js';
ds.charset = 'UTF-8';
(document.getElementsByTagName('head')[0]
|| document.getElementsByTagName('body')[0]).appendChild(ds);
})();
</script>
<!-- 多说公共JS代码 end -->
  1. 打开themes\light\layout_partial\article.ejs
    在最后一行加上如下代码
1
2
3
<% if(!index){ %>
<%- partial('comment') %>
<% } %>

后记

在早期版本,第二步骤中的三个文章参数不是必须的,但是新版中,如果不配置,会报错.样式也不能正常显示 .

定位程序崩溃点的方法探究

发表于 2015-06-03   |   分类于 iOS Tips   |  

context

昨天遇到问题,当我的 NavitgationController back 的时候,程序崩溃,诡异的地方是: 控制台完全没有任何打印,崩溃的断点直接回到了 main 函数中.

几个尝试

想到之前曾经读过一篇出现在这样情景崩溃的文章:有对象依赖被 pop 的控制器,结果导致了崩溃,但是经过仔细排查,发现并没有这样的情况.

查找资料

网上对崩溃问题的定位常规方法总结起来有:

1.添加通用断点

  1. 选择 BreakPoint Navigator,点击右下角的 ‘+’ ,然后在弹窗中选择 ‘Add Exception BreakPoint’

  1. 右键断点,选择 ‘Edit BreakPoint’,检查设置如下

然后运行程序,程序就能定位到出现崩溃的代码.

但是很遗憾的是,这种方式只能解决大部分的问题(比如不识别的selector 等),有很多类型的崩溃它是不能定位的

比如出现 EXEC_BAD_ACCESS这种错误,以上的方法是不能定位的.

2.重写object的respondsToSelector方法

1.重写object的respondsToSelector方法,现实出现EXEC_BAD_ACCESS前访问的最后一个object.因为有时候程序崩溃根本不知错误发生在什么地方。

在可能出现问题的 .m 或者.mm 文件中加入以下代码

1
2
3
4
5
6
#ifdef _FOR_DEBUG_  
-(BOOL) respondsToSelector:(SEL)aSelector {
printf("SELECTOR: %s\n", [NSStringFromSelector(aSelector) UTF8String]);
return [super respondsToSelector:aSelector];
}
#endif
  1. 在 other c flags中加入-D _FOR_DEBUG_(记住请只在Debug Configuration下加入此标记),这样当你程序崩溃时,Xcode的console上就会准确地记录了最后运行的object的方法。


很不幸,这样还是没有定位我出现问题的代码.

最终方案

首先说一下 EXC_BAD_ACCESS 这个错误,可以这么说,90%的错误来源在于对一个已经释放的对象进行release操作.那么我们应该启用 僵尸对象.方法如下:

Product->Scheme->Edit Scheme->Arguments 的 Environment Variables 中,增加标计位NSZombieEnabled设为YES)objc


这样,就能看到崩溃的具体原因了.但是如果想知道代码,这个原文说需要借助 Xcode 控制台的 GDB,很不幸的是,高版本的 Xcode 中,已经没有切换到 GDB 的功能了.网上也有帖子介绍 GDB 对应 lldb 的指令是什么,很不幸,都不能正常工作,所以这里不在罗列.

后来,我想到是否可以借助终端来完成任务?

那么问题来了,终端怎么知道这个内存地址是属于谁的?
后来想到,可以通过活动监视器,拿到我们程序进程的 pid

我的是 1175

然后参考刚刚原文中的指令, sudo malloc_history 1175 0x7a692620
后面一个参数是崩溃的地址.

此时终端提示,没有打印 MallocStackLogging .

其实这里是需要在 Xocde 中配置的.按照刚刚配置 NSZombieEnabled的位置和方式,添加一个参数:

MallocStackLoggingNoCompact 值设置为 YES

然后继续重新编译运行,查看 pid ,查看崩溃的内存地址.

见到终端打印出了调用顺序,一般来说,是最后一个你自定义的方法导致的崩溃.

然后就是解决 bug 了,祝好运 ~

参考网址:
http://blog.csdn.net/totogo2010/article/details/8949440
http://mobile.51cto.com/iphone-279455.htm

2015-06-01滚动监听 触摸点获取 Tranform RecealApp

发表于 2015-06-01   |   分类于 iOS Tips   |  

概要

  • UITableView 滚动行为的监听,触摸点的获取
  • CGAffineTransformMakeTranslation和CGAffineTransformTranslate
  • reveal app 的项目集成
  • inputAccessoryView 遇到的几个问题
阅读全文 »
1…8910…13
桂庆

桂庆

Kenny 肉桂的主页 记录自己的进步

75 日志
17 分类
23 标签
RSS
微博
© 2013 - 2017 桂庆
由 Hexo 强力驱动
主题 - NexT.Mist