使用CocoaPods时开启inhibit_warnings参数的小问题

inhibit_warnings参数能够有效的抑制CocoaPods引入的第三方代码库产生的warning,但是有时候会产生意想不到的错误,例如我今天引入ReactiveCocoa的时候就产生了下面的错误:

CompileDTraceScript ReactiveCocoa/ReactiveCocoaFramework/ReactiveCocoa/RACSignalProvider.d
    cd /Users/Tony/Code/TestApp/Pods
    setenv PATH "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/Users/Tony/.rvm/gems/ruby-1.9.3-p194/bin:/Users/Tony/.rvm/gems/ruby-1.9.3-p194@global/bin:/Users/Tony/.rvm/rubies/ruby-1.9.3-p194/bin:/Users/Tony/.rvm/bin:/Library/Frameworks/Python.framework/Versions/2.7/bin:/usr/local/heroku/bin:/usr/local/git/bin:/usr/local/share/npm/bin:/Applications/MAMP/Library/bin:/Users/Tony/Applications/play:/Users/Tony/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/Applications/Server.app/Contents/ServerRoot/usr/bin:/Applications/Server.app/Contents/ServerRoot/usr/sbin:/usr/local/git/bin:/usr/local/sbin:/Users/Tony/.rvm/bin:/Users/Tony/.ec2/bin"
    /usr/sbin/dtrace -h -DOS_OBJECT_USE_OBJC=0 -fobjc-arc -DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-checker -s ReactiveCocoa/ReactiveCocoaFramework/ReactiveCocoa/RACSignalProvider.d -o /Users/Tony/Library/Developer/Xcode/DerivedData/TestApp-bfkcwbnhjkdedddkxicxplyvlnxq/Build/Intermediates/Pods.build/Debug-iphonesimulator/Pods-ReactiveCocoa.build/DerivedSources/RACSignalProvider.h

......

Command /usr/sbin/dtrace failed with exit code 2


而我的pod文件中引入方式如下:


pod 'ReactiveCocoa', '~> 2.1', :inhibit_warnings => true

在这里,关闭了inhibit_warnings之后,就可以正常编译了。同理,inhibit_all_warnings也会产生类似的问题。

所以,要开启这个参数,需要谨慎,不要因为一些小小洁癖耽误自己大量的时间。

iBeacons

iBeacons是iOS7的新增的功能,可用于室内近场定位。iOS设备可以检测到附近的iBeacons兼容设备,在当前版本中甚至可以在应用后台运行的情况下获得回调。

iBeacons设备往往都是低功耗的,用Bluetooth Low Energy低功耗蓝牙实现,设计良好的iBeacons设备在一节CR2032纽扣电池支持下应能支持一年以上的使用时间。

iBeacons还有一个有用的特性是可以距离感应,当你的iOS设备检测到了一个iBeacons设备,那么app即可通过CoreLocation监测设备的距离,通过回调的形式通知距离变化。

i

常见应用场景

可以有不少有趣的应用场景,随便列举一些。

  • 商场购物时,靠近某些商品时,提示用户正在打折,或者查看商品的具体信息以及评价。靠近交费区域时,使用某一信用卡支付可以获得优惠。
  • 室内导航,例如机场登机口指示
  • 各种大会入场checkin,免去繁琐的签到流程
  • 各种展览场所,当用户靠近某些展品时,就可以获得相应的介绍信息

什么时候应该使用iBeacons

  • 同时需要检测多个区域
  • 被检测区域可以是一个移动的区域,例如汽车,列车。。
  • 检测区域范围有限的情况(一般不会大于100m)
  • 每个区域需要一些标识做区分的情况
  • 每个区域可以在室内,同一建筑物内,可以有重合
  • 用户愿意开启低功耗蓝牙来检测区域

如何把iOS设备变成一个iBeacon

所有支持低功耗蓝牙技术的iOS设备都可以变成一个iBeacon设备,被其它iOS设备检测到。例如iPhone 4s, iPod Touch5, iPad3及之后的设备,都支持低功耗蓝牙技术。

定义你的iBeacon

首先需要了解4个属性

  • proximity UUID , 是一个iBeacon或一组iBeacons设备的唯一标识,标明它的类型,你可以用osx下的 uuidgen
    命令生成
  • 一个内部identifier ,你在app中自定义的标识
  • 一个 major identifier, 可用于区分一组拥有相同proximity UUID的设备
  • 一个 minor identifier, 可用于区分一组拥有相同proximity UUID和相同major identifier的设备

创建并广播一个iBeacon区域

首先需要定义一个CLBeaconRegion来实现iBeacon,如下

NSUUID *myProximityUUID = [[NSUUID alloc]
    initWithUUIDString:@"566C5595-6EC7-4F08-909F-C954BDCA6CD3"];
NSNumber *branchNumber = @42;
NSNumber *tillNumber = @3;
CLBeaconRegion *region = [[CLBeaconRegion alloc]
    initWithProximityUUID:myProximityUUID
    major:[branchNumber unsignedShortValue]
    minor:[tillNumber unsignedShortValue]
    identifier:@"com.mycompany.store"];

然后把这些信息交由CBPeripheralManager进行广播


NSDictionary *peripheralData =
    [region peripheralDataWithMeasuredPower:nil];
CBPeripheralManager *myPeripheralManager =
    [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
[myPeripheralManager startAdvertising:peripheralData];

于是一个iOS设备就变成了一个iBeacon了

兼容的iBeacon设备

目前Apple并未公布iBeacons的具体技术细节,但是仍然有不少第三方通过蓝牙嗅探工具反向工程实现了iBeacons兼容设备。在国外已经有一些成品上市,例如

  • estimote
  • sticknfind
  • paypal,它甚至将iBeacons融入了它的支付技术

本人也利用TI公司的CC2541实现了一个简单的iBeacons兼容模块,为了未来可能的变化,做了预留的空中升级接口,现在某宝尝试性的对外出售,适用于有一定电子技术动手能力的爱好者测试。

参考链接

使用xctool自动打包,测试xcode项目

xctool是facebook开源的一个命令行工具,用来替代苹果的xcodebuild工具。

功能如下:

  • 像xcode一样跑测试用例
  • 结构化输出编译测试结果
  • 彩色且方便阅读的编译内容输出

示例截图:

xctool

如何安装xctool

最简单的办法是通过homebrew安装xctool

brew update
brew install xctool

搞定

如何使用xctool

打包


path/to/xctool.sh 
  -workspace YourWorkspace.xcworkspace 
  -scheme YourScheme 
  archive

build

path/to/xctool.sh 
  -workspace YourWorkspace.xcworkspace 
  -scheme YourScheme 
  build

测试

path/to/xctool.sh 
  -workspace YourWorkspace.xcworkspace 
  -scheme YourScheme 
  test

Arduino的蓝牙4.0串口透明传输模块

最近利用业余时间做了点小玩意

什么是BLUESHIELD?

BlueShield是一块支持蓝牙4.0串口透明传输模块,专为Arduino开发板设计,支持大多数Arduino开发板及衍生版本。

BLUESHIELD能干什么?

可以让你的iOS设备例如iPhone 5, iPhone 4S等等(兼容设备请参考上文)和Arduino通过蓝牙4.0通讯,将数据通过串口透明传输。

我能用它来和ARDUINO, IOS设备做些什么?

  • 通过iPhone传输数据Arduino,完成遥控操作
  • 将传感器信息通过串口传给iPhone以备后续操作
  • Arduino通过iOS设备来访问互联网信息
  • 更多用法,依赖你的想象力..

详细内容见BlueShield发布 — Arduino的蓝牙4.0串口透明传输模块

购买连接

tmux的滚屏

tmux下无法滚屏很烦人。

一句话就解决了: CTRL + B 再按 \”[\”,这时就可以用光标键来操作翻页滚屏

如果需要兼容vim的操作方式,那么在~/.tmux.conf加上一行:

setw -g mode-keys vi

使用CocoaPods之后的头文件包含问题

使用了一段时间CocoaPods来管理Objective-c的类库,方便了不少。但是有一个小问题,当我在xcode输入import关键字的时候,没有自动联想补齐代码的功能,需要手工敲全了文件名,难以适应。

在stackoverflow上找到了解决办法:

Go to the Target > \”Build Settings\” tab and find the \”User Header Search Paths\” setting.

Set this to \”$(BUILT_PRODUCTS_DIR)\” and check the \”Recursive\” check box.

Now the built target will search the workspace’s shared build directory to locate the linkable header files.

简单说就是这么几步:

  • 选择Target -> Build Settings 菜单,找到\”User Header Search Paths\”设置项
  • 新增一个值$(BUILT_PRODUCTS_DIR),并且选择\”Recursive\”,这样xcode就会在项目目录中递归搜索文件

自动补齐功能马上就好使了。

php的libev扩展

pecl上新添了一个ev扩展,目前版本是0.2.0,已经stable。这个扩展为php提供了libev库的接口。

ev is a PECL extension providing inteface to libev library – high performance full-featured event loop written in C.

ABOUT LIBEV
Libev is an event loop: you register interest in certain events (such as a file descriptor being readable or a timeout occurring), and it will manage these event sources and provide your program with events.

那么什么是libev呢,从网上摘录一段:

libev 是高性能事件循环/事件模型的网络库,并且包含大量新特性。
它是继lievent和Event perl module之后的一套全新网络库。它追求的目标:速度更快,bug更少,特性更多,体积更小。
它和libevent很像,按照作者的介绍,可以作为libevent的替代者,能够提供更高的性能。并不需要复杂的配置。

看起来和之前提到的libevent大有渊源,但是这个扩展的作者显然比较活跃,一周内提交了3个版本。

代码示例

timer的使用

stop();
    // Stop the watcher if further calls cause more than 10 iterations
    Ev::iteration() >= 10 and $w->stop();
});

// 创建一个已停止的timer,手工start才有效
$w_stopped = EvTimer::createStopped(10, 5, function($w) {
    echo \"Callback of a timer created as stoppedn\";

    // Stop the watcher after 2 iterations
    Ev::iteration() >= 2 and $w->stop();
});

// Loop until Ev::stop() is called or all of watchers stop
Ev::run();

// Start and look if it works
$w_stopped->start();
echo \"Run single iterationn\";
Ev::run(Ev::RUN_ONCE);

echo \"Restart the second watcher and try to handle the same events, but don\'t blockn\";
$w2->again();
Ev::run(Ev::RUN_NOWAIT);

$w = new EvTimer(10, 0, function() {});
echo \"Running a blocking loopn\";
Ev::run();
echo \"ENDn\";
?>

输出内容


2 seconds elapsed
is called every second, is launched after 2 seconds
iteration = 1
is called every second, is launched after 2 seconds
iteration = 2
is called every second, is launched after 2 seconds
iteration = 3
is called every second, is launched after 2 seconds
iteration = 4
is called every second, is launched after 2 seconds
iteration = 5
Run single iteration
Callback of a timer created as stopped
Restart the second watcher and try to handle the same events, but don\'t block
Running a blocking loop
is called every second, is launched after 2 seconds
iteration = 8
is called every second, is launched after 2 seconds
iteration = 9
is called every second, is launched after 2 seconds
iteration = 10
END

I/O事件

例1

例2

stop();
    // Stop write watcher
    $w->stop();

    $in = \"HEAD / HTTP/1.1rn\";
    $in .= \"Host: google.co.ukrn\";
    $in .= \"Connection: Closernrn\";

    if (!socket_write($socket, $in, strlen($in))) {
        trigger_error(\"Failed writing $in to socket\", E_USER_ERROR);
    }

    $read_watcher = new EvIo($socket, Ev::READ, function ($w, $re)
        use ($socket, $e_nonblocking) {
        // Socket is readable. recv() 20 bytes using non-blocking mode
        $ret = socket_recv($socket, $out, 20, MSG_DONTWAIT);

        if ($ret) {
            echo $out;
        } elseif ($ret === 0) {
            // All read
            $w->stop();
            socket_close($socket);
            return;
        }

        // Caught EINPROGRESS, EAGAIN, or EWOULDBLOCK
        if (in_array(socket_last_error(), $e_nonblocking)) {
            return;
        }

        $w->stop();
        socket_close($socket);
    });

    Ev::run();
});

$result = socket_connect($socket, $address, $service_port);

Ev::run();
?>

输出

HTTP/1.1 301 Moved Permanently
Location: http://www.google.co.uk/
Content-Type: text/html; charset=UTF-8
Date: Sun, 23 Dec 2012 16:08:27 GMT
Expires: Tue, 22 Jan 2013 16:08:27 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 221
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Connection: close

源码

源码放在bitbucket

vimari – safari下的vimium扩展

虽说我现在用的主力浏览器还是chrome,但是偶尔还是会给safari一些机会,这让在chrome下用惯了vimium插件的我很不适应,按下熟悉的按钮没得到应有的反馈,简直就跟残废了似的。

于是我开始放狗搜索,然后得到了这个 — vimari.

简单介绍

vimari从chrome的vimium移植而来,大部分代码都是基于vimium。而vimium对于chrome来说,就象是vimperator之于firefox,在浏览网页的时候,也能带来vim类似的操作体验,对于vim控来说实在是不可多得的好扩展。

Vimari is a Safari extension that provides keyboard based navigation. The code is heavily based on \’vimium\’, a chrome extension that provides much more extensive features.
Vimari attempts to provide a lightweight port of vimium to Safari, taking the best components of vimium and adapting them to Safari.

稍加配置,我就很容易获得了和后者类似的使用体验。例如下图的配置选项中,我把 Modifier key to preceed commands 这一项留空,按下f键就可以选择打开页面上的某个链接,而不是使用它默认的快捷键ctrl + f.

\"vimari\"

注意事项

安装扩展之后请即刻升级至最新版本,否则可定制的选项比较少。

多个github帐号的ssh keys支持

不知不觉就有了多个github帐户,平时为了方便都是采用ssh去操作git,所以这个时候问题就来了,在同一台机器上对多个github操作时,会因为ssh key只有一个而无法提交。所以我需要想办法配置多个ssh keys.

解决办法

放狗搜了一圈,有类似需求的大有人在。例如这里:Multiple GitHub Accounts & SSH Config

\’I\’m having some trouble getting two different SSH keys/GitHub accounts to play well together. I have the following setup:

Repos accessible from one account using git@github.com:accountname Repos accessible from another account using git@github.com:anotheraccount

傻瓜操作步骤

生成新的ssh key

ssh-add这一步很重要,否则是前功尽弃


ssh-keygen -t rsa -C \'work@mail.com\'
ssh-add ~/.ssh/work_rsa

配置.ssh/config

我只需要在~/.ssh/config里新增一个Host的别名,将不同帐号的区分开来就可以了。

Host me.github.com
    HostName github.com
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/me_rsa

Host work.github.com
    HostName github.com
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/work_rsa

配置git仓库

需要把git的配置更改过来,其中github.com更换为work.github.com,这样它会找到对应的key来登录。

git remote add origin git@work.github.com:work/test.git

关于Markdown Preview Plus的补充说明

Markdown Preview Plus的使用方法做一个补充说明,这是一个chrome的插件,方便预览markdown格式的文件。

使用方法

  • 从chrome的webstore安装Markdown Preview Plus插件
  • 在设置页中勾选 “允许访问文件网址”,如图
    \"options\"
  • 在chrome中打开本地markdown文件,http/https也是可以支持的
  • 你会看到已经转换成html的内容

为每个md文件设置样式

新的0.2.1版本已经支持对每个md文件设置样式,这个可以覆盖全局的样式设置

\"弹出页面\"