Bootstrap 3 Grid 笔记

作为非专业的前端开发,Bootstrap 真是个好东西,特别适合做运营、管理系统界面。这些系统界面要求不高,干净整齐就好,最主要的就是网格 Grid 的使用,简单记录一下。

Bootstrap 3 自带了移动优先的响应流式网格布局系统,将整个屏幕或某一视区(viewport)划分为 12 列,使用时把内容放到相应列中,自然就整齐不乱。一般来说 Bootstrap 的网页结构是 container > row > col,一个或多个 col 组成一组 row,多个 row 归于一个 container,这样的多级布局很方便在大小不同的屏幕灵活布局。

最小单位 col 有四种:col-xs-*, col-sm-*, col-md-*, col-lg-*,(题外话,Bootstrap 这四个 col 命名实在是让人费解,也不是什么缩写,完全没有 Foundation 的 small-2 large-4 columns 简洁明了),分别适用于手机(768px 以下),平板(768-992px),桌面(992px+)和超大屏幕(1200px+),后一位是需要的宽度比例,总和为 12,这样就自动把界面进行划分布局,比如想把一个普通电脑屏幕左右平分,两个 col-md-6 即可。col 可以组合,这样就同时适配手机和电脑,比如在电脑是左右三等分,手机是二等分:

<div class="container">
  <div class="row">
    <div class="col-md-4 col-xs-6">
      A
    </div>
    <div class="col-md-4 col-xs-6">
      B
    </div>
    <div class="col-md-4 col-xs-6">
      C
    </div>
  </div>
</div>

col 也可以嵌套,要注意的是每个 col 里又是一个 12 等分的完整网格,也要包在二级容器 row 里。比如左右二等分,每个再 1:2 划分:

<div class="container">
  <div class="row">
    <div class="col-md-6">
      <div class="row">
        <div class="col-sm-4">
          A
        </div>
        <div class="col-sm-8">
          B
        </div>
      </div>
    </div>
    <div class="col-md-6">
      ...
    </div>
  </div>
</div>

网格还有一个方便的东西就是 Offset .col-md-offset-*,可以把某一 div 向右偏移指定比例,比如只一半的宽度,然后居中,3-6-3 布局:

<div class="container">
  <div class="row">
    <div class="col-sm-6 col-sm-offset-3">
      S
  </div>
</div>

参考 Bootstrap 3: the new grid system, for starters.

批量杀进程

批量杀掉包含某一关键字的进程:

ps aux|grep KEY|grep -v grep|awk {'print $2'}|xargs kill -9

git cherry-pick

git-cherry-pick - Apply the changes introduced by some existing commits.

实际开发中会有这种情况:同时存在 v1、v2 两个分支,且不可合并。然后发现两个分支都存在某 bug,在 v1 中修复,需要合并到 v2,要么手动修改,或者用 git cherry-pick:

git cherry-pick 0ba264a1e666bacc

准爸爸

2013-10-20.

Crash Early, Crash Often

最近开发中的一点感悟。

在开发阶段要尽量多的尽量早的暴露问题,应用 crash 恰恰是暴露问题最直接的方式,方便定位没有考虑到的细节问题。

举个例子,应用中对数据边界通常会进行保护判断,比如数组取值前判断数组长度是否满足。其实在开发阶段完全没必要,要求 array[3] 有值你之前的操作就必须要满足,如果不能达到就要想想哪里出了问题,如果数据源根本不能提供那么就要检查业务设计是否有问题。过分的保护检查不一定是好事。

@zadr's iOS 7 dev tricks

@zadr 在 iOS 7 正式发布几个小时后在 Twitter 上连续发了一些 iOS 7 SDK 小技巧,大部分都是我还不知道的东西,所以摘录一下,版权归 @zadr 完全所有。

iOS 7: -[AVPlayer volume] and -[AVPlayer muted]; ! You can finally programmatically control the volume of playback without private APIs! via

AVPlayer 音量状态。

iOS 7: [CTTelephonyNetworkInfo currentRadioAccessTechnology]; what kind of cellular connection you’re on now. LTE/GPRS/CDMA{Rev 0, …}/etc! via

获取运营商网络类别。

iOS 7: -[NSArray firstObject]; Like -[NSArray lastObject];, only, the other end of the array. via

NSArray 直接取第一个对象。推荐 Underscore.m.

iOS 7: NSData has base64 encoding/decoding support now. And this fancy method, enumerateByteRangesUsingBlock:. via

NSData 有了原生的 base64 方法 base64EncodedStringWithOptions:

iOS 7: NSURLComponents: Build a NSURL and have it automatically handle encoding of strings for fragement/path/query/etc. via

NSURLComponents 自动编码处理。

iOS 7: iAd support for prerolls in MPMoviePlayerController. This is more of a heads up than an FYI. via

iAd 支持从前卷广告类型。

iOS 7: JavaScriptCore! Bridge between executing native code and executing JavaScript without needing a UIWebView. via

ObjC 直接操作 JS 的 API,JavaScriptCore 是个里程碑,值得好好学习一番。

iOS 7: MKDistanceFormatter. Localized, unit-specific formatting of distances for both imperial and metric systems. via

MapKit 相关,支持本地化的地点距离换算。

iOS 7: -[MPVolumeView wirelessRouteActive] and -[MPVolumeView wirelessRoutesAvailable] — Customize volume control when AirPlay is available. via

AirPlay 音量控制。

iOS 7: -[UIScrollView keyboardDismissMode]; — Easily recreate Messages.app’s scroll-to-dismiss-keyboard behavior! via

类似系统 Message 的键盘滑动消失效果,UIScrollViewKeyboardDismissModeInteractive.

iOS 7: UITextView supports inserting and tapping on links. Making your own Twitter client just got that much easier! via

UITextView 支持链接点击,应该是 TextKit 带来的新功能。TextKit 也是一个很值得学习的新东西。

iOS 7: AVCaptureDeviceFormat has video zooming with stabilization and simple control over frame rate/duration! via

视频录制支持缩放,以前不支持?

iOS 7: AVSpeechSynthesis - Speak text to users without requiring VoiceOver to be turned on. via

VoiceOver 相关。

iOS 7: Foundation changed a whole bunch of return types to be instancetype instead of id. Yay, type safety! via

默认对象返回类型改为 instancetype,自己封装的类库要跟进。

iOS 7: MediaAccessibility. New framework that makes it really easy to work with closed captions and video. via

图片视频功能继续加强。

iOS 7: MFMessageComposeViewController supports adding attachments! Take a photo/video and iMessage it to someone in the same flow. via

邮件分享支持直接添加附件。

iOS 7: AVCaptureMetadataOutput can detect and decode most kinds of barcodes, including QR codes! via

原生支持二维码扫描!

iOS 7: Also fixed some security vulnerabilities and updated root certificates. Check ‘em out, http://support.apple.com/kb/HT5934 via

修复了一些证书相关的安全问题。

iOS 7: SSReadingList. Add Stuff to Safari’s reading list that syncs between your Mac and iOS devices. via

Safari Reading List API。

iOS 7: I don’t even know how to describe it accurately, but, there’s some amazing motion APIs in there to explore. Can’t call out just one. via

CoreMotion API,M7 也是 iPhone 5s 最吸引我的东西。

iOS 7: UIInputView: If you have a custom input field, use this as the root object. All subviews then get tinting and blur effects. via

iOS 7 输入框的模糊效果。

iOS 7: UISimpleTextPrintFormatter: Print attributed strings without having to fall back to CoreGraphics to render content before printing. via

更为简单的打印内容格式化。

iOS 7: -[NSObject decreaseSize:] / -[NSObject increaseSize:]; // called when cmd+ & cmd- are hit, so you can increase/decrease content size. via

外接键盘可控制显示大小,类似 OS X 上的 Cmd+/Cmd-.

iOS 7: dispatch_source_memorypressure_flags_t, for whenever the system’s memory pressure conditions change. Critical <-> Warn <-> Normal. via

GCD 相关,话说 GCD 的使用一直停留在基本层面,要多多深入。

PS: 分享一个 Twitter 搜索技巧: iOS 7 from:zadr 即可搜索 @zadr 所有包含 iOS 7 关键字的 Tweets。最后鄙视一下一些所谓的开发者,完全无视 NDA 的存在,在 iOS 7 SDK 正式发布前通过翻译等方式来刷自己的技术存在感。

NSURLConnection 在页面滑动时继续执行

这篇笔记只是为了清掉 BlogTodos,实际开发中用了 AFN 等是不会遇到这个问题。当然也可以作为原理理解。

首先是 NSRunLoop,我的理解 runloop 就是 iOS 的消息循环处理机制,响应处理各种消息事件。runloop 有不同的执行模式,不同模式下只会响应处理该模式类型的事件。App 运行时会有一个主线程 mainRunLoop,在程序中可以用 [NSRunloop currentRunLoop] 简单获取当前的 runloop。

NSURLConnection 在网络请求的时候(无论主线程还是子线程),如果有点击或滑动界面,网络请求会被暂停执行,直到滑动等操作结束。这是因为 NSURLConnection 默认是 NSDefaultRunLoopMode,也就是说只会在该模式下执行,当有滑动、点击界面等操作的时候,runloop 会切换到 NSEventTrackingRunLoopMode 来处理界面操作,这时候网络请求就会被暂停执行,直到界面操作结束,runloop 模式切换回去。

解决方法就是设置 NSURLConnection 的执行模式为 NSRunLoopCommonModes,这样就会在所有模式下持续执行:

[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

NSRunLoop Class Reference:

NSDefaultRunLoopMode - The mode to deal with input sources other than NSConnection objects.

NSRunLoopCommonModes - Objects added to a run loop using this value as the mode are monitored by all run loop modes that have been declared as a member of the set of “common” modes.

参考 NSURLConnection: How to avoid blocked file loading during scrolling of UIScrollView or UITableView

NSInvocation Notes

iOS 中一般用 performSelector 系列方法调用某个对象的方法消息,但是参数过多就不太方便,这时候就可以用 NSInvocation。一个简单的例子:

NSMethodSignature *sig = [self methodSignatureForSelector:@selector(addAlbum:atIndex:)];
NSInvocation *action = [NSInvocation invocationWithMethodSignature:sig];
[action setTarget:self];                            //0
[action setSelector:@selector(addAlbum:atIndex:)];  //1
[action setArgument:&deletedAlbum atIndex:2];       //2
[action setArgument:&currentAlbumIndex atIndex:3];  //3
[action retainArguments];
[action invoke];

NSMethodSignature 直译就是方法签名,保存了方法的参数类型和返回值信息 (type information for the arguments and return value of a method)。 通过方法签名信息就可以完整构建一个 invocation,对各个参数进行赋值后激活执行,也就完成了对象方法调用。

再看 NSMethodSignature 一段文档:

Indices begin with 0. The hidden arguments self (of type id) and _cmd (of type SEL) are at indices 0 and 1; method-specific arguments begin at index 2.

NSInvocation 第一步设定 Target(0),第二步设定 Selector(1),然后从 index 2 开始依次对参数赋值,因为 0/1 已被 Target/Selector 占用。要注意赋值的时候传的都是 指针 ,如果赋值参数可能会被释放,要记得 retainArguments。如果需要 NSInvocation 执行后的返回值:

NSString *returnString = nil; //假定返回值类型为 NSString
[action getReturnValue:&returnString];

最后附上 Three20 里用 NSInvocation 实现多参数 performSelector:

https://github.com/facebook/three20/blob/1.0.12/src/Three20Core/Sources/NSObjectAdditions.m#L89

- (id)performSelector:(SEL)selector
           withObject:(id)p1
           withObject:(id)p2
           withObject:(id)p3
           withObject:(id)p4
           withObject:(id)p5
{
    NSMethodSignature *sig = [self methodSignatureForSelector:selector];
    if (sig) {
        NSInvocation* invo = [NSInvocation invocationWithMethodSignature:sig];
        [invo setTarget:self];
        [invo setSelector:selector];
        [invo setArgument:&p1 atIndex:2];
        [invo setArgument:&p2 atIndex:3];
        [invo setArgument:&p3 atIndex:4];
        [invo setArgument:&p4 atIndex:5];
        [invo setArgument:&p5 atIndex:6];
        [invo invoke];

        if (sig.methodReturnLength) {
            id anObject;
            [invo getReturnValue:&anObject];
            return anObject;
        } else {
            return nil;
        }
    } else {
        return nil;
    }
}

MBP 不能充电解决

MBP 电源适配器不能充电,各种插拔都无效,真以为要悲剧了,搜到一个办法:

苹果的电源适配器在电流过大或电压不稳的情况下会自动启用保护机制,切断电流以保护电脑,所以才会充不进电。而解决方法非常简单,只需将 MagSafe 电源适配器拔出电源,静置 60秒以上,就可以重置电源适配器。

简单重置后果然有效,留记。

Dev 放权

最近的一点反思。

着重技术往 Dev Leader 转型的过程中,老是做不到技术放权。新需求和问题过来第一反应往往是自己怎么去做,原因有二:

  1. 不自信。自己技术不懂不熟,所以想借实战强化;刚学到一个新技术点想实用一次,毕竟技术性调研和实际项目应用差别还是很大。这种情况多出现在新项目。
  2. 不信任。对事不对人的说,项目紧,其他人对业务不是特别熟悉,所以很不放心把东西交出去做。

结果就是自己排了很多 tickets,很容易拖累进度,而其他人对业务继续不熟悉。

以后要加多 Code Reivew,前期系统设计多参与,后期实现时多跟进把控,具体实现大家一起完成,强化整体架构能力。