SuperYang`s Blog

Coding Everything.

ReactiveCocoa 设计规范

Design Guidelines【译】

RACSequence 的一些约定

  1. 默认情况延迟发生
  2. 默认会阻塞调用者
  3. 副作用只发生一次

RACSignal 的约定

  1. 信号事件有序串行执行,保证不会同时到达两个或多个信号,但是可以运行在不同的scheduler之上。
  2. 订阅事件总会在一个 scheduler 上
  3. 错误会立即传播(优先级最高)
  4. 订阅事件会产生副作用
  5. 订阅关系总会在complete或error时自动销毁
  6. 销毁会取消正在执行的任务并且清理相关的资源

JavaScript 骨骼动画 (DragonBones) 在 iOS 端截屏功能

需求背景:

使用 DragonBones 在 Webview 中绘制骨骼动画,并对当前的骨骼页面进行图层截取,实现保存本地和分享功能。

问题:

使用 DragonBones 制作骨骼动画时遇到一个问题,使用 WKWebView 加载骨骼动画正常,再对 WKWebView 的父容器 view (控制器 view )进行截图是出现空白。

解决思路及方案一:

让 iOS/Android 网络API开发更加自由-charles模拟服务器返回本地数据

原因:在与服务器联调接口之后,所有的API都能正常跑通,但是涉及到具体的业务逻辑时,比如界面遇到不同的数据做出特定的布局操作或弹框提示,再或者只有当数据字段符合特定的值时才能做出更多复杂的逻辑操作。如果依赖于服务器或者数据库,那么需要他们去帮你制造假数据来检测你的代码的正确性,这样是一次两次没问题,但是量大的时候,会影响双方的开发进度。能不能采取解耦的思想让移动端和服务端分隔开,在移动端测试开发阶段,自己根据接口文档制造自己需要的特定的返回数据呢?

解决方案:这时候我们需要自己的代理服务器来实现–使用 Charles 制作代理服务器。

具体需求:当API有所改动时,服务器正在开发相应功能,但是还没有部署到服务器上去,只是在原接口的返回数据中多加了一个字段“id”。现在移动端的业务逻辑写好了,就等数据测试了。

具体操作步骤:

HLS-iOS视频播放服务架构深入探究(二)

HLS-Demo地址:https://github.com/yangchao0033/HLS-Demo

使用demo前请注意下面的问题,我在代码中也做了注释。

1
2
3
4
5
6
7
8
9
10
11
//#warning 注意,不要直接使用切换流的主索引,当前代码的协议只提供对.ts定位的子索引的下载和播放,而且其中只有点播协议那一小段是可以下载的,直播协议只能播放,无法下载,无法下载的原因是因为m3u8的那个库中只对特定的一种m3u8的格式做了解析,而m3u8的格式有很多种,所以无法加息出来,该demo只做演示,不会对所有格式进行全解析,如果大家感兴趣的话可以对m3u8的库进行扩展,在github 上 pull request 我做一个补充扩展😁,我会及时在博客中进行更新。博客地址:superyang.gitcafe.io或yangchao0033.github.io 同简书:http://www.jianshu.com/users/f37a8f0ba6f8/latest_articles

/** 点播协议 (只有这个是可以下载的,但是苦于太短,没办法播放出来,正在寻找可以下载并播放的新的点播或直播源,希望有读者可以帮忙提供哈,不甚感激~)*/
//#define TEST_HLS_URL @"http://m3u8.tdimg.com/147/806/921/3.m3u8"
/** 视频直播协议 */
/** 父索引(无法下载,只作为结构分析) */
//#define TEST_HLS_URL @"http://dlhls.cdn.zhanqi.tv/zqlive/34338_PVMT5.m3u8"
/** 子索引(无法下载,只作为结构分析) */
//#define TEST_HLS_URL @"http://dlhls.cdn.zhanqi.tv/zqlive/34338_PVMT5_1024/index.m3u8?Dnion_vsnae=34338_PVMT5"
/** wwcd视频,果然苹果自己就用这个协议(无法下载,只作为结构分析) */
//#define TEST_HLS_URL @"http://devstreaming.apple.com/videos/wwdc/2015/413eflf3lrh1tyo/413/hls_vod_mvp.m3u8"

如果觉得文章有用的话,请读者在github上点个star😁,或者在简书上点个赞。

Demo配置原理:

1、 需要导入第三方库:ASIHttpRequest,CocoaHTTPServer,m3u8(其中ASI用于网络请求,CocoaHTTPServer用于在ios端搭建服务器使用,m3u8是用来对返回的索引文件进行解析的)

HLS-iOS视频播放服务架构深入探究(一)

HTTP Live Streaming (HLS)

苹果官方对于视频直播服务提出了 HLS 解决方案,该方案主要适用范围在于:

  • 使用 iPhone 、iPod touch、 iPad 以及 Apple TV 进行流媒体直播功能。(MAC 也能用)
  • 不使用特殊的服务软件进行流媒体直播。
  • 需要通过加密和鉴定(authentication)的视频点播服务。

首先,需要大家先对 HLS 的概念进行预览。

CoreText基础概念(扫盲篇)

CoreText 基础扫盲(阅读源码必看了)

这段时间阅读ibireme神的源码,看到了 CoreText 排版这一块,里面包含了很多文字排版的专有名词,这里做一下整理,顺便帮大家安利一下。

CoreText 框架中最常用的几个类:

下面是该框架的结构图

CocoaPod Version Update

问题描述:

使用 pod 安装第三方库时无法使用 pod search 搜索最新的版本

定位问题:

使用的 pod 版本过低

方案:

RunLoop深度探究(五)

RunLoop深度探究(四)

使用 Run Loop 对象

一个 run loop 对象提供了一些主要接口用于向你的 run loop 中添加 input source ,timers, 和run loop observer,并且运行它。每一条线程有且只有一个run loop 与他相关联。在 Cocoa 中,这个对象是 NSRunLoop 类的一个实例。在底层的应用中,它是指向 CFRunLoopRef 这种不透明类型的一个指针。

获取 Run Loop 对象

你需要使用以下其中之一来获取当前线程的 Run Loop :

RunLoop深度探究(四)

原文链接:Run Loops

Run loops 是与线程相关联的基础设施的一部分。Run loop 是用来调度工作并且协调传入事件的时间处理循环。run loop 的目的是:让你的线程在有工作的任务的事后保持忙碌,并且在空闲的事后使线程保持休眠。

RunLoop深度探究(三)

苹果用 RunLoop 实现的功能

首先我们可以看一下 App 启动后 RunLoop 的状态:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
CFRunLoop {
    current mode = kCFRunLoopDefaultMode
    common modes = {
        UITrackingRunLoopMode
        kCFRunLoopDefaultMode
    }

    common mode items = {

        // source0 (manual)
        CFRunLoopSource {order =-1, {
            callout = _UIApplicationHandleEventQueue}}
        CFRunLoopSource {order =-1, {
            callout = PurpleEventSignalCallback }}
        CFRunLoopSource {order = 0, {
            callout = FBSSerialQueueRunLoopSourceHandler}}

        // source1 (mach port)
        CFRunLoopSource {order = 0,  {port = 17923}}
        CFRunLoopSource {order = 0,  {port = 12039}}
        CFRunLoopSource {order = 0,  {port = 16647}}
        CFRunLoopSource {order =-1, {
            callout = PurpleEventCallback}}
        CFRunLoopSource {order = 0, {port = 2407,
            callout = _ZL20notify_port_callbackP12__CFMachPortPvlS1_}}
        CFRunLoopSource {order = 0, {port = 1c03,
            callout = __IOHIDEventSystemClientAvailabilityCallback}}
        CFRunLoopSource {order = 0, {port = 1b03,
            callout = __IOHIDEventSystemClientQueueCallback}}
        CFRunLoopSource {order = 1, {port = 1903,
            callout = __IOMIGMachPortPortCallback}}

        // Ovserver
        CFRunLoopObserver {order = -2147483647, activities = 0x1, // Entry
            callout = _wrapRunLoopWithAutoreleasePoolHandler}
        CFRunLoopObserver {order = 0, activities = 0x20,          // BeforeWaiting
            callout = _UIGestureRecognizerUpdateObserver}
        CFRunLoopObserver {order = 1999000, activities = 0xa0,    // BeforeWaiting | Exit
            callout = _afterCACommitHandler}
        CFRunLoopObserver {order = 2000000, activities = 0xa0,    // BeforeWaiting | Exit
            callout = _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv}
        CFRunLoopObserver {order = 2147483647, activities = 0xa0, // BeforeWaiting | Exit
            callout = _wrapRunLoopWithAutoreleasePoolHandler}

        // Timer
        CFRunLoopTimer {firing = No, interval = 3.1536e+09, tolerance = 0,
            next fire date = 453098071 (-4421.76019 @ 96223387169499),
            callout = _ZN2CAL14timer_callbackEP16__CFRunLoopTimerPv (QuartzCore.framework)}
    },

    modes  {
        CFRunLoopMode  {
            sources0 =  { /* same as 'common mode items' */ },
            sources1 =  { /* same as 'common mode items' */ },
            observers = { /* same as 'common mode items' */ },
            timers =    { /* same as 'common mode items' */ },
        },

        CFRunLoopMode  {
            sources0 =  { /* same as 'common mode items' */ },
            sources1 =  { /* same as 'common mode items' */ },
            observers = { /* same as 'common mode items' */ },
            timers =    { /* same as 'common mode items' */ },
        },

        CFRunLoopMode  {
            sources0 = {
                CFRunLoopSource {order = 0, {
                    callout = FBSSerialQueueRunLoopSourceHandler}}
            },
            sources1 = (null),
            observers = {
                CFRunLoopObserver >{activities = 0xa0, order = 2000000,
                    callout = _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv}
            )},
            timers = (null),
        },

        CFRunLoopMode  {
            sources0 = {
                CFRunLoopSource {order = -1, {
                    callout = PurpleEventSignalCallback}}
            },
            sources1 = {
                CFRunLoopSource {order = -1, {
                    callout = PurpleEventCallback}}
            },
            observers = (null),
            timers = (null),
        },

        CFRunLoopMode  {
            sources0 = (null),
            sources1 = (null),
            observers = (null),
            timers = (null),
        }
    }
}

可以看到,系统默认注册了5个Mode: