标签归档iOS

Swift blog

建议读一通swift
blog来了解OC与swift不同以及swift版本变动细节

OC id -> Swift Any

瑜,不待手动装箱
令OC API更加灵敏

OC Swift2 Swift3
id AnyObject Any
NSArray * [AnyObject] [Any]
NSDictionary * [NSObject:AnyObject] [AnyHashable:Any]
NSSet * Set<NSObject> Set<AnyHashable>

欲留意的而是swift2不再供隐式转换,因此NS桥接的待你出示转换

Overriding methods and conforming to protocols

取名符合OC的正式,id->Any

// Swift 2
class Foo: NSObject, NSCopying {
    override func isEqual(_ x: AnyObject?) -> Bool { ... }
    func copyWithZone(_ zone: NSZone?) -> AnyObject { ... }
}

// Swift 3
class Foo: NSObject, NSCopying {
    override func isEqual(_ x: Any?) -> Bool { ... }
    func copy(with zone: NSZone?) -> Any { ... }
}

Untyped Collections

隐式桥接不存在了,需要采取as,swift3导入的cocoa接受了Any/AnyHashable,因此对于集合也得以应用[AnyHashable:Any]

// Swift 2
struct State {
    var name: String
    var abbreviation: String
    var population: Int

    var asPropertyList: [NSObject: AnyObject] {
        var result: [NSObject: AnyObject] = [:]//也可以使用NSDictionary
        // Implicit conversions turn String into NSString here…
        result["name"] = self.name
        result["abbreviation"] = self.abbreviation
        // …and Int into NSNumber here.
        result["population"] = self.population
        return result
    }
}

let california = State(name: "California",
                       abbreviation: "CA",
                       population: 39_000_000)
NSNotification(name: "foo", object: nil,
               userInfo: california.asPropertyList)

// Swift 3
struct State {
    var name: String
    var abbreviation: String
    var population: Int

    // Change the dictionary type to [AnyHashable: Any] here...
    var asPropertyList: [AnyHashable: Any] {
        var result: [AnyHashable: Any] = [:]
        // No implicit conversions necessary, since String and Int are subtypes
        // of Any and AnyHashable
        result["name"] = self.name
        result["abbreviation"] = self.abbreviation
        result["population"] = self.population
        return result
    }
}
let california = State(name: "California",
                       abbreviation: "CA",
                       population: 39_000_000)
// ...and you can still use it with Cocoa API here
Notification(name: "foo", object: nil,
             userInfo: california.asPropertyList)

The AnyHashable Type

Any类型可以有另外项目,但是Dictionary、Set需要Hasble,AnyHashble是swift3提出的hashable的超类,任何一个可hash的类且实现了Anyhashble协议,比如String、Int

Explicit Conversion for Unbridged Contexts

在部分限制的场地swift不能够一直桥接C和OC的计划,比如id*,这个时段api将会晤显示UnsafePointer<AnyObject>,此时待as转换,再&

// ObjC
@interface Foo

- (void)updateString:(NSString **)string;
- (void)updateObject:(id *)obj;

@end

// Swift
func interactWith(foo: Foo) -> (String, Any) {
    var string = "string" as NSString // explicit conversion
    foo.updateString(&string) // parameter imports as UnsafeMutablePointer<NSString>
    let finishedString = string as String

    var object = "string" as AnyObject
    foo.updateObject(&object) // parameter imports as UnsafeMutablePointer<AnyObject>
    let finishedObject = object as Any

    return (finishedString, finishedObject)
}

除此以外,OC的合计是类似协议,不能够就此结构体、枚举或另轻量级的通用型遵守OC的商事

AnyObject Member Lookup

Any没有AnyObject的摸索行为艺术,因此无克动态的向Any发送信息,但是AnyObject可以,此时用更换

// Swift 2
func foo(x: NSArray) {
    // Invokes -description by magic AnyObject lookup
    print(x[0].description)
}

// Swift 3
func foo(x: NSArray) {
    // Result of subscript is now Any, needs to be coerced to get method lookup
    print((x[0] as AnyObject).description)//也可以转换到你期望的指定类型as!NSOjbect
}

Swift Value Types in Objective-C

Any可以有所另外的结构体、枚举、元组或者其他的种类,OC的id在swift3等价于any,在swift2中得手动封箱或者转入类,swift3则免待

// Swift 2
struct CreditCard { number: UInt64, expiration: NSDate }

let PaymentMade = "PaymentMade"

// We can't attach CreditCard directly to the notification, since it
// isn't a class, and doesn't bridge.
// Wrap it in a Box class.
class Box<T> {
    let value: T
    init(value: T) { self.value = value }
}

let paymentNotification =
    NSNotification(name: PaymentMade,
                   object: Box(value: CreditCard(number: 1234_0000_0000_0000,
                                                 expiration: NSDate())))


// Swift 3
let PaymentMade = Notification.Name("PaymentMade")

// We can associate the CreditCard value directly with the Notification
let paymentNotification =
    Notification(name: PaymentMade,
                 object: CreditCard(number: 1234_0000_0000_0000,
                                    expiration: Date()))

用小心的凡swift3中对此大规模的布局体类型将会晤桥接作为透明对象要休是cocoa对象,Int、UInt、Double、Bool会桥接为NSNumber,Int8,UInt16虽说单独桥接为透明对象。如果赶上了unrecognized selector sent to _SwiftValue题材,它象征OC尝试唤醒一个办法以swift
值类型上,此时我们用手动管理

swift Any持有任一类包括Optional,尽管OC api要求是nonull
id,Optional在不解包的情事下吧足以作为参数传递,会招runtime
error而无是编译错误。swift3.0.1+Xoce8.1解决了上述问题,为了避免兼容问题,不要因让透明对象为前景之swift可能会见桥接到固定类型

Working with JSON in Swift

JSONSerialization Foundation framework

Extracting Values from JSON

JSONSerialization类方法jsonObject返回Any类型并且扔来很要data不克分析

import Foundation

let data: Data // received from a network request, for example
let json = try? JSONSerialization.jsonObject(with: data, options: [])

json顶层对象一般为字典或者反复组,我们得用as?+if进行判断转换

// Example JSON with object root:
/*
    {
        "someKey": 42.0,
        "anotherKey": {
            "someNestedKey": true
        }
    }
*/
if let dictionary = jsonWithObjectRoot as? [String: Any] {
    if let number = dictionary["someKey"] as? Double {
        // access individual value in dictionary
    }

    for (key, value) in dictionary {
        // access all key / value pairs in dictionary
    }

    if let nestedDictionary = dictionary["anotherKey"] as? [String: Any] {
        // access nested dictionary values by key
    }
}

// Example JSON with array root:
/*
    [
        "hello", 3, true
    ]
*/
if let array = jsonWithArrayRoot as? [Any] {
    if let firstObject = array.first {
        // access individual object in array
    }

    for object in array {
        // access all objects in array
    }

    for case let string as String in array {
        // access only string values in array
    }
}

Creating Model Objects from Values Extracted from JSON

若来只食堂的model

import Foundation

struct Restaurant {
    enum Meal: String {
        case breakfast, lunch, dinner
    }

    let name: String
    let location: (latitude: Double, longitude: Double)
    let meals: Set<Meal>
}

来自sever的JSON数据

{
    "name": "Caffè Macs",
    "coordinates": {
        "lat": 37.330576,
        "lng": -122.029739
    },
    "meals": ["breakfast", "lunch", "dinner"]
}

Writing an Optional JSON Initializer

extension Restaurant {
    init?(json: [String: Any]) {
        guard let name = json["name"] as? String,
            let coordinatesJSON = json["coordinates"] as? [String: Double],
            let latitude = coordinatesJSON["lat"],
            let longitude = coordinatesJSON["lng"],
            let mealsJSON = json["meals"] as? [String]
        else {
            return nil
        }

        var meals: Set<Meal> = []
        for string in mealsJSON {
            guard let meal = Meal(rawValue: string) else {
                return nil
            }

            meals.insert(meal)
        }

        self.name = name
        self.coordinates = (latitude, longitude)
        self.meals = meals
    }
}

Writing a JSON Initializer with Error Handling

enum SerializationError: Error {
    case missing(String)
    case invalid(String, Any)
}

extension Restaurant {
    init(json: [String: Any]) throws {
        // Extract name
        guard let name = json["name"] as? String else {
            throw SerializationError.missing("name")
        }

        // Extract and validate coordinates
        guard let coordinatesJSON = json["coordinates"] as? [String: Double],
            let latitude = coordinatesJSON["lat"],
            let longitude = coordinatesJSON["lng"]
        else {
            throw SerializationError.missing("coordinates")
        }

        let coordinates = (latitude, longitude)
        guard case (-90...90, -180...180) = coordinates else {
            throw SerializationError.invalid("coordinates", coordinates)
        }

        // Extract and validate meals
        guard let mealsJSON = json["meals"] as? [String] else {
            throw SerializationError.missing("meals")
        }

        var meals: Set<Meal> = []
        for string in mealsJSON {
            guard let meal = Meal(rawValue: string) else {
                throw SerializationError.invalid("meals", string)
            }

            meals.insert(meal)
        }

        // Initialize properties
        self.name = name
        self.coordinates = coordinates
        self.meals = meals
    }
}

Interactive Playgrounds

关于此可以去看本身之简文playground正确采取姿势

Literals in Playgrounds

Xcode7.1开始支持字面量,主要用来颜色、图片、文件

Strings in Swift 2

至于此可以错过押自己之简文汝确实懂swift
string吗?

Increasing Performance by Reducing Dynamic Dispatch

swift允许再次写超类的主意以及属性,这即需要以运转时接的访并且实施间接调用。这个技术叫做动态派发,这项技艺增加了语言表达的复杂和大度的runtime消耗以间接的运及。下面介绍三栽艺术消除动态派发:final、private、WholeModule
Optimization

告澳门新葡亰官网看下的代码

class ParticleModel {
    var point = ( 0.0, 0.0 )
    var velocity = 100.0

    func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
        point = newPoint
        velocity = newVelocity
    }

    func update(newP: (Double, Double), newV: Double) {
        updatePoint(newP, newVelocity: newV)
    }
}

var p = ParticleModel()
for i in stride(from: 0.0, through: 360, by: 1.0) {
    p.update((i * sin(i), i), newV:i*1000)
}

便像面写的,编译器发出动态派发调用

  1. 调用p 的 update
  2. 调用p 的 updatePoint
  3. 取p 的 point长祖属性
  4. 获取p 的 速率

此间使用动态派发的因在ParticleModel的子类可能通过可计算属性重写point、velocity,也再度写update、updatePonit

动态派发调用的贯彻是透过搜寻method
table然后行间接调用。着相对于直接调用的速度必然是徐的。

Use final when you know that a declaration does not need to be overridden

final关键字会范围class、method、property不吃重写。能够安全之使编译器取消动态派发。point、velocity、updatePoint不进行动态派发,直接看,update进行动态派发

class ParticleModel {
    final var point = ( x: 0.0, y: 0.0 )
    final var velocity = 100.0

    final func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
        point = newPoint
        velocity = newVelocity
    }

    func update(newP: (Double, Double), newV: Double) {
        updatePoint(newP, newVelocity: newV)
    }
}

final修饰类的时段,表明无克为子类化,因此指明函数、属性都是final

final class ParticleModel {
    var point = ( x: 0.0, y: 0.0 )
    var velocity = 100.0
    // ...
}

Infer final on declarations referenced in one file by applying the private keyword.

动用private关键字,限制以当下文件内,如果手上文件内没针对拖欠class的重写,那么编译器就会想其不适用动态派发

class ParticleModel {
    private var point = ( x: 0.0, y: 0.0 )
    private var velocity = 100.0

    private func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
        point = newPoint
        velocity = newVelocity
    }

    func update(newP: (Double, Double), newV: Double) {
        updatePoint(newP, newVelocity: newV)
    }
}

及final一样,private也可修饰class

Use Whole Module Optimization to infer final on internal declarations.

internal默认的访问控制权限表明只有能够在模块可见。swift编译文件是模块独立的,无法确定internal声明在不同的文本是否让另行写了。但是如果全模块的优化是被之,所有的模块同时编译、能够允许编译器将internal推断其的可见性

public class ParticleModel {
    var point = ( x: 0.0, y: 0.0 )
    var velocity = 100.0

    func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
        point = newPoint
        velocity = newVelocity
    }

    public func update(newP: (Double, Double), newV: Double) {
        updatePoint(newP, newVelocity: newV)
    }
}

var p = ParticleModel()
for i in stride(from: 0.0, through: times, by: 1.0) {
    p.update((i * sin(i), i), newV:i*1000)
}

Nullability and Objective-C

事实上对应的就是是只是选值

  • !表示非空
  • ?可空

个人档案关于 iOS 系统机能的 URL 汇总列表

蜂巢网络:prefs:root=MOBILE_DATA_SETTINGS_ID
*** — prefs:root=General&path=Network/***
Wi-Fi:prefs:root=WIFI
稳服务:prefs:root=LOCATION_SERVICES
私热点:prefs:root=INTERNET_TETHERING
有关本机:prefs:root=General&path=About
协助力量:prefs:root=General&path=ACCESSIBILITY
航空模式:prefs:root=AIRPLANE_MODE
锁定:prefs:root=General&path=AUTOLOCK
亮度:prefs:root=Brightness
蓝牙:prefs:root=Bluetooth
日设置:prefs:root=General&path=DATE_AND_TIME
FaceTime:prefs:root=FACETIME
设置:prefs:root=General
设置 prefs:root=SETTING
定位服务 prefs:root=LOCATION_SERVICES
键盘设置:prefs:root=General&path=Keyboard
iCloud:prefs:root=CASTLE
iCloud备份:prefs:root=CASTLE&path=STORAGE_AND_BACKUP
语言:prefs:root=General&path=INTERNATIONAL
定位:prefs:root=LOCATION_SERVICES
音乐:prefs:root=MUSIC
Music Equalizer — prefs:root=MUSIC&path=EQ
Music Volume Limit — prefs:root=MUSIC&path=VolumeLimit
Network — prefs:root=General&path=Network
Nike + iPod — prefs:root=NIKE_PLUS_IPOD
Notes — prefs:root=NOTES
Notification — prefs:root=NOTIFICATIONS_ID
Phone — prefs:root=Phone
Photos — prefs:root=Photos
Profile — prefs:root=General&path=ManagedConfigurationList
Reset — prefs:root=General&path=Reset
Safari — prefs:root=Safari
Siri — prefs:root=General&path=Assistant
Sounds — prefs:root=Sounds
Software Update — prefs:root=General&path=SOFTWARE_UPDATE_LINK
Store — prefs:root=STORE
Twitter — prefs:root=TWITTER
Usage — prefs:root=General&path=USAGE
Wallpaper — prefs:root=Wallpaper

电话 mobilephone://
备忘录 mobilenotes://
墨客 com.moke.moke-1://
刺全能王 camcard://
环顾全能王 camscanner://
TuneIn Radio tunein:// 或 tuneinpro://
OfficeSuite mobisystemsofficesuite://
WPS Office KingsoftOfficeApp://
Line line://
1Password onepassword://
Clear(著名的Todo应用) clearapp://
Chrome谷歌浏览器 googlechrome://
Calendars 5 calendars://
GoodReader 4 com.goodreader.sendtogr://
PDF Expert 5 pdfexpert5presence://
Documents 5 rdocs://
nPlayer nplayer-http://
GPlayer gplayer://
AVPlayer HD AVPlayerHD://
AVPlayer AVPlayer://
Ace Player aceplayer://
12306缔约票助手 trainassist://
金山词霸 com.kingsoft.powerword.6://
旋律大师 tencentrm://
赶集生活 **://
凤凰新闻 comIfeng3GifengNews://
强铁管家 gtgj://
飞信 fetion://
豆瓣FM doubanradio://
大智慧 dzhiphone://
布卡漫画 buka://
爱奇艺PPS ppstream://
哔哩哔哩动画 bilibili://
56视频 com.56Video://
365日历 rili365://
58同城 wbmain://
遇见 iaround://
陌陌 momochat://
出道词典 yddict://
优酷 youku://
掌阅iReader iReader://
艺龙旅行 elongIPhone://
迅雷+迅雷云播 thunder://
大熊猫公交 wb1405365637://
携程无线 CtripWireless://
无线苏州 SuZhouTV://
唯品会 vipshop://
微视 weishiiosscheme://
微拍 wpweipai://
旺信 wangxin://
网易公开课 ntesopen://
网易将军令 netease-mkey://
万年历 youloft.419805549://
土豆视频 tudou://
同花顺 amihexin://
天涯社区 tianya://
天气通Pro sinaweatherpro://
天气通 sinaweather://
墨迹天气 rm434209233MojiWeather://
淘宝旅行 taobaotravel://
人人 renrenios://
蜻蜓FM qtfmp://
浦发银行 wx1cb534bb13ba3dbd://
招商银行 cmbmobilebank://
建设银行 wx2654d9155d70a468://
工商银行 com.icbc.iphoneclient://
酷我音乐 com.kuwo.kwmusic.kwmusicForKwsing://
酷狗音乐 kugouURL://
今头久 snssdk141://
京东 openApp.jdMobile://
QQ mqq://
微信 wechat:// 或 weixin://
QQ音乐 qqmusic://
QQ斗地主 tencent382://
QQ浏览器 mttbrowser://
QQ安全中心 qmtoken://
QQ国际版 mqqiapi://
腾讯新闻 qqnews://
腾讯微云 weiyun://
腾讯地图 sosomap://
腾讯企业邮箱 qqbizmailDistribute2://
腾讯手机管家 mqqsecure://
腾讯视频 tenvideo:// 或 tenvideo2:// 或 tenvideo3://
腾讯微博 TencentWeibo://
无时无刻星连萌 tencent100689806://
整日爱脱 tencent100689805://
时刻酷跑 tencent100692648://
随时飞车 tencent100695850://
PPTV pptv://
爱奇艺视频 qiyi-iphone://
暴风影音 com.baofeng.play://
侍卫菲2 wb2217954495://
保萝卜 wb1308702128://
百度音乐 baidumusic://
百度视频 baiduvideoiphone:// 或 bdviphapp://
百度糯米 bainuo://
百度魔图 photowonder://
百度魔拍 wondercamera://
百度地图 baidumap://
百度导航 bdNavi://
百度 baiduboxapp:// 或 BaiduSSO://
搜狗输入法 com.sogou.sogouinput://
搜狐视频 sohuvideo-iphone:// 或 sohuvideo://
搜狐新闻 sohunews://
随手记 FDMoney://
无时无刻动听 ttpod://
开财记账 wacai://
威锋网 com.weiphone.forum://
新浪微博 weibo:// 或 sinaweibo://
网易邮箱 neteasemail://
高德导航 Autonavi://
百度输入法 BaiduIMShop://
百度贴吧 com.baidu.tieba://
淘宝 taobao://
天猫 tmall://
支付宝 alipay://
旺旺卖家版 wangwangseller://
百度云 baiduyun://
网易新闻 newsapp://
UC浏览器 ucbrowser://
E-Mail MESSAGE://

澳门新葡亰官网iOS视频直播初窥:高仿<喵播APP>

效果图

gif1

gif2

由于licecap录制的GIF失帧太严重, 都模糊掉了, 再推广少布置高清截图

png1

png2

前言

本年三月份,斗鱼腾讯领投的1亿美元融资的音于各大平台报道转载,在电竞、泛娱乐已是热门投资的就,网络直播平台自吧抱了各界的关怀。盗用两布置有关游戏直播的大势图

一日游直播规模

一日游直播规模

立刻尚只是是娱直播这块的蛋糕.直播业之竞争会进一步激烈,
不管是主播还是直播平台都面临着可以的竞争, 当然直播行业为会越规范,
直播元素也越来越多.

视频直播初窥

视频直播,可以分为 采集,前处理,编码,传输, 服务器处理,解码,渲染

  • 采访: iOS系统因为软硬件种类不多, 硬件适配性比较好, 所以比较简单.
    而Android端市面上机型众多, 要召开来机型的适配工作.PC端是最最累的,
    各种奇葩摄影头驱动.所以现在众多的中小型直播平台, 都放弃了PC的直播,
    更产生局部直播平台就做iOS端的视频直播.

  • 前面处理: 美颜算法,视频的歪曲效果, 水印等都是于是环节做.
    目前iOS端最显赫开源框架的定就是GPUImage.其中坐了125栽渲染效果,
    还支持各种本子自定义. 我高仿的喵播的美颜功能也是基于GPUImage的.

  • 编码:
    重难点在使以分辨率,帧率,码率,GOP等参数设计达到找到最佳平衡点。iOS8后,
    Apple开放了VideoToolbox.framework, 可以直接开展硬编解码,
    这为是干吗现在多数直播平台最低单支持及iOS8之原故之一.
    iOS端硬件兼容性比较好, 可以一直下硬编码.
    而Android得硬编码又是一致十分坑.

  • 传输: 这块一般还是提交CDN服务商.
    CDN单纯提供带宽和服务器之间的导,
    发送端和接纳端的网络连接抖动缓存还是如和谐实现之.目前国内极特别的CDN服务商应该是网宿.

  • 服务器处理: 需要以服务器做有淌处理工作,
    让推送上来之流适配各个平台各种不同的协议, 比如:RTMP,HLS,FLV…

  • 解码和渲染: 也即即音视频的播放. 解码毫无疑问也须要硬解码.
    iOS端兼容于好, Android依然十分坑.这块的困难在于音画同步,
    目前广大直播平台这块是刚伤.国内比较好的开源项目相应是B站开源的<a
    href=”https://github.com/Bilibili/ijkplayer"&gt;ijkplayer
    </a>. 斗鱼哪怕是基于<a
    href=”https://github.com/Bilibili/ijkplayer"&gt;ijkplayer
    </a>的, 本项目也是根据<a
    href=”https://github.com/Bilibili/ijkplayer"&gt;ijkplayer
    </a>的.

艺坑 : 降噪, 音频解码器, 蓝牙适配, 回声消除, 信令控制, 登录, 鉴权,
权限管理, 状态管理, 应用信息, 消息推送, 礼物系统, 即时聊, 支付体系,
统计系统, 数据库, 缓存, 分布式文件存储, 消息队列,
运维系统等等大小不一的坑等您来填!!!

基金坑 : 以带富也条例, 2万人数同时在线, 手机码率在600KB,
每个月份之拉动富费用至少在30万左右. 基于欢聚时代(YY)15年四季度财务报,
他们的带来富成本也人民币1.611亿首, 折合每月5000万+.
人力财力+渠道支出与其他支出就一无所知谈了.

社会坑: 还得天天与各种黑暗势力斗争, 包括韵, 广告, 刷小号,
刷充值, 告侵权, DDos…(我反而编译喵播的官方APP,
他们的种类名为就让Shehui, O(∩_∩)O哈哈~)

型下载地址

<a
href=”https://github.com/SunLiner/MiaowShow"&gt;GitHub下载地址&lt;/a&gt;

早期准备

品类重点是因<a
href=”https://github.com/Bilibili/ijkplayer"&gt;ijkplayer </a>的.
最好是从包改成framework. 原本我准备写一个封装教程,
不了后来当简书上发现了扳平篇专门详细的从包blog, 分享给大家: <a
href=”http://www.jianshu.com/p/1f06b27b3ac0"&gt;http://www.jianshu.com/p/1f06b27b3ac0&lt;/a&gt;.

设若你根据教程打包失败了(当然这种概率比粗),
我顿时还有平等份本身就由包好之(Release版), 下充斥地址:
链接:http://pan.baidu.com/s/1eRVetdK
密码:2dc0
下载后, 直接解压即可.

种类文件结构

  • Frameworks: 如果文件夹不有, 点击classes选择Show in Finder,
    新建一个即可, 将您自包之抑下载的framework拖入其中并拉扯上路中.
    你吧得自己打一个文书夹, 把这Frameworks直接delete即可

  • Profile : 个人基本, 这其中仅来一个ProfileController.
    因为总写重复代码, 都写吐了, 这儿来趣味的自己写一下吧, So easy…

  • Network : 关于网络连接的家伙类. 关于网络的实时监督, 网络状态的切换,
    网络请求的工具类都当此处面.

  • Other : 全局的常量. 当然你吗得以于里将文件结构进一步细化.

  • Home : 包含最新主播, 最暖直播, 关注之直播, 礼物排行榜等模块.
    还有无限要紧之视频直播呢以当下中了.

  • ShowTime :见名知意. 视频直播的先头处理,
    智能美颜和H264硬编码等还在这里面.

  • Main : UITabBarControllerUINavigationController的配置

  • Toos : 这儿命名有点不标准, 这里面放的都是种类因此到之归类

  • Login : 登录模块

  • Resource : 项目用到之资源文件

类详解

  • tip1: 判读网络类型.

每当收看直播的时候, 我们常见都是为此WiFi或者3/4G(土豪级别的),
一般用户以展开网络切换的当儿, 我们还使为起友善的唤起, 告诉TA:
您的网络状态切换至了XX状态. 假设用户从WiFi切换至4G,
你的利用为没个提醒, 导致TA的流量归零甚至不够了运营商一臀部的钱,
我怀念你的APP的用户体验吧就算归零或者也负了.

咱得以动用苹果之Reachability结缘下面的代码实时监听网络状态的转

typedef NS_ENUM(NSUInteger, NetworkStates) {
    NetworkStatesNone, // 没有网络
    NetworkStates2G, // 2G
    NetworkStates3G, // 3G
    NetworkStates4G, // 4G
    NetworkStatesWIFI // WIFI
};

// 判断网络类型
+ (NetworkStates)getNetworkStates
{
    NSArray *subviews = [[[[UIApplication sharedApplication] valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];
    // 保存网络状态
    NetworkStates states = NetworkStatesNone;
    for (id child in subviews) {
        if ([child isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) {
            //获取到状态栏码
            int networkType = [[child valueForKeyPath:@"dataNetworkType"] intValue];
            switch (networkType) {
                case 0:
                   //无网模式
                    states = NetworkStatesNone;
                    break;
                case 1:
                    states = NetworkStates2G;
                    break;
                case 2:
                    states = NetworkStates3G;
                    break;
                case 3:
                    states = NetworkStates4G;
                    break;
                case 5:
                {
                    states = NetworkStatesWIFI;
                }
                    break;
                default:
                    break;
            }
        }
    }
    //根据状态选择
    return states;
}
  • tip2: 登录模块

假定您基本上运行几次于就是会意识,
登录模块背景中播放的视频是2单视频每次随机播放一个底.并且是绝重复的,
也就是说只要你直接发呆着登录界面, 就会见单视频循环播放当下底看出频.
这儿的报到就是几独按钮, 没有具体的登录逻辑,
随便点哪一个按钮都可以进首页.

我们要监听视频, 是否播放完成.

// 监听视频是否播放完成
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didFinish) name:IJKMPMoviePlayerPlaybackDidFinishNotification object:nil];

倘播放完成了, 让IJKFFMoviePlayerController再次play即可

- (void)didFinish
{
    // 播放完之后, 继续重播
    [self.player play];
}
  • tip3: 首页

首页

这种效应相信广大人数犹看了要开过.我概括说一样下我的做法(不必然是极品的,
只是提供一个思路)

一个父控制器HomeViewController+三只子控制器(最热/最新/关注.
每个控制器各自管理好的政工逻辑, 高内集低耦合).
重写HomeViewControllerloadView,
self.view替换成UIScrollView.
将三只子控制器的view添加到UIScrollView上即可. 其他的功力落实,
请参照我之代码, 都有详实的华语注释.

  • tip4: 直播(面向观众捧)
    这是全体项目的严重性有了.这种直播的布局, 应该是比主流的了.
    我下载的不在少数直播类APP都是这个项目布局,
    包括YY也是这种界面布局.这个里面涉及的事物比较多矣, 三言两语真说不清.

简短说一下业已落实之功效:
A: 主播的直播
B: 关联主播的视频直播, 默认是不过发界面, 没有声音之.
点击该视图可以切换到这个主播
C: 下拉切换其他一个主播, 这个效果是甚广泛的.
做法是直播控制器是一个UICollectionViewController, 只来一个cell,
cell.frame就是self.collectionViewb.bounds.
我们进来直播控制器的时光, 其实是污染上一个关联主播数组,
每次下拉的上, 就加载数组里面的主播
D. 查看观众席的观众详情
E. 查看主播详情
F. 足迹: 粒子动画, 后面详解
G. 弹幕: 点击最下方的工具栏第一单按钮可以打开/关闭弹幕, 后面详解

  • tip5: 粒子动画实现游客足迹
    粒子动画的layer是加上到播放器的view上面的. 下面代码有详细的笺注

CAEmitterLayer *emitterLayer = [CAEmitterLayer layer];
// 发射器在xy平面的中心位置
emitterLayer.emitterPosition = CGPointMake(self.moviePlayer.view.frame.size.width-50,self.moviePlayer.view.frame.size.height-50);
// 发射器的尺寸大小
emitterLayer.emitterSize = CGSizeMake(20, 20);
// 渲染模式
emitterLayer.renderMode = kCAEmitterLayerUnordered;
// 开启三维效果
//    _emitterLayer.preservesDepth = YES;
NSMutableArray *array = [NSMutableArray array];
// 创建粒子
for (int i = 0; i<10; i++) {
    // 发射单元
    CAEmitterCell *stepCell = [CAEmitterCell emitterCell];
    // 粒子的创建速率,默认为1/s
    stepCell.birthRate = 1;
    // 粒子存活时间
    stepCell.lifetime = arc4random_uniform(4) + 1;
    // 粒子的生存时间容差
    stepCell.lifetimeRange = 1.5;
    // 颜色
    // fire.color=[[UIColor colorWithRed:0.8 green:0.4 blue:0.2 alpha:0.1]CGColor];
    UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"good%d_30x30", i]];
    // 粒子显示的内容
    stepCell.contents = (id)[image CGImage];
    // 粒子的名字
    //            [fire setName:@"step%d", i];
    // 粒子的运动速度
    stepCell.velocity = arc4random_uniform(100) + 100;
    // 粒子速度的容差
    stepCell.velocityRange = 80;
    // 粒子在xy平面的发射角度
    stepCell.emissionLongitude = M_PI+M_PI_2;;
    // 粒子发射角度的容差
    stepCell.emissionRange = M_PI_2/6;
    // 缩放比例
    stepCell.scale = 0.3;
    [array addObject:stepCell];
}

emitterLayer.emitterCells = array;
[self.moviePlayer.view.layer insertSublayer:emitterLayer below:self.catEarView.layer];
  • tip6: 弹幕
    弹幕澳门新葡亰官网使用的啊是一个叔方轮子<a
    href=”https://github.com/unash/BarrageRenderer"&gt;BarrageRenderer
    </a>. 这个开源项目的文档都是华语的, 用法也是好粗略的.

    核心配备

 _renderer = [[BarrageRenderer alloc] init];
// 设置弹幕的显示区域. 基于父控件的.
_renderer.canvasMargin = UIEdgeInsetsMake(ALinScreenHeight * 0.3, 10, 10, 10);
[self.contentView addSubview:_renderer.view];

弹幕配置

#pragma mark - 弹幕描述符生产方法
/// 生成精灵描述 - 过场文字弹幕
- (BarrageDescriptor *)walkTextSpriteDescriptorWithDirection:(NSInteger)direction
{
    BarrageDescriptor * descriptor = [[BarrageDescriptor alloc]init];
    descriptor.spriteName = NSStringFromClass([BarrageWalkTextSprite class]);
    descriptor.params[@"text"] = self.danMuText[arc4random_uniform((uint32_t)self.danMuText.count)];
    descriptor.params[@"textColor"] = Color(arc4random_uniform(256), arc4random_uniform(256), arc4random_uniform(256));
    descriptor.params[@"speed"] = @(100 * (double)random()/RAND_MAX+50);
    descriptor.params[@"direction"] = @(direction);
    descriptor.params[@"clickAction"] = ^{
        UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"弹幕被点击" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:nil];
        [alertView show];
    };
    return descriptor;
}

最终一步, 千万万一记start

[_renderer start];
  • tip7: 智能美颜功能
    现的直播平台, 美颜是标配.
    不然绝大多数之主播都是没法看之.美颜算法需要为此到GPU编程,
    需要了解图像处理的人. 图像处理及时同一片我无是异常熟稔,
    相关的文献为是看得云里雾里的. 所以, 依然采取开源的轮:<a
    href=”https://github.com/BradLarson/GPUImage"&gt; GPUImage
    </a>. 这个开源框架来近1.3W+star(7月5日数码), 真不是坐之,
    内置125种滤镜效果, 没有您不意, 只有你无见面为此.
    我之类型被都出详尽的用法, 还是大简单的.
    在此间摘抄一份其.h文件的注释. 一方面有利于大家修改我种受到的美颜功能,
    另一方面也是召开个备份.(具体产生处于自己真正忘了, 如果有人找到了源地址链接,
    可以联系自身长)

#import "GLProgram.h"

// Base classes
#import "GPUImageOpenGLESContext.h"
#import "GPUImageOutput.h"
#import "GPUImageView.h"
#import "GPUImageVideoCamera.h"
#import "GPUImageStillCamera.h"
#import "GPUImageMovie.h"
#import "GPUImagePicture.h"
#import "GPUImageRawDataInput.h"
#import "GPUImageRawDataOutput.h"
#import "GPUImageMovieWriter.h"
#import "GPUImageFilterPipeline.h"
#import "GPUImageTextureOutput.h"
#import "GPUImageFilterGroup.h"
#import "GPUImageTextureInput.h"
#import "GPUImageUIElement.h"
#import "GPUImageBuffer.h"

// Filters
#import "GPUImageFilter.h"
#import "GPUImageTwoInputFilter.h"


#pragma mark - 调整颜色 Handle Color

#import "GPUImageBrightnessFilter.h"                //亮度
#import "GPUImageExposureFilter.h"                  //曝光
#import "GPUImageContrastFilter.h"                  //对比度
#import "GPUImageSaturationFilter.h"                //饱和度
#import "GPUImageGammaFilter.h"                     //伽马线
#import "GPUImageColorInvertFilter.h"               //反色
#import "GPUImageSepiaFilter.h"                     //褐色(怀旧)
#import "GPUImageLevelsFilter.h"                    //色阶
#import "GPUImageGrayscaleFilter.h"                 //灰度
#import "GPUImageHistogramFilter.h"                 //色彩直方图,显示在图片上
#import "GPUImageHistogramGenerator.h"              //色彩直方图
#import "GPUImageRGBFilter.h"                       //RGB
#import "GPUImageToneCurveFilter.h"                 //色调曲线
#import "GPUImageMonochromeFilter.h"                //单色
#import "GPUImageOpacityFilter.h"                   //不透明度
#import "GPUImageHighlightShadowFilter.h"           //提亮阴影
#import "GPUImageFalseColorFilter.h"                //色彩替换(替换亮部和暗部色彩)
#import "GPUImageHueFilter.h"                       //色度
#import "GPUImageChromaKeyFilter.h"                 //色度键
#import "GPUImageWhiteBalanceFilter.h"              //白平横
#import "GPUImageAverageColor.h"                    //像素平均色值
#import "GPUImageSolidColorGenerator.h"             //纯色
#import "GPUImageLuminosity.h"                      //亮度平均
#import "GPUImageAverageLuminanceThresholdFilter.h" //像素色值亮度平均,图像黑白(有类似漫画效果)

#import "GPUImageLookupFilter.h"                    //lookup 色彩调整
#import "GPUImageAmatorkaFilter.h"                  //Amatorka lookup
#import "GPUImageMissEtikateFilter.h"               //MissEtikate lookup
#import "GPUImageSoftEleganceFilter.h"              //SoftElegance lookup




#pragma mark - 图像处理 Handle Image

#import "GPUImageCrosshairGenerator.h"              //十字
#import "GPUImageLineGenerator.h"                   //线条

#import "GPUImageTransformFilter.h"                 //形状变化
#import "GPUImageCropFilter.h"                      //剪裁
#import "GPUImageSharpenFilter.h"                   //锐化
#import "GPUImageUnsharpMaskFilter.h"               //反遮罩锐化

#import "GPUImageFastBlurFilter.h"                  //模糊
#import "GPUImageGaussianBlurFilter.h"              //高斯模糊
#import "GPUImageGaussianSelectiveBlurFilter.h"     //高斯模糊,选择部分清晰
#import "GPUImageBoxBlurFilter.h"                   //盒状模糊
#import "GPUImageTiltShiftFilter.h"                 //条纹模糊,中间清晰,上下两端模糊
#import "GPUImageMedianFilter.h"                    //中间值,有种稍微模糊边缘的效果
#import "GPUImageBilateralFilter.h"                 //双边模糊
#import "GPUImageErosionFilter.h"                   //侵蚀边缘模糊,变黑白
#import "GPUImageRGBErosionFilter.h"                //RGB侵蚀边缘模糊,有色彩
#import "GPUImageDilationFilter.h"                  //扩展边缘模糊,变黑白
#import "GPUImageRGBDilationFilter.h"               //RGB扩展边缘模糊,有色彩
#import "GPUImageOpeningFilter.h"                   //黑白色调模糊
#import "GPUImageRGBOpeningFilter.h"                //彩色模糊
#import "GPUImageClosingFilter.h"                   //黑白色调模糊,暗色会被提亮
#import "GPUImageRGBClosingFilter.h"                //彩色模糊,暗色会被提亮
#import "GPUImageLanczosResamplingFilter.h"         //Lanczos重取样,模糊效果
#import "GPUImageNonMaximumSuppressionFilter.h"     //非最大抑制,只显示亮度最高的像素,其他为黑
#import "GPUImageThresholdedNonMaximumSuppressionFilter.h" //与上相比,像素丢失更多

#import "GPUImageSobelEdgeDetectionFilter.h"        //Sobel边缘检测算法(白边,黑内容,有点漫画的反色效果)
#import "GPUImageCannyEdgeDetectionFilter.h"        //Canny边缘检测算法(比上更强烈的黑白对比度)
#import "GPUImageThresholdEdgeDetectionFilter.h"    //阈值边缘检测(效果与上差别不大)
#import "GPUImagePrewittEdgeDetectionFilter.h"      //普瑞维特(Prewitt)边缘检测(效果与Sobel差不多,貌似更平滑)
#import "GPUImageXYDerivativeFilter.h"              //XYDerivative边缘检测,画面以蓝色为主,绿色为边缘,带彩色
#import "GPUImageHarrisCornerDetectionFilter.h"     //Harris角点检测,会有绿色小十字显示在图片角点处
#import "GPUImageNobleCornerDetectionFilter.h"      //Noble角点检测,检测点更多
#import "GPUImageShiTomasiFeatureDetectionFilter.h" //ShiTomasi角点检测,与上差别不大
#import "GPUImageMotionDetector.h"                  //动作检测
#import "GPUImageHoughTransformLineDetector.h"      //线条检测
#import "GPUImageParallelCoordinateLineTransformFilter.h" //平行线检测

#import "GPUImageLocalBinaryPatternFilter.h"        //图像黑白化,并有大量噪点

#import "GPUImageLowPassFilter.h"                   //用于图像加亮
#import "GPUImageHighPassFilter.h"                  //图像低于某值时显示为黑


#pragma mark - 视觉效果 Visual Effect

#import "GPUImageSketchFilter.h"                    //素描
#import "GPUImageThresholdSketchFilter.h"           //阀值素描,形成有噪点的素描
#import "GPUImageToonFilter.h"                      //卡通效果(黑色粗线描边)
#import "GPUImageSmoothToonFilter.h"                //相比上面的效果更细腻,上面是粗旷的画风
#import "GPUImageKuwaharaFilter.h"                  //桑原(Kuwahara)滤波,水粉画的模糊效果;处理时间比较长,慎用

#import "GPUImageMosaicFilter.h"                    //黑白马赛克
#import "GPUImagePixellateFilter.h"                 //像素化
#import "GPUImagePolarPixellateFilter.h"            //同心圆像素化
#import "GPUImageCrosshatchFilter.h"                //交叉线阴影,形成黑白网状画面
#import "GPUImageColorPackingFilter.h"              //色彩丢失,模糊(类似监控摄像效果)

#import "GPUImageVignetteFilter.h"                  //晕影,形成黑色圆形边缘,突出中间图像的效果
#import "GPUImageSwirlFilter.h"                     //漩涡,中间形成卷曲的画面
#import "GPUImageBulgeDistortionFilter.h"           //凸起失真,鱼眼效果
#import "GPUImagePinchDistortionFilter.h"           //收缩失真,凹面镜
#import "GPUImageStretchDistortionFilter.h"         //伸展失真,哈哈镜
#import "GPUImageGlassSphereFilter.h"               //水晶球效果
#import "GPUImageSphereRefractionFilter.h"          //球形折射,图形倒立

#import "GPUImagePosterizeFilter.h"                 //色调分离,形成噪点效果
#import "GPUImageCGAColorspaceFilter.h"             //CGA色彩滤镜,形成黑、浅蓝、紫色块的画面
#import "GPUImagePerlinNoiseFilter.h"               //柏林噪点,花边噪点
#import "GPUImage3x3ConvolutionFilter.h"            //3x3卷积,高亮大色块变黑,加亮边缘、线条等
#import "GPUImageEmbossFilter.h"                    //浮雕效果,带有点3d的感觉
#import "GPUImagePolkaDotFilter.h"                  //像素圆点花样
#import "GPUImageHalftoneFilter.h"                  //点染,图像黑白化,由黑点构成原图的大致图形


#pragma mark - 混合模式 Blend

#import "GPUImageMultiplyBlendFilter.h"             //通常用于创建阴影和深度效果
#import "GPUImageNormalBlendFilter.h"               //正常
#import "GPUImageAlphaBlendFilter.h"                //透明混合,通常用于在背景上应用前景的透明度
#import "GPUImageDissolveBlendFilter.h"             //溶解
#import "GPUImageOverlayBlendFilter.h"              //叠加,通常用于创建阴影效果
#import "GPUImageDarkenBlendFilter.h"               //加深混合,通常用于重叠类型
#import "GPUImageLightenBlendFilter.h"              //减淡混合,通常用于重叠类型
#import "GPUImageSourceOverBlendFilter.h"           //源混合
#import "GPUImageColorBurnBlendFilter.h"            //色彩加深混合
#import "GPUImageColorDodgeBlendFilter.h"           //色彩减淡混合
#import "GPUImageScreenBlendFilter.h"               //屏幕包裹,通常用于创建亮点和镜头眩光
#import "GPUImageExclusionBlendFilter.h"            //排除混合
#import "GPUImageDifferenceBlendFilter.h"           //差异混合,通常用于创建更多变动的颜色
#import "GPUImageSubtractBlendFilter.h"             //差值混合,通常用于创建两个图像之间的动画变暗模糊效果
#import "GPUImageHardLightBlendFilter.h"            //强光混合,通常用于创建阴影效果
#import "GPUImageSoftLightBlendFilter.h"            //柔光混合
#import "GPUImageChromaKeyBlendFilter.h"            //色度键混合
#import "GPUImageMaskFilter.h"                      //遮罩混合
#import "GPUImageHazeFilter.h"                      //朦胧加暗
#import "GPUImageLuminanceThresholdFilter.h"        //亮度阈
#import "GPUImageAdaptiveThresholdFilter.h"         //自适应阈值
#import "GPUImageAddBlendFilter.h"                  //通常用于创建两个图像之间的动画变亮模糊效果
#import "GPUImageDivideBlendFilter.h"               //通常用于创建两个图像之间的动画变暗模糊效果


#pragma mark - 尚不清楚
#import "GPUImageJFAVoroniFilter.h"
#import "GPUImageVoroniConsumerFilter.h"
  • tip8: H264硬编码
    如若采取<a
    href=”https://github.com/Bilibili/ijkplayer"&gt;ijkplayer
    </a>使用硬解码, 一句代码即可.

// 开启硬解码
[option setPlayerOptionValue:@"1" forKey:@"videotoolbox"];

硬编码的采用场景: 我们而拿主播的视频数据传送给服务器

通过拍摄头来采访图像,然后将征集到之图像,通过硬编码的不二法门开展编码,最后编码后的多寡以其成成H264之码流通过网络盛传。

摄像头采集图像, iOS系统提供了AVCaptureSession来集摄像头的图像数据.
项目受到自己是直接利用<a
href=”https://github.com/BradLarson/GPUImage"&gt; GPUImage
</a>中的GPUImageVideoCamera,
直接设置GPUImageVideoCamera的代理即可,
在该代理方- (void)willOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer;进行数据编码即可.

记住一点:
不管是系统自带的AVCaptureSession还是GPUImageVideoCamera采访到的数额还是免经过编码的CMSampleBuffer.

接下来拿收集到之数据, 用iOS开放的VideoToolbox展开硬编码.
关于VideoToolbox硬编解码网上广大课程, 当然最好是看Apple的合法文档,
如果只是硬编码, 看我之花色就可.

重点之编码函数(来自YOLO直播负责人的开源项目<a
href=”https://github.com/Guikunzhi/BeautifyFaceDemo"&gt;
BeautifyFaceDemo </a>)

void didCompressH264(void *outputCallbackRefCon, void *sourceFrameRefCon, OSStatus status, VTEncodeInfoFlags infoFlags,
                     CMSampleBufferRef sampleBuffer )
{
    if (status != 0) return;
    // 采集的未编码数据是否准备好
    if (!CMSampleBufferDataIsReady(sampleBuffer))
    {
        NSLog(@"didCompressH264 data is not ready ");
        return;
    }
    ALinH264Encoder* encoder = (__bridge ALinH264Encoder*)outputCallbackRefCon;

    bool keyframe = !CFDictionaryContainsKey((CFArrayGetValueAtIndex(CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, true), 0)), kCMSampleAttachmentKey_NotSync);

    if (keyframe) // 关键帧
    {
        CMFormatDescriptionRef format = CMSampleBufferGetFormatDescription(sampleBuffer);
        size_t sparameterSetSize, sparameterSetCount;
        const uint8_t *sparameterSet;
        OSStatus statusCode = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(format, 0, &sparameterSet, &sparameterSetSize, &sparameterSetCount, 0 );
        if (statusCode == noErr)
        {
            size_t pparameterSetSize, pparameterSetCount;
            const uint8_t *pparameterSet;
            OSStatus statusCode = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(format, 1, &pparameterSet, &pparameterSetSize, &pparameterSetCount, 0 );
            if (statusCode == noErr)
            {
                encoder->sps = [NSData dataWithBytes:sparameterSet length:sparameterSetSize];
                encoder->pps = [NSData dataWithBytes:pparameterSet length:pparameterSetSize];
                NSLog(@"sps:%@ , pps:%@", encoder->sps, encoder->pps);
            }
        }
    }

    CMBlockBufferRef dataBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
    size_t length, totalLength;
    char *dataPointer;
    OSStatus statusCodeRet = CMBlockBufferGetDataPointer(dataBuffer, 0, &length, &totalLength, &dataPointer);
    if (statusCodeRet == noErr) {

        size_t bufferOffset = 0;
        static const int AVCCHeaderLength = 4;
        while (bufferOffset < totalLength - AVCCHeaderLength)
        {
            uint32_t NALUnitLength = 0;
            memcpy(&NALUnitLength, dataPointer + bufferOffset, AVCCHeaderLength);
            NALUnitLength = CFSwapInt32BigToHost(NALUnitLength);
            NSData *data = [[NSData alloc] initWithBytes:(dataPointer + bufferOffset + AVCCHeaderLength) length:NALUnitLength];
            bufferOffset += AVCCHeaderLength + NALUnitLength;
            NSLog(@"sendData-->> %@ %lu", data, bufferOffset);
        }

    }

}

感触

则这项目是独山寨的, 高仿的, 但是仍已经特别巨大了.
具体的底细要得大家好失去看本身的项目源码.
短短几千许还当真说不清这么多的学识点. blog的文章名字说了是初窥,
还确实只是初窥, 视频直播间的坑太多. 且行且珍惜…

tip: 本文理论知识部分, 采集自网络.
请牢记一句话talk is cheap show me the code, 重点在于Demo色本身.
理论有自己只是一个挑夫和总结者…

种编译环境

Xcode7(及以上)
最为是拿项目走在真机上. 有些地方模拟器是未支持的, 也看不到任何效果的,
比如硬编码/智能美颜等, 这些功能模块, 我举行了限制的, 需要真机状态才会进行.

花色下载地址

<a
href=”https://github.com/SunLiner/MiaowShow"&gt;GitHub下载地址&lt;/a&gt;
恳请star和fork. 后续的bug会持续更新到github上之.
起题目得以以简书给自己留言/私信, 或者微博(简书个人及篇页有自家之微博)私信我.

7月9日凌晨更新: 项目曾经集成视频直播推流
blog地址详解<a
href=”http://www.jianshu.com/p/8ea016b2720e"&gt;快速集成iOS基于RTMP的视频推流&lt;/a&gt;

联系我

<a href=”https://github.com/SunLiner"&gt;github&lt;/a&gt;

<a
href=”http://www.weibo.com/5589163526/profile?rightmod=1&wvr=6&mod=personinfo&is\_all=1"&gt;微博&lt;/a&gt;

<a
href=”http://www.jianshu.com/users/9723687edfb5/latest\_articles"&gt;简书&lt;/a&gt;

Swift

Swift iOS : 字体图标

厌倦了以位图在xcode的Assets.xcassets内,因为辛苦,包括如下的累:
找图 图要分尺寸 需要操作员类似工作去管理
然后,现在产生矣字图标,就有益多了: 比较成熟之几仿照库,用名字就可查
矢量图,尺寸无极缩放,想只要多大都行 都以代码和字体文件内,不需要以工程…

Swift iOS :
Archive


Archive 想拿目标序列化到文件,可以率先使这个目标符合 NSCoding
协议,然后以归档类完成序列化。 如下案例,可以管目标 User
序列化到文件内: import UIKit @UIApplicationMain class AppDelegate:
UIResponder…

Swift iOS :
创建一个POD


广告 Swift iOS开发小书 ,帮你飞上手开发
http://www.ituring.com.cn/book/2413
正文
你创造了一个迷幻的View,想要为海内外共享它。怎么惩罚?cocoapods可以帮。
##创立一个工程,其中起若得分享的代码 首先,我们创建这样的…

Swift iOS :
定制Cell


TableViewCell提供了样定制的恐怕,包括textLabel,detailLabel,各种访问附件等。但是急需死记硬背,何必为,反正一个连续了UITableViewCell的子类,然后在其外进入自己之定制View其实并无复杂,并且动用了平的在subView的方案。因…

Swift iOS :
显示SVG文件的法子


SVG文件是矢量图标准有,特点是足以缩放,并且可以用足翻阅之源代码的道(而休是二进制)来存储图形信息。比如如下文件就是一个svg文件:
<svg xmlns=”http://www.w3.org/2000/svg” viewBox=”0 0 350 100″>
<defs>…

Swift iOS :
在webview的脚下网页上提信息的不二法门


广告 Swift iOS开发小书 ,帮你快上手开发
http://epub.ituring.com.cn/946
正文
使用UIWebView装载一个网页后,可能得领取其外之信息,比较好的主意是以JavaScript。方法UIWebView.stringByEvaluati…

最小的Swift
App


哪通过通过纯粹的代码,而休依赖让Xcode的StoryBoard,来形成一个App?
首先举行些操作性的干活,具体经过是这般的: 打开xcode 创建一个Single View
App
Xcode会进入重点编辑界面。此时,我们开辟AppDelegate.swift文件然后盖源…

Swift iOS :
CocoaPods


CocoaPods是一个iOS项目之借助管理器,使用它可于导入第三方库和处理依赖关系转移得简单。
出于测试和说明的目的,这里会创一个Swift工程,并运用CocoaPods导入第三正在HTTP库alamofire。
准备CocoaPods CocoaPods需要系统外既设置了…

Swift iOS : StackView
详解


StackView
有那么些布局好行使横向布局与纵向布局来组合得,此种植情形下,可以用
UIStackView 来简化创建布局。 假设我们怀念如果横向布局 3
只标签,标签内来边距的话,可以这么: import UIKit @UIApplicationMain
class AppDel…

Swift iOS :
解决了一个信托不做事之动静


每当解决一个遗产代码的过程中,我希望对UIAlertView稍作封装,以便从英雄的ViewController内分离有特定的AlertView的代码,我这么做的:
import UIKit @UIApplicationMain class AppDelegate: UIRespon…

Swift iOS :
RichText


咱常常见到简单平实的公文显示,然后真的可以透过 RichText
来好增长文本的外观,增强界面的表达力。 UILabel 等零件,除了 text
属性外,还有 attributedText 属性,通过构建 NSAttributedString
的实例,并赋值给此属性,就得设置 RichTex…

Swift iOS :
YYText计算文字占用高度


动用动态文字填充UITableViewCell内容时,需要算文字占用高度,以便告知UITableViewCell的行高。使用YYText的YYTextLayout可以帮成功这点。
如下案例,简单封装了YYTextLayout,并通过简单只案例调用,演示其的做法:
import…

Swift iOS :
CocoaPods


CocoaPods是iOS最常用最出名的框架依赖管理工具。但是采取过程吧是凭空的波折的,because
I Love China。 首先你用ruby环境。 $ruby -v ruby 2.0.0p648 (2015-12-16
revision 53162) [unive…

Swift iOS :
使用Cartography布局


广告 Swift iOS开发小书 ,帮你飞上手开发
http://www.ituring.com.cn/book/2413
正文
使用SnapKit布局当然对,但是本人觉得Cartography更好,因为可以形容来更为规整的布局代码。表达式总是比由链式函数容易看。
依然是布局三…

Swift iOS
:我之及时5个月之习过程


2015年,我吗失去看了下objc,第一感到蛮不好,C语言和objc的壮大在同,特别乱,当时感:
都是函数,C的函数和objc的函数创建和利用差别大充分,并且混合在一起
objc函数带在参数标签的,函数增长之受不了
即使是第一步最为小的app,也得询问设计模式,它同样开始就登台,叫做…

Swift iOS :
本地化


随即首文章大概是当下而得看来底最好简便的本地化教程。 广告 Swift
iOS开发小书 ,帮您快速上手开发
http://epub.ituring.com.cn/946
目标
本地化的意思,在于iOS切换不同语言时,App可以会同改变,用指定的语言展示应用。iOS提供了一如既往法用来国际…

Swift iOS : attributedText
富文本操作


广告 Swift iOS开发小书 ,帮你快上手开发
http://www.ituring.com.cn/book/2413
正文
通常被UILabel设置文本,我们都是安装属性UILabel.text。这代表显示的文书是纯的,整个文件只能发出同样种同等的公文效果。而另外一个特性…

Swift iOS :
tintColor


每当iOS
7后,UIView新增加了一个tintColor属性,这个特性表示的是“色调”,一旦设置颜色为其,那么这个视图为根视图的所有视图层次组织还见面被改动颜色。从而得以不必一一赋值就足以当视图系统内取得一致的颜色体系。
如下代码当点击RUN按钮时,整个以self.view为根视…

Swift iOS:AutoLayout
快速介绍


AutoLayout
典型的,加入一个子视图的做法尽管是创造实例,指定位置,然后把它们在到视图里面来。在指定位置的代码处,一般就是设置
frame 属性即可,就比如这样: import UIKit @UIApplicationMain class
AppDelegate: UIResp…

Swift
iOS:SnapKit


iOS默认提供的布局技术强大使愚蠢。幸好有一个封装的包SnapKit,可以为布局变得易看与改动。
假若是要当一个UIViewController上布局两个label,要求是:
第一个label的xy距离父视图为5,100 第二只label
的x距离第一只label为10,高度…

Swift iOS :
一个简陋的TableView封装


UITableView功能强大,但是下delegate设计模式的DataSource真的可怜无痛快。比如说:
一堆冗长的函数签名 只能拷贝,错一点都心有余而力不足执行之,也无见面提醒您免针对
冗长的函数签名是这般的: func numberOfSections(in: UITableView…

Swift_iOS:
扫描二维码的措施


足以AVFoundation框架来启动相机扫描二维码,把一个二维码转换为一个字符串。
如下应用,进入首页看到一个按钮和一个标签。点按钮的讲话,会沾一不好扫描,把围观到之亚维码转换为字符串后,会显得在标签内。代码如下:
import UIKit @UIApplicationMai…

Swift iOS :
访问于签署证书https服务器


做客HTTPS服务器时,可以下由签定证书之、在该地的https服务器,对于调试应用是特别有益之。
Apple已经于iOS
9版本要求得采用https。如果https服务器是CA签署之关系,那么共同不通,如果是自签约证书,就需要做简单独附加的工作:
在info.plist内投入…

Swift iOS :
内置的下拉刷新


本着TableView,下拉刷新新的数码是好有利的。iOS内置有一个下拉刷新控件UIRefreshControl,虽然非可知开上拉刷新,但是盖用简单,倒也值得介绍。
如下代码,使用TableView加载OS列表,每次下拉,都学刷新一久新的OS项目:
import UIKit @…

Swift iOS :
闭包之一个施用


本人读一个开源代码的经过中,常常发现发这般的结构: var textLabel:UILabel
= { let label = UILabel() label.backgroundColor = .red return label
}()功能会编译,能够运转,因此语法当然是指向之…

Swift iOS :
装入webview时,如何为图片都展示在屏幕外


webview装入的网页,常常发生宽度比较的图,这些图会超出手机的大幅度,因此造成显示不完全。
比如如下案例,加入了点儿个图片,大小分别吗: 650×300 150×150每当iPhone
SE的模拟器下,默认情况下,前一张图会在宽达超过,后同张可显得完整。
import UIKit…

Swift
iOS:KVO


KVO是Key Value
Observer的缩写,可以用于监视一个目标的属于性值变化,然后实施一个代码块(块、函数、闭包等)。Facebook开源了一个KVO框架,KVOController。
这个案例用KVOController,用于App主题改变通知。通过KVO监视主题的…

Swift iOS :
剿除编译耦合的同一种植办法


俺们常常会待拿多独类耦合在一起以便共同完成一个或者千篇一律组功能。但是同时为象征中单独的切近为依靠了别的切近,当给转换至个中工程被即使会无法无法编译通过,更加谈不上运行了。比如如下的案例之几个像样就是了的贴合在一起:
import UIKit @UIApplicationMain…

Swift iOS :
如果Cell内部有webview怎么打适应吗


Cell高度自适应的题材的确多。现在,如果内部生webView,内容动态装入,大小为是各不相同的,并且高度要根据内容,而休是view本身的冲天来适应,怎么收拾也?特别是如发生多单webView的景象下。
这样即便好了: import UIKit @UIApplicationMain…

Swift iOS :
上拉刷新或者下拉刷新


框架 MJRefresh 提供了上拉刷新或者下拉刷新,非常的喜闻乐见。 需要采取
pod: target ‘Swift-MJrefresh’ do use_frameworks! # Pods for
Swift-MJrefresh pod ‘MJRefresh’ end 记得去履行命…

Swift iOS : 解析 ISO8601
日期字符串的法子


日子时时不时要以字符串形式打包到JSON内,常用之字符串格式为ISO8601,格式卡起是这样的:
“2016-06-05T16:56:57.019+01:00″解析其的要紧,是采取DateFormater的当儿,写好格式化字符串,内容吗:
dateFormatter.date…

Swift iOS : self sized
cell


根据Cell内的情节,动态调整Cell高度,是常用的技巧。在iOS 8
还是以上之版内,这个技能不再要协调计算行高,而是变得简单至极。
如下案例,假而一个Cell内发生少独Label,其中一个单行,第二单多尽,根据第二单Label的情节之不同,高度也会见不同,这个高度的变换死,会导…

Swift iOS :
自动闭包autoclosure


一般来说为合法文档的定义,但是建议乃不经意她,搞明白了电动闭包再来拘禁才便于了解:)
自动闭包是一样栽电动创建的闭包,用于包装传递让函数作为参数的表达式。这种闭包不受任何参数,当它们被调
用的当儿,会回到给包在里的表达式的值。这种便宜语法让您可知省略闭包的花括号,用一个平凡的表达式
来代替…

Swift iOS :
创建一个framework


Swift支持代码按物理模块分割组织,分而治之。其中的一个做法即是当您的工程中行使framework。
本文创建一个太简易framework。 首先创建一个framework工程。步骤为:
创建工程 选择iOS | Framework & Library | Cocoa Tou…

Swift iOS :
模糊化


iOS的模糊化,会被界面很炫酷,用了非可知终止。本案例用了FXBlurView,对图片进行模糊处理。
使用Pod文件: target ‘five’ do use_frameworks! pod ‘FXBlurView’, ‘~>
1.6.4’ end然后施行pod install…

Swift iOS : 访问 https
服务器


采用 URLSession 可以拜 https 服务器。为了测试好,省下团结编写 https
服务器的累,可以利用一个网络服务叫做 httpbin.org/ip, 当访问子 URL
时,它会回一个 json,格式为: {origin = “221.237.156.243”;} 访问
http…

Swift 访问
sqlite,最抢之左侧案例


足行使 sqlite 作为关系数据库来囤积 iOS 本地数据。这象征,通过 sql
语言方便之召开多少的增删改查。 sqlite 本身提供了 C 语言的 API,使用 Swift
访问需要 创建一个桥接文件,引入 C API,访问 SQLite 数据库需要动用 SQLite
官方提供的 C 语言风格的 API,所以…

Swift iOS :
plist


plist
plist是一个XML的子集,使用UTF-8编码的公文文件,它的彻底节点是一个字典,内容由多独主键和价值构成。常常为此来囤App的布局信息。
可以一直动用NSDictionary类直接存储它们的情节及plist内,比如这样: import
UIKit @UIApplica…

Swift iOS : cnodejs api
测试


cnodejs允许以她提供的api来出客户端。并且提供了文档。为了测试与验证api,可以应用curl命令来做此事。有矣这些命令集合,开发以及研讨api变得越来越爱。如下就是这些可以实施之文档。
发布主题: curl –data “tab=dev&title=title&con…

Swift iOS :
解析json


卓越的前台后台的竞相操作,几乎都是这么的: 访问后台服务API
然后分析其回到的JSON
使用Alamofire,它的扩大AlamofireObjectMapper可以把HTTP访问获得的结果转换为json对象,使用ObjectMapper可以管json对象同swift对象做一个…

Swift iOS :
编译器的智能


广告 Swift iOS 小书
http://www.ituring.com.cn/book/2413
正文
编辑代码时,不小心将错了,却意外的发现,这样的代码是得编译通过和运作的:
@UIApplicationMain class AppDelegate: UIRespon…

Swift iOS :
YYText显示微博@文字的法门


广告 Swift iOS开发小书 ,帮你飞上手开发
http://www.ituring.com.cn/book/2413
正文
第三正库YYText可以好富文本的输入,如果要创造类似微博@一样的输入UI,可以采用它们的YYTextView组件。具体说:
当内容中起@打头的文…

Swift iOS :
KeyChain


广告 Swift iOS开发小书 ,帮您快速上手开发
http://www.ituring.com.cn/book/2413
正文
KeyChain提供了加密囤积敏感信息之法门。所谓的敏锐性信息,不外是密码,信用卡号等。如果一个目标涵盖敏感信息,也足以管方方面面对象序列化为Data,然…

Swift iOS :
WebView缓存图片的计


广告 Swift iOS开发小书 ,帮您飞上手开发
http://www.ituring.com.cn/book/2413
正文
每次加载WebView内容,如果图片可以缓存的话,速度就会见非常急匆匆。默认情况下,WebView自己来加载图片,缓存的政策也是祥和得的。如想使团结缓存的…

Swift iOS : Core
Data


Core Data是法定对Sqlite访问的包装框架。使用其的补益是: 不待协调引入Sqlite动态库和创建桥接文件 不需利用SQL语言即可访问Sqlite 使用其的重要性需求是引入其,像是这般: import CoreData依然要我们的题材是储存todo项目,字段…

Swift iOS :
#selector


始终版的Swift(小于2.2),想如果被Button一个轩然大波的言语,需要为此到Selector函数,像是如此:
import UIKit @UIApplicationMain class AppDelegate: UIResponder,
UIApplicationDelegate …

Swift iOS :
扩展类的特性


extension可以吗接近添加新的计,但是如果想只要增补加多少成员的语就是见面叫阻挡,比如如下代码:
extension Foo { var _title: String? var title: String? { get { return
_title } set { _title …

Swift iOS :
根据情节调整Cell高度的方法


偶然,需要动态调整UITableView的Cell高度,比如其中有一个TextView,内容由用户决定,可长可短的情形下,肯定是盼Cell和TextView可以展示全部内容,因此也得Cell高度为随即一起越强了。
如下代码,展示一个长变化的TextView,当内容变更时…

Swift iOS :
NotificationCenter


好像NotificationCenter提供了同等种植轻耦合的消息传递机制。可以发起一个通报,在差不多地处监听是通知。比如说一个App的主题样式被改动,就好由此此类来通知多独相关UI,做响应的处理。
如下案例显示了这种可能: import UIKit @UIApplicationMain …

Swift iOS: View
详解


View 视图类 UIView
定义了一个矩形区域,并且管理这用户界面内之互动。视图可以管理子视图,全部子视图和自视图一起,构成一个层次化的视图树。
我们就一个案例,代码可以创造两只 50
见方的矩形,它们并清除在一道,并且还有第三单视图,它放在第二单视图内。三只视图的背景色分别吗…

详解 View
Controller



UIViewController,它叫称呼视图控制器,被用来装和假释视图、管理视图交互、并且与另外视图控制器一起合作完成整体的
App 界面。为了术语一致,后文会直接行使其的英文称:View Controller。 View
Controller 管理一个视图层级体系。比如在一个…

Node.js: 一个正够用用之 HTTPS
服务器


奇迹,需要创造一个https服务器,以便测试用。使用node.js完成此项工作还是比较简单的。另外,为了可以创造https,需要openssl工具栈。
首先创建证书: openssl genrsa -out key.pem openssl req -new -key key…

git : 修正HEAD
detached状态


奇迹发现时代码修改的歇斯底里了,想要温故知新至前面数版本,多次checkout查找合适版本时,会发觉眼前处在这样的状态;
(HEAD detached from
REVISION-ID)如果这召开了改,那么得动用如下命令合并修改到主分支: git
branch temp git c…

Swift iOS : @escaping
属性


以闭包,有有限栽情景,一种植是在调用者完成前闭包就吃实施好了。还有一样栽则相反:调用函数完成了,但是闭包还并未吃调用或者没吃成功。后者叫喻为逃逸闭包。
所有网络要的函数,在形成调用请求后,直到响应返回,闭包才会被调用,所以是类别的网要求函数内等待响应的闭包就是奔闭包。这…

Swift iOS :
内存管理


Swift 是活动管理内存的。这象征,你免欲积极释放内存。 比如 Foo
内涵盖的 Bar,可以会同 Foo 一起被放走: import UIKit @UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDele…

Swift iOS :
抽屉效果


足以DrawerController框架实现抽屉的效用。看起或蛮帅气的。
需要开的即是一个DrawerController,3个ViewController。3个ViewController分别用于左侧的抽屉,当前之斗,右侧的斗。DrawerController用来…

个人档案iOS视频直播初窥:高仿<喵播APP>

效果图

gif1

gif2

由于licecap录制的GIF失帧太严重, 都模糊掉了, 再推广少摆放高清截图

png1

png2

前言

现年三月份,斗鱼腾讯领投的1亿美元融资的音信给各国大平台报道转载,在电竞、泛娱乐已是热门投资之就,网络直播平台自为抱了各界的关心。盗用两摆有关游戏直播的动向图

娱直播规模

打闹直播规模

立还只是游戏直播这块的蛋糕.直播行的竞争会越来越猛烈,
不管是主播还是直播平台都面临着熊熊的竞争, 当然直播行也罢会更规范,
直播元素也越来越多.

视频直播初窥

视频直播,可以分成 采集,前处理,编码,传输, 服务器处理,解码,渲染

  • 募集: iOS系统因为软硬件种类不多, 硬件适配性比较好, 所以比较简单.
    而Android端市面上机型众多, 要召开来机型的适配工作.PC端是极度累的,
    各种奇葩摄影头驱动.所以现在广大之中小型直播平台, 都放弃了PC的直播,
    更有一部分直播平台就做iOS端的视频直播.

  • 前面处理: 美颜算法,视频的混淆效果, 水印等都是于斯环节做.
    目前iOS端最资深开源框架的得就是GPUImage.其中坐了125种渲染效果,
    还支持各种本子自定义. 我高仿的喵播的美颜功效啊是冲GPUImage的.

  • 编码:
    重难点在要于分辨率,帧率,码率,GOP等参数设计上找到最佳平衡点。iOS8随后,
    Apple开放了VideoToolbox.framework, 可以一直开展硬编解码,
    这也是胡现在大部分直播平台最低单支持及iOS8之因由之一.
    iOS端硬件兼容性比较好, 可以一直动用硬编码.
    而Android得硬编码又是一模一样良坑.

  • 传: 这块一般都是付出CDN服务商.
    CDN才供带宽和服务器之间的传,
    发送端和接受端的网络连接抖动缓存还是如自己实现之.目前国内最为要命的CDN服务商应该是网宿.

  • 服务器处理: 需要以服务器做有注处理工作,
    让推送上来的流适配各个平台各种不同之磋商, 比如:RTMP,HLS,FLV…

  • 解码和渲染: 也即即音视频的播放. 解码毫无疑问也得要硬解码.
    iOS端兼容于好, Android依然充分坑.这块的难在于音画同步,
    目前多直播平台这块是刚伤.国内比较好之开源项目应是B站开源之<a
    href=”https://github.com/Bilibili/ijkplayer"&gt;ijkplayer
    </a>. 斗鱼就是是基于<a
    href=”https://github.com/Bilibili/ijkplayer"&gt;ijkplayer
    </a>的, 本项目为是冲<a
    href=”https://github.com/Bilibili/ijkplayer"&gt;ijkplayer
    </a>的.

技巧坑 : 降噪, 音频解码器, 蓝牙适配, 回声消除, 信令控制, 登录, 鉴权,
权限管理, 状态管理, 应用信息, 消息推送, 礼物系统, 即时聊, 支付系统,
统计系统, 数据库, 缓存, 分布式文件存储, 消息队列,
运维系统等等大小不一的坑等你来填!!!

成本坑 : 以带动富为例, 2万口同时在线, 手机码率在600KB,
每个月的带动富费用至少在30万左右. 冲欢聚时代(YY)15年四季度财务报,
他们的带富成本也人民币1.611亿首批, 折合每月5000万+.
人力成本+渠道支出和其他支出就一无所知谈了.

社会坑: 还得天天与各种黑暗势力斗争, 包括韵, 广告, 刷小号,
刷充值, 告侵权, DDos…(我反而编译喵播的官方APP,
他们之项目名为就是吃Shehui, O(∩_∩)O哈哈~)

路下载地址

<a
href=”https://github.com/SunLiner/MiaowShow"&gt;GitHub下载地址&lt;/a&gt;

初期准备

型重要是冲<a
href=”https://github.com/Bilibili/ijkplayer"&gt;ijkplayer </a>的.
最好是打包改成framework. 原本自己准备写一个卷入教程,
不了后来于简书上发现了同等首特别详细的自包blog, 分享给大家: <a
href=”http://www.jianshu.com/p/1f06b27b3ac0"&gt;http://www.jianshu.com/p/1f06b27b3ac0&lt;/a&gt;.

假如你根据教程打包失败了(当然这种概率比较小),
我及时还有同客本身就由包好之(Release版), 下充斥地址:
链接:http://pan.baidu.com/s/1eRVetdK
密码:2dc0
下载后, 直接解压即可.

项目文件结构

  • Frameworks: 如果文件夹不在, 点击classes选择Show in Finder,
    新建一个即可, 将你于包之或下载的framework拖入其中并累及上路中.
    你啊得协调建一个文书夹, 把这Frameworks直接delete即可

  • Profile : 个人基本, 这中独自出一个ProfileController.
    因为总写重复代码, 都写吐了, 这儿来趣味之祥和写一下咔嚓, So easy…

  • Network : 关于网络连接的工具类. 关于网络的实时监督, 网络状态的切换,
    网络请求的工具类都在此地面.

  • Other : 全局的常量. 当然你为堪当里面将文件结构更为细化.

  • Home : 包含最新主播, 最暖直播, 关注的直播, 礼物排行榜等模块.
    还有无限重大的视频直播呢在这中了.

  • ShowTime :见名知意. 视频直播的前面处理,
    智能美颜和H264硬编码等还在此地面.

  • Main : UITabBarControllerUINavigationController的配置

  • Toos : 这儿命名有点不正规, 这其间放的且是路因此到的分类

  • Login : 登录模块

  • Resource : 项目因此到的资源文件

类型详解

  • tip1: 判读网络类型.

在看直播的时候, 我们日常都是故WiFi或者3/4G(土豪级别的),
一般用户以展开网络切换的当儿, 我们还如被起友善的唤醒, 告诉TA:
您的纱状态切换到了XX状态. 假设用户从WiFi切换到4G,
你的利用也远非个提醒, 导致TA的流量归零甚至不够了运营商一屁股的钱,
我思念你的APP的用户体验吧就算归零或者也负了.

咱俩可下苹果的Reachability成下面的代码实时监听网络状态的转移

typedef NS_ENUM(NSUInteger, NetworkStates) {
    NetworkStatesNone, // 没有网络
    NetworkStates2G, // 2G
    NetworkStates3G, // 3G
    NetworkStates4G, // 4G
    NetworkStatesWIFI // WIFI
};

// 判断网络类型
+ (NetworkStates)getNetworkStates
{
    NSArray *subviews = [[[[UIApplication sharedApplication] valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];
    // 保存网络状态
    NetworkStates states = NetworkStatesNone;
    for (id child in subviews) {
        if ([child isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) {
            //获取到状态栏码
            int networkType = [[child valueForKeyPath:@"dataNetworkType"] intValue];
            switch (networkType) {
                case 0:
                   //无网模式
                    states = NetworkStatesNone;
                    break;
                case 1:
                    states = NetworkStates2G;
                    break;
                case 2:
                    states = NetworkStates3G;
                    break;
                case 3:
                    states = NetworkStates4G;
                    break;
                case 5:
                {
                    states = NetworkStatesWIFI;
                }
                    break;
                default:
                    break;
            }
        }
    }
    //根据状态选择
    return states;
}
  • tip2: 登录模块

倘您差不多运行几潮就见面发觉,
登录模块背景被播放的视频是2个视频每次随机播放一个底.并且是极致重复的,
也就是说只要您一直发呆在登录界面, 就会见单视频循环播放时底观望频.
这儿的报到就是几乎单按钮, 没有现实的记名逻辑,
随便点哪一个按钮都足以进来首页.

咱得监听视频, 是否播放完成.

// 监听视频是否播放完成
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didFinish) name:IJKMPMoviePlayerPlaybackDidFinishNotification object:nil];

假定播放完成了, 让IJKFFMoviePlayerController再次play即可

- (void)didFinish
{
    // 播放完之后, 继续重播
    [self.player play];
}
  • tip3: 首页

首页

这种意义相信广大人还看看过或者举行过.我简单说一样下自家的做法(不自然是顶尖的,
只是提供一个思路)

一个父控制器HomeViewController+三独子控制器(最热/最新/关注.
每个控制器各自管理自己的事务逻辑, 高内集聚低耦合).
重写HomeViewControllerloadView,
self.view替换成UIScrollView.
将三独子控制器的view添加到UIScrollView上即可. 其他的功力实现,
请参照我之代码, 都生详细的国语注释.

  • tip4: 直播(面向观众捧)
    以此是一切项目的显要之一了.这种直播的布局, 应该是比主流的了.
    我下载的众直播类APP都是是项目布局,
    包括YY也是这种界面布局.这个里面涉及的东西比多矣, 三言两语真说不清.

简简单单说一下就实现的效能:
A: 主播的直播
B: 关联主播的视频直播, 默认是特生界面, 没有动静之.
点击该视图可以切换到之主播
C: 下拉切换其他一个主播, 这个职能是大广阔的.
做法是直播控制器是一个UICollectionViewController, 只出一个cell,
cell.frame就是self.collectionViewb.bounds.
我们登直播控制器的时光, 其实是传染进一个关乎主播数组,
每次下拉的上, 就加载数组里面的主播
D. 查看观众席的观众详情
E. 查看主播详情
F. 足迹: 粒子动画, 后面详解
G. 弹幕: 点击最下方的工具栏第一个按钮可以打开/关闭弹幕, 后面详解

  • tip5: 粒子动画实现游客足迹
    粒子动画的layer是长到播放器的view上面的. 下面代码有详尽的诠释

CAEmitterLayer *emitterLayer = [CAEmitterLayer layer];
// 发射器在xy平面的中心位置
emitterLayer.emitterPosition = CGPointMake(self.moviePlayer.view.frame.size.width-50,self.moviePlayer.view.frame.size.height-50);
// 发射器的尺寸大小
emitterLayer.emitterSize = CGSizeMake(20, 20);
// 渲染模式
emitterLayer.renderMode = kCAEmitterLayerUnordered;
// 开启三维效果
//    _emitterLayer.preservesDepth = YES;
NSMutableArray *array = [NSMutableArray array];
// 创建粒子
for (int i = 0; i<10; i++) {
    // 发射单元
    CAEmitterCell *stepCell = [CAEmitterCell emitterCell];
    // 粒子的创建速率,默认为1/s
    stepCell.birthRate = 1;
    // 粒子存活时间
    stepCell.lifetime = arc4random_uniform(4) + 1;
    // 粒子的生存时间容差
    stepCell.lifetimeRange = 1.5;
    // 颜色
    // fire.color=[[UIColor colorWithRed:0.8 green:0.4 blue:0.2 alpha:0.1]CGColor];
    UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"good%d_30x30", i]];
    // 粒子显示的内容
    stepCell.contents = (id)[image CGImage];
    // 粒子的名字
    //            [fire setName:@"step%d", i];
    // 粒子的运动速度
    stepCell.velocity = arc4random_uniform(100) + 100;
    // 粒子速度的容差
    stepCell.velocityRange = 80;
    // 粒子在xy平面的发射角度
    stepCell.emissionLongitude = M_PI+M_PI_2;;
    // 粒子发射角度的容差
    stepCell.emissionRange = M_PI_2/6;
    // 缩放比例
    stepCell.scale = 0.3;
    [array addObject:stepCell];
}

emitterLayer.emitterCells = array;
[self.moviePlayer.view.layer insertSublayer:emitterLayer below:self.catEarView.layer];
  • tip6: 弹幕
    弹幕使用的吗是一个老三方轮子<a
    href=”https://github.com/unash/BarrageRenderer"&gt;BarrageRenderer
    </a>. 这个开源项目的文档都是华语的, 用法也是深粗略的.

    着力配置

 _renderer = [[BarrageRenderer alloc] init];
// 设置弹幕的显示区域. 基于父控件的.
_renderer.canvasMargin = UIEdgeInsetsMake(ALinScreenHeight * 0.3, 10, 10, 10);
[self.contentView addSubview:_renderer.view];

弹幕配置

#pragma mark - 弹幕描述符生产方法
/// 生成精灵描述 - 过场文字弹幕
- (BarrageDescriptor *)walkTextSpriteDescriptorWithDirection:(NSInteger)direction
{
    BarrageDescriptor * descriptor = [[BarrageDescriptor alloc]init];
    descriptor.spriteName = NSStringFromClass([BarrageWalkTextSprite class]);
    descriptor.params[@"text"] = self.danMuText[arc4random_uniform((uint32_t)self.danMuText.count)];
    descriptor.params[@"textColor"] = Color(arc4random_uniform(256), arc4random_uniform(256), arc4random_uniform(256));
    descriptor.params[@"speed"] = @(100 * (double)random()/RAND_MAX+50);
    descriptor.params[@"direction"] = @(direction);
    descriptor.params[@"clickAction"] = ^{
        UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"弹幕被点击" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:nil];
        [alertView show];
    };
    return descriptor;
}

终极一步, 千万要记得start

[_renderer start];
  • tip7: 智能美颜功效
    现行底直播平台, 美颜是标配.
    不然绝大多数的主播都是无奈看的.美颜算法需要为此到GPU编程,
    需要了解图像处理的人. 图像处理这同样块我非是十分熟悉,
    相关的文献也是圈得云里雾里的. 所以, 依然以开源之车轱辘:<a
    href=”https://github.com/BradLarson/GPUImage"&gt; GPUImage
    </a>. 这个开源框架来濒临1.3W+star(7月5日多少), 真不是盖之,
    内置125种滤镜效果, 没有你不意, 只有你无会见用.
    我的门类个人档案面临还起详实的用法, 还是雅简单的.
    在这里摘抄一份其.h文件之注释. 一方面有利于大家修改我种中的美颜功效,
    另一方面也是做个备份.(具体产生处于自己真正忘了, 如果有人找到了源地址链接,
    可以沟通自己长)

#import "GLProgram.h"

// Base classes
#import "GPUImageOpenGLESContext.h"
#import "GPUImageOutput.h"
#import "GPUImageView.h"
#import "GPUImageVideoCamera.h"
#import "GPUImageStillCamera.h"
#import "GPUImageMovie.h"
#import "GPUImagePicture.h"
#import "GPUImageRawDataInput.h"
#import "GPUImageRawDataOutput.h"
#import "GPUImageMovieWriter.h"
#import "GPUImageFilterPipeline.h"
#import "GPUImageTextureOutput.h"
#import "GPUImageFilterGroup.h"
#import "GPUImageTextureInput.h"
#import "GPUImageUIElement.h"
#import "GPUImageBuffer.h"

// Filters
#import "GPUImageFilter.h"
#import "GPUImageTwoInputFilter.h"


#pragma mark - 调整颜色 Handle Color

#import "GPUImageBrightnessFilter.h"                //亮度
#import "GPUImageExposureFilter.h"                  //曝光
#import "GPUImageContrastFilter.h"                  //对比度
#import "GPUImageSaturationFilter.h"                //饱和度
#import "GPUImageGammaFilter.h"                     //伽马线
#import "GPUImageColorInvertFilter.h"               //反色
#import "GPUImageSepiaFilter.h"                     //褐色(怀旧)
#import "GPUImageLevelsFilter.h"                    //色阶
#import "GPUImageGrayscaleFilter.h"                 //灰度
#import "GPUImageHistogramFilter.h"                 //色彩直方图,显示在图片上
#import "GPUImageHistogramGenerator.h"              //色彩直方图
#import "GPUImageRGBFilter.h"                       //RGB
#import "GPUImageToneCurveFilter.h"                 //色调曲线
#import "GPUImageMonochromeFilter.h"                //单色
#import "GPUImageOpacityFilter.h"                   //不透明度
#import "GPUImageHighlightShadowFilter.h"           //提亮阴影
#import "GPUImageFalseColorFilter.h"                //色彩替换(替换亮部和暗部色彩)
#import "GPUImageHueFilter.h"                       //色度
#import "GPUImageChromaKeyFilter.h"                 //色度键
#import "GPUImageWhiteBalanceFilter.h"              //白平横
#import "GPUImageAverageColor.h"                    //像素平均色值
#import "GPUImageSolidColorGenerator.h"             //纯色
#import "GPUImageLuminosity.h"                      //亮度平均
#import "GPUImageAverageLuminanceThresholdFilter.h" //像素色值亮度平均,图像黑白(有类似漫画效果)

#import "GPUImageLookupFilter.h"                    //lookup 色彩调整
#import "GPUImageAmatorkaFilter.h"                  //Amatorka lookup
#import "GPUImageMissEtikateFilter.h"               //MissEtikate lookup
#import "GPUImageSoftEleganceFilter.h"              //SoftElegance lookup




#pragma mark - 图像处理 Handle Image

#import "GPUImageCrosshairGenerator.h"              //十字
#import "GPUImageLineGenerator.h"                   //线条

#import "GPUImageTransformFilter.h"                 //形状变化
#import "GPUImageCropFilter.h"                      //剪裁
#import "GPUImageSharpenFilter.h"                   //锐化
#import "GPUImageUnsharpMaskFilter.h"               //反遮罩锐化

#import "GPUImageFastBlurFilter.h"                  //模糊
#import "GPUImageGaussianBlurFilter.h"              //高斯模糊
#import "GPUImageGaussianSelectiveBlurFilter.h"     //高斯模糊,选择部分清晰
#import "GPUImageBoxBlurFilter.h"                   //盒状模糊
#import "GPUImageTiltShiftFilter.h"                 //条纹模糊,中间清晰,上下两端模糊
#import "GPUImageMedianFilter.h"                    //中间值,有种稍微模糊边缘的效果
#import "GPUImageBilateralFilter.h"                 //双边模糊
#import "GPUImageErosionFilter.h"                   //侵蚀边缘模糊,变黑白
#import "GPUImageRGBErosionFilter.h"                //RGB侵蚀边缘模糊,有色彩
#import "GPUImageDilationFilter.h"                  //扩展边缘模糊,变黑白
#import "GPUImageRGBDilationFilter.h"               //RGB扩展边缘模糊,有色彩
#import "GPUImageOpeningFilter.h"                   //黑白色调模糊
#import "GPUImageRGBOpeningFilter.h"                //彩色模糊
#import "GPUImageClosingFilter.h"                   //黑白色调模糊,暗色会被提亮
#import "GPUImageRGBClosingFilter.h"                //彩色模糊,暗色会被提亮
#import "GPUImageLanczosResamplingFilter.h"         //Lanczos重取样,模糊效果
#import "GPUImageNonMaximumSuppressionFilter.h"     //非最大抑制,只显示亮度最高的像素,其他为黑
#import "GPUImageThresholdedNonMaximumSuppressionFilter.h" //与上相比,像素丢失更多

#import "GPUImageSobelEdgeDetectionFilter.h"        //Sobel边缘检测算法(白边,黑内容,有点漫画的反色效果)
#import "GPUImageCannyEdgeDetectionFilter.h"        //Canny边缘检测算法(比上更强烈的黑白对比度)
#import "GPUImageThresholdEdgeDetectionFilter.h"    //阈值边缘检测(效果与上差别不大)
#import "GPUImagePrewittEdgeDetectionFilter.h"      //普瑞维特(Prewitt)边缘检测(效果与Sobel差不多,貌似更平滑)
#import "GPUImageXYDerivativeFilter.h"              //XYDerivative边缘检测,画面以蓝色为主,绿色为边缘,带彩色
#import "GPUImageHarrisCornerDetectionFilter.h"     //Harris角点检测,会有绿色小十字显示在图片角点处
#import "GPUImageNobleCornerDetectionFilter.h"      //Noble角点检测,检测点更多
#import "GPUImageShiTomasiFeatureDetectionFilter.h" //ShiTomasi角点检测,与上差别不大
#import "GPUImageMotionDetector.h"                  //动作检测
#import "GPUImageHoughTransformLineDetector.h"      //线条检测
#import "GPUImageParallelCoordinateLineTransformFilter.h" //平行线检测

#import "GPUImageLocalBinaryPatternFilter.h"        //图像黑白化,并有大量噪点

#import "GPUImageLowPassFilter.h"                   //用于图像加亮
#import "GPUImageHighPassFilter.h"                  //图像低于某值时显示为黑


#pragma mark - 视觉效果 Visual Effect

#import "GPUImageSketchFilter.h"                    //素描
#import "GPUImageThresholdSketchFilter.h"           //阀值素描,形成有噪点的素描
#import "GPUImageToonFilter.h"                      //卡通效果(黑色粗线描边)
#import "GPUImageSmoothToonFilter.h"                //相比上面的效果更细腻,上面是粗旷的画风
#import "GPUImageKuwaharaFilter.h"                  //桑原(Kuwahara)滤波,水粉画的模糊效果;处理时间比较长,慎用

#import "GPUImageMosaicFilter.h"                    //黑白马赛克
#import "GPUImagePixellateFilter.h"                 //像素化
#import "GPUImagePolarPixellateFilter.h"            //同心圆像素化
#import "GPUImageCrosshatchFilter.h"                //交叉线阴影,形成黑白网状画面
#import "GPUImageColorPackingFilter.h"              //色彩丢失,模糊(类似监控摄像效果)

#import "GPUImageVignetteFilter.h"                  //晕影,形成黑色圆形边缘,突出中间图像的效果
#import "GPUImageSwirlFilter.h"                     //漩涡,中间形成卷曲的画面
#import "GPUImageBulgeDistortionFilter.h"           //凸起失真,鱼眼效果
#import "GPUImagePinchDistortionFilter.h"           //收缩失真,凹面镜
#import "GPUImageStretchDistortionFilter.h"         //伸展失真,哈哈镜
#import "GPUImageGlassSphereFilter.h"               //水晶球效果
#import "GPUImageSphereRefractionFilter.h"          //球形折射,图形倒立

#import "GPUImagePosterizeFilter.h"                 //色调分离,形成噪点效果
#import "GPUImageCGAColorspaceFilter.h"             //CGA色彩滤镜,形成黑、浅蓝、紫色块的画面
#import "GPUImagePerlinNoiseFilter.h"               //柏林噪点,花边噪点
#import "GPUImage3x3ConvolutionFilter.h"            //3x3卷积,高亮大色块变黑,加亮边缘、线条等
#import "GPUImageEmbossFilter.h"                    //浮雕效果,带有点3d的感觉
#import "GPUImagePolkaDotFilter.h"                  //像素圆点花样
#import "GPUImageHalftoneFilter.h"                  //点染,图像黑白化,由黑点构成原图的大致图形


#pragma mark - 混合模式 Blend

#import "GPUImageMultiplyBlendFilter.h"             //通常用于创建阴影和深度效果
#import "GPUImageNormalBlendFilter.h"               //正常
#import "GPUImageAlphaBlendFilter.h"                //透明混合,通常用于在背景上应用前景的透明度
#import "GPUImageDissolveBlendFilter.h"             //溶解
#import "GPUImageOverlayBlendFilter.h"              //叠加,通常用于创建阴影效果
#import "GPUImageDarkenBlendFilter.h"               //加深混合,通常用于重叠类型
#import "GPUImageLightenBlendFilter.h"              //减淡混合,通常用于重叠类型
#import "GPUImageSourceOverBlendFilter.h"           //源混合
#import "GPUImageColorBurnBlendFilter.h"            //色彩加深混合
#import "GPUImageColorDodgeBlendFilter.h"           //色彩减淡混合
#import "GPUImageScreenBlendFilter.h"               //屏幕包裹,通常用于创建亮点和镜头眩光
#import "GPUImageExclusionBlendFilter.h"            //排除混合
#import "GPUImageDifferenceBlendFilter.h"           //差异混合,通常用于创建更多变动的颜色
#import "GPUImageSubtractBlendFilter.h"             //差值混合,通常用于创建两个图像之间的动画变暗模糊效果
#import "GPUImageHardLightBlendFilter.h"            //强光混合,通常用于创建阴影效果
#import "GPUImageSoftLightBlendFilter.h"            //柔光混合
#import "GPUImageChromaKeyBlendFilter.h"            //色度键混合
#import "GPUImageMaskFilter.h"                      //遮罩混合
#import "GPUImageHazeFilter.h"                      //朦胧加暗
#import "GPUImageLuminanceThresholdFilter.h"        //亮度阈
#import "GPUImageAdaptiveThresholdFilter.h"         //自适应阈值
#import "GPUImageAddBlendFilter.h"                  //通常用于创建两个图像之间的动画变亮模糊效果
#import "GPUImageDivideBlendFilter.h"               //通常用于创建两个图像之间的动画变暗模糊效果


#pragma mark - 尚不清楚
#import "GPUImageJFAVoroniFilter.h"
#import "GPUImageVoroniConsumerFilter.h"
  • tip8: H264硬编码
    如果运用<a
    href=”https://github.com/Bilibili/ijkplayer"&gt;ijkplayer
    </a>使用硬解码, 一句代码即可.

// 开启硬解码
[option setPlayerOptionValue:@"1" forKey:@"videotoolbox"];

硬编码的利用场景: 我们而拿主播的视频数据传送给服务器

经拍摄头来采访图像,然后拿集到的图像,通过硬编码的道进行编码,最后编码后的数量以那个构成成H264底码流通过网络流传。

摄像头采集图像, iOS系统提供了AVCaptureSession来收集摄像头的图像数据.
项目中自我是直接使用<a
href=”https://github.com/BradLarson/GPUImage"&gt; GPUImage
</a>中的GPUImageVideoCamera,
直接设置GPUImageVideoCamera的代理即可,
在该摄方- (void)willOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer;展开数据编码即可.

记住一点:
不管是系自带的AVCaptureSession还是GPUImageVideoCamera采访到的数目还是休经过编码的CMSampleBuffer.

接下来以集到之多少, 用iOS开放之VideoToolbox展开硬编码.
关于VideoToolbox硬编解码网上广大课程, 当然最是看Apple的合法文档,
如果只是硬编码, 看自己之路就是可.

关键的编码函数(来自YOLO直播负责人的开源项目<a
href=”https://github.com/Guikunzhi/BeautifyFaceDemo"&gt;
BeautifyFaceDemo </a>)

void didCompressH264(void *outputCallbackRefCon, void *sourceFrameRefCon, OSStatus status, VTEncodeInfoFlags infoFlags,
                     CMSampleBufferRef sampleBuffer )
{
    if (status != 0) return;
    // 采集的未编码数据是否准备好
    if (!CMSampleBufferDataIsReady(sampleBuffer))
    {
        NSLog(@"didCompressH264 data is not ready ");
        return;
    }
    ALinH264Encoder* encoder = (__bridge ALinH264Encoder*)outputCallbackRefCon;

    bool keyframe = !CFDictionaryContainsKey((CFArrayGetValueAtIndex(CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, true), 0)), kCMSampleAttachmentKey_NotSync);

    if (keyframe) // 关键帧
    {
        CMFormatDescriptionRef format = CMSampleBufferGetFormatDescription(sampleBuffer);
        size_t sparameterSetSize, sparameterSetCount;
        const uint8_t *sparameterSet;
        OSStatus statusCode = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(format, 0, &sparameterSet, &sparameterSetSize, &sparameterSetCount, 0 );
        if (statusCode == noErr)
        {
            size_t pparameterSetSize, pparameterSetCount;
            const uint8_t *pparameterSet;
            OSStatus statusCode = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(format, 1, &pparameterSet, &pparameterSetSize, &pparameterSetCount, 0 );
            if (statusCode == noErr)
            {
                encoder->sps = [NSData dataWithBytes:sparameterSet length:sparameterSetSize];
                encoder->pps = [NSData dataWithBytes:pparameterSet length:pparameterSetSize];
                NSLog(@"sps:%@ , pps:%@", encoder->sps, encoder->pps);
            }
        }
    }

    CMBlockBufferRef dataBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
    size_t length, totalLength;
    char *dataPointer;
    OSStatus statusCodeRet = CMBlockBufferGetDataPointer(dataBuffer, 0, &length, &totalLength, &dataPointer);
    if (statusCodeRet == noErr) {

        size_t bufferOffset = 0;
        static const int AVCCHeaderLength = 4;
        while (bufferOffset < totalLength - AVCCHeaderLength)
        {
            uint32_t NALUnitLength = 0;
            memcpy(&NALUnitLength, dataPointer + bufferOffset, AVCCHeaderLength);
            NALUnitLength = CFSwapInt32BigToHost(NALUnitLength);
            NSData *data = [[NSData alloc] initWithBytes:(dataPointer + bufferOffset + AVCCHeaderLength) length:NALUnitLength];
            bufferOffset += AVCCHeaderLength + NALUnitLength;
            NSLog(@"sendData-->> %@ %lu", data, bufferOffset);
        }

    }

}

感触

虽然这类型是只山寨的, 高仿的, 但是还是已经不行巨大了.
具体的细节要需要大家温馨去押自己的品种源码.
短短几千许还真说不清这么多之学问点. blog的文章名字说了凡初窥,
还确确实实只是初窥, 视频直播中的坑太多. 且行且珍惜…

tip: 本文理论知识部分, 采集自网络.
请记住一句子话talk is cheap show me the code, 重点在于Demo类型本身.
理论有自己只是一个搬运工和总结者…

项目编译环境

Xcode7(及以上)
极端是拿项目走在真机上. 有些地方模拟器是休支持的, 也看不到任何意义的,
比如硬编码/智能美颜等, 这些功能模块, 我开了限定的, 需要真机状态才会向前行.

型下载地址

<a
href=”https://github.com/SunLiner/MiaowShow"&gt;GitHub下载地址&lt;/a&gt;
央star和fork. 后续之bug会持续创新到github上的.
来问题得以在简书给本人留言/私信, 或者微博(简书个人及篇页有自家的微博)私信我.

7月9日凌晨翻新: 项目曾经集成视频直播推流
blog地址详解<a
href=”http://www.jianshu.com/p/8ea016b2720e"&gt;快速集成iOS基于RTMP的视频推流&lt;/a&gt;

联系我

<a href=”https://github.com/SunLiner"&gt;github&lt;/a&gt;

<a
href=”http://www.weibo.com/5589163526/profile?rightmod=1&wvr=6&mod=personinfo&is\_all=1"&gt;微博&lt;/a&gt;

<a
href=”http://www.jianshu.com/users/9723687edfb5/latest\_articles"&gt;简书&lt;/a&gt;

频频集成 — 理论篇

相同、软件开发面临的题材

  • 规定软件需要
  • 确定项目进度(可见性)
  • 争以极抢速度将软件提交给用户?
  • 什么样被开发、测试、产品经营、运维人员迅速工作?

软件需要满足于工作目的,质量无对等完美,“追求面面俱到是将作业做好的冤家”。

第二、持续集成

络绎不绝集成是一样栽软件开发实践【不是工具】,即组织出成员经常集成他们之做事,通常每个成员每天起码集成一不成。每次集成都经过自动化的构建(包括编译,发布,自动化测试)来证实,从而尽快地窥见并错误。
— Martin Fowler

络绎不绝集成

其三、持续集成的值

1.协作

为开发之软件直接处于可工作状态

2.开发人员

  • 赶快发现问题
    解决问题之重大是快发现题目
    调减引入缺陷以及修复缺陷之间的日子

  • 防分支大幅偏离主干

  • 压缩重复过程&人为不当:
    以自动化编译、发布、测试…,代替手工操作
    避了一部分人工的不当(build号忘加1、Debug开关忘关)

  • 确立集体对出产品的信念

3. 测试人员

粗步增量,易于发现题目,并飞速反馈给开发人员

四、小结

合并的目的其实是维系:集成可以让开发者告诉其他人他们都改了哟东西,频繁之沟通好于开发者重新快地打听变化。

五、持续集成的前提条件

1.团队共识

络绎不绝集成不是工具,是千篇一律种植实施,需要投入并遵照一些条条框框,才会提高质量

2.反复提交

“如果您遇上相同桩好惨痛之事体,似乎较好的建议就是重频繁地做这桩业务”
— Martin Fowler
哲学:一宗业务很麻烦,又不能不去做,不妨经常去开,每次做一点,分而治之,滴水穿石、跬步千里
—— 早集成、常集成
釜底抽薪问题之首要是尽早发现问题
各级过几只钟头即付一赖,冲突为会见当几乎独钟头之内吃发现
少不行提交之间就来几乎独小时的改,产生这些题材无非或以充分单薄的几乎单地方
提交的更多,需要找冲突错误的地方就更是少,改起也更快
就此异样调试比较时本与事先未曾 bug 的本
理所当然上会鼓励开发者将工作分解变成因为时计之有些片

3. 确保每次交的品质

每次交的本都出或发一个但发布的本子
老是交的质不好,不但会潜移默化好,而且会影响别人

4.不单单源代码

以及品类有关的有内容(代码、测试代码、数据库脚本、构建和配置脚本、
IDE配置文件,以及有着用于创造、安装、运行、测试应用程序的物)
至于这点,可以参见频频集成的“Everything is
code”

5. 两全的自动化构建、测试套件

  • 10分钟 build(快速的build)
    从来不啊比较缓慢的 build 更会损害不止集成移动
    倘付出 build 成功,其他人就得放心地基于这些代码工作了
  • 在不同之情形被 build 不同的 target
  • 每次代码提交后都见面以连集成服务器上触一不好构建
    构建不单独是编译,可能包含编译、测试、审查与布局及另外一些业务,将代码放在一块儿,并被那得以看做一个一致的单元运行的经过
  • 自动化专业
    任何人都应有力所能及于一个绝望之电脑达 check out
    源代码,然后敲入一条命令,就好拿走能当即时令机器及运行的网

6. 本地环境暨不断集成环境、测试环境、生产条件一致

deployment-plan.gif

至于环境而参看:Traditional Development/Integration/Staging/Production
Practice for Software
Development

六、必要之执行

1.“最新的不易版本”作为起点

2.时刻准备回滚到前面一个本

3.修复破坏应用程序的轻易修改是参天优先级的任务

10分钟修复不结,需要回滚&在回滚之前如果确定一个修复时

4. 等交测试通过后再累做事

叫好喝相同盏咖啡的流年
待集成返回结果后连续工作会压缩不当,也会被他人当新型的正确性版本作为起点

5.提及前当地方运行具有的付测试

当代CI服务器提供“预测试提交”、“个人构建”

6.构建失败后并非交新代码

7.谁提交,谁负责

蹲点 mainline 上之构建,失败时马上修复
倘当收工前交给了代码,那在 mainline 构建成功之前即非克回家

8.勿将砸的测试注释掉

修改代码、修改测试、删除测试

9.测试驱动开发

七、 持续集成实践步骤

1.自动化构建
2.引入自动化测试

试试着指出要出错的地方,并使受自动化测试暴露这些不当

3.试着加速build 的进度

10分钟build

4.CI选型

https://github.com/ligurio/Continuous-Integration-services/blob/master/continuous-integration-services-list.md

5.寻寻找老车手拉(很重大)

总司机理论+实践经验丰富

详见

https://github.com/CatchZeng/ContinuousIntegration

个人档案Clean Code 告诉您呀是好代码

前言

近年来在社实施Code
Review,遇到一个嫌恶的题材。当朝同伴的代码提一个comment时,他们不为人知为何用如此改。细细想来,是他们不知道何为好代码,也非明了自己之代码有哪些
“坏味道”。因此,分享了几期待Clean Code,团队受益良多,故成为此文。

Clean Code

鉴于Clean Code篇幅较丰富,故先配备如下我道较为关键之几接触:

  • 命名
  • 函数(方法)
  • 注释
  • 靶、数据结构

命名

命名有众多规则,但总起来就是 “有意义” 才是强项道理。

名副其实

Int d;//逝去的时间

旋即句代码的题目在d没有发表好逝去的光阴之定义,故待注释。请牢记“名副其实就不需要注释”

Int elapsedTime;

复来拘禁个例证

哪位还深麻烦猜出其含义,看看小优化后的结果

骨干看清了意思,这虽是命名的机要。细心的情人还会见发现及时段代码的一些瑕疵
:这里的4是呀鬼?习惯性我们无她为“魔法数字”

要么觉得有些问题,再优化

相对而言下最早的代码,相信您晤面起发了。

免误导

生活被的场面为常并发于Code中,看下图,你的Code是否为出现这么的窘迫也?那便Make
it clean

是否傻傻分不到底了呢? 再来个

accountList

自我了解乃想说,这有啊问题。是的,如果你莫是做Java开发,不见面知道链表叫List,所以只要您切莫是因此链表存储account,请不要因此其编制饰,或许这时节你用acountGroup会更好把。
该点需要以具体支出条件下因地制宜

出义的界别

Product
ProductInfo
ProductData

可以想象下,当一个类别被还要起上述三单近乎的时刻,你是如何区分开的,反正我是不曾此能力。类似的还有

game
theGame

name
nameString

享受时,伙伴说nameString有啊问题。我反问说难道你的名字会是Float型的?你知道了吧。

前缀

m_desc

有人提出加m前缀表示该变量为私有变量。
自身怀念说:你的变量很多?需要区分私有的还是国有的?如果您的变量很多,那就算设琢磨是未是从未有过计划好类,没有如约纯净任务规范,另外私有和国有变量编译器会赞助高亮显示区分的,不待自己来分(若某些编译器无此特性,怪编译器去)。

命名惯性

取名需要看重词性
类名:名词 or 名词短语
措施名: 动词 or 动词短语

每个概念对应一个词

以一个模块中不要用简单个一般的定义来表达不同的操作。我于平等份代码中看到过一个看似吃以起以下三个词打头的主意

fetch
get
retrieve

试问那个才是确实获取值的章程?我实际分不干净。

采用世界名称

运用领域命名能于小伙伴重新亮你的程序结构(关于领域是定义,不熟识的得看下一本书叫
《领域让设计》,俗称DDD)
推个例子,比如你用访问者模式来构建用户系统,那么

AccountVisitor

便显示明确、易懂

对抗缩写诱惑

缩写需要小心,适当的缩写是可的,但是倘若保证缩写后的辞藻仍然会表达其本意。举个有意思的事例

ABCDEFG

立即为是个缩写,但是乍看这个真不知道是什么的缩写,直接宣布答案吧

小结

取名是一定的难题,我领几独建议吧

  • 大抵扣开源代码,积累好的用词
  • 勿知晓的词就是翻下词典,好了您自己想的
  • 举行只自己的开源项目,让旁人吃您建议
  • 搞好积累、再累、还是积累

有的借鉴词

函数(方法)

函数的首先修规则是要少小,第二久规则还是如欠小。

短小

那么到底多短合适呢?历史上出现了几只专业

  • 一屏
  • 100行
  • 50行
  • 20行
    有人提问我干什么会不同这么多,我之答是:以前的屏幕分辨率那么小,一屏为就是20-50尽期间吧,所以以前一屏的说法呢是合情之。
    对此行数,行业没有一个永恒的业内。我所掌握的Oracle建议是50执行,Bob大叔的建议是20实施。

代码短小,好处自然很多。

  • 单元测试覆盖率高
  • 每个函数一目了然,只做同宗事
  • 方便函数中之代码都以跟一个空洞层级

只开相同码事

函数应该举行同样起事。做好当下桩事。只做一样桩事。
那怎样判定单独做同项事?

请问这个函数做了几码事?伙伴的答案是

1.判断是否为测试页面
2.加入测试数据
3.渲染页面

你的答案是稍微为?其实答案是单做了扳平项事,主要是未曾扣留清
一样码事 OR 一码事的大多独步骤,关于这点,大家如果可以体会。

除此以外一个断定是否仅仅做同样件事的好方法: 是否能重新分离有新函数

以及一个虚幻层级

关于层级,比较难以讲明,直接扣例子吧

再也看一个版本

公会发觉看第二个版本的代码,明显舒服多。因为第二底本子的老三句子代码都当与一个层级。而首先个本子的代码中之率先句是安装roundView的某某属性,但是最终一句子也是于装bubbleView,层级不同(roundView与bubbleView才是和层级)

运描述性名称

如加上一些之名目可以进一步分明,不要犹豫,用清晰的吧(注意是如生义的)

calculate
calculatePrice

相对而言起来calculatePrice就好过多。
复来拘禁个例

addComment
addCommentAndReturnCount

君免是说长一些再次清晰吧,那addCommentAndReturnCount很好吧。
有关这点大家而专注,如果您需要因此and、or之类的介词来编排辞函数时,要考虑下而是不是违背了十足任务规范

参数个数

0个最好,
1个次之,
2个还行,
3单以上不是太好了。
参数与函数称为在不同的抽象层级,它要求您必须了解时连无特别重大的细节。
解决办法有许多,比如一些场景可利用DTO

嵌套层次、分支过多

嵌套、分支过多会于代码变得甚为难掌握,解决的办法来如下:

  • 卫语句
  • do-while,引入break
  • if-else if-then
  • 领函数
  • 以子类取代类型代码
  • 坐多态取代条件式

  • 实际但因项目特点选用

划分指令和查询

set这个函数很无引人注目的是究竟是安成了归来true,还是名字存回true,但确确实实的题材在于,它是单指令但是掺杂了询问的效应。

拿查询及指令分离后,代码便清晰很多了。

小结

什么勾勒有好之函数

  • 预先勾勒对的,再写好之
  • 对 =》 单元测试 =》识别坏味道 =》重构

注释

“别为糟糕的代码加注 — 重新勾吧。” –Brian & P.J.
“注释总是一样种植失败” –Bob

为此代码来阐述

感受两段落代码会发觉代码即注释的美

坏注释

事先来探啊是老之诠释

喃喃自语

立注绝对是被好扣之

余下的笺注

说跟没解释一样,不如代码来之简单明了

误导性的注解

若当误导吧

循规式注释

其一肯定要是注意,循环式的诠释了多余(除了做sdk、开源)

括号后的笺注

如果括号后需要注释,只表明你及时段代码太丰富了,需要举行的莫是加注,而是将它换短。

属于签约

Git、SVN知道凡是若付出的,不用这么刷存在感

注掉代码

注解掉的代码,只见面给修改你代码的总人口蒙圈,如果您道就段代码有或后会用,也非用担心,Git、SVN会帮你找回来

信息过多

面向对象讲究,暴露操作,隐藏实现,如果您还要注释这些信,表示若没包装好。这些消息,可考虑放个链接或者其它的简短提示,太长的注解,别人懒得读、也难读懂

好注释

圈了那基本上老注释,来看看啊是好的注解

法规信息
供信息
本着意向的注释
阐释
警示
TODO注释
放大

靶、数据结构

数据抽象

将变量设置也个体(Private),主要是免思叫其他人依这些变量。所以,不要随便吃变量添加赋值方法以及取值方法(set/get方法),这样实在是把个体变量公之于广大。
隐身变量和促成,并无是以变量和外之间放一个函数层那么粗略。隐藏关乎抽象。
类似并无略地用赋值方法以及取值方法以那个变量推向外间,而是暴露抽象接口,以便用户不必了解多少的贯彻而能够操作数据本体。
一经盖什么点子展现对象所蕴藏的多寡,需要举行严肃的思量。随便加赋值方法以及取值方法,是绝深的取舍。

多少、对象的反对称性

前者是一样栽过程式代码,后者是面向对象式代码。我们会发觉只要要上加一个新形态的话,后者绝对是不错的抉择,因为以上代码都无欲修改,只需要写一个新形状类,这可“开放–封闭”原则。然而一旦添加一个计周长的作用的语句那就算杯具了,因为这样子每个形状类都得转。但是只要是因此过程式代码的语就需要加上一个初函数。

过程式代码(使用数据结构的代码)便于在非改既来数据结构的前提下上加新函数。
面向对象代码便于在未更改既来函数的前提下上加新类。
一切都是对象只是是一个风传

组织

  • 官静态变量
  • 个体静态变量
  • 民用实体变量
  • 公家函数
  • 私函数
    自到向下标准
    此处为何没有写公有实体变量是为,其无建议出现于代码中。

短小

函数的短缺小标准是行数,那类是什么吗?答案是职责
恍如需要按单纯任务规范

内聚

苟以上代码,内聚性高,除了size方法外,其他办法都以了区区单实例变量。
内聚:模块内部各个要素彼此结合的紧紧程度(类吃艺术以及变量间的三结合程度)
保持内聚会得到多不够小之近乎
当一个看似丧失内聚性时我们应有拆分它

总结

Clean
Code能帮助组织构建代码质量体系,有助于开发之各个环节(静态分析、持续集成、Code
Review…)。当然,对个人的力增强吗颇有补,建议大家都应有熟悉。等集团Code
Review一段时间后,有其他获取吧,再被大家大饱眼福。
预祝大家国庆节快乐!

iOS申请邓白氏总结-20160322

如您是设为申请公司账号只要注册得邓白氏代码,那么您用将方有填写得消息还使铭记在心,因为以提请公司账号的时候需要因此到这些,并且使同报名邓白氏所填写得消息相互抱,不然你得企业账号对不见面成功。

邓白氏编码注册连接,免费之:https://developer.apple.com/ios/enroll/dunsLookupForm.action

落得图中,出现了红的书体,因为该页面的 富有信息都需在英文键盘下输入 

(1.)选择我们所于得国家或地区,没有亮出来得可直接让他俩发邮件;

(2.)Legal Entity
Name:填写公司名字。注意:要是英文得,例如上海aaa科技公司:Shanghai aaa
technology co.,
LTD。前面xxx就算是你得企业名字,肯定是拼音,不容许您得企业名字翻译成了英语。(一般你可以寻找你们的情解决这题目)

(3.)Tradestyle or DBA:这等同牢可以不填,没有涉嫌得。(反正自己是绝非写)

上图:填写你   公司地址信息   ,可以为此拼音

(1.)Street
Address:街道(这里实在就算是事无巨细的地点了,门牌号几整治几声泪俱下几乎幢几止初几室等等,几几乎几乎几乎的)

(2.)City/Town:城市(自己查,当时自我填Chongming County)

(3.)State/Province:省/州(自己查,当时本人填Shanghai)

(4.)Postal Code:邮政编码

(5.)Phone Number:电话(能联络到总人口的手机号就是实施,可以填充老板还是人事的)

上图:填写   寄的地方,要和公司地址一样的话,可以一直选钩same ad
headquarters address

(1.)Street Address:街道

(2.)City/Town:城市

(3.)State/Province:省/州

(4.)Postal Code:邮政编码

上图:填写 申请人 的信息

(1.)Given Name:名字(我顿时将姓名写反了,应该不碍大事)

(2.)Family Name:姓

(3.)  Job Title:职称(google翻译去)

(4.)Phone Number:手机号

(5.) Work Email:邮箱(用来收取邓白氏邮件的)

最后验证码就是不说了,然后点击Continue



斯时,你闹   !!!“可能会”!!!     遭见这则的,如下图:

起了而公司地址附近的部分局,如果您选了一个,Submit高亮,一旦您点击,你的信箱就会吸纳
拖欠店铺的邓白氏码 ;如果非挑,又只有Back。。。。可能这我们注意力都以赫的地方,但是要认真看下的英文小字,想必你曾经掌握了咔嚓。重点就是是终极一实践,大致意思是:想吧卿的庄创办一个邓白氏码的话,就提交你的音信。

接下来会跻身到一个新的页面,说就发了一如既往客邮件,具体忘记了,看下英文就可知理解的。

还有  *可能会
 *遇见打了一个艳情的⚠️的页面,然后页面及还是你之前填写的信,其实就是只要而再肯定,然后交到,===这里的提交按钮和
 【上图】  的“submit your information”是一模一样的。



横1龙左右时刻邓白氏那边会给您电话进行信息审核,对方非常平易近人得姑娘,所以若也如嗲一些。呵呵!你而且邮件会收取一个十几各数,这个不是邓白氏编码,他们待大约2-4天时间才会时有发生一个邮件回复,邮件里有只9位数才是公得邓白氏编码。

根本:1.如果你不过得登记邓白氏编码,无其它用途那么没有干,到此地就早已收尾了。

2.要是您是使为申请公司账号只要注册得邓白氏代码,这就是说你要拿地方装有填写得消息人事档案都设铭记,因为以申请公司账号的当儿要用到这些,并且只要同报名邓白氏所填写写得消息相互适合,不然你得企业账号对免会见成功。而且邓白氏编码申请下来不是您就就可错过用到申请公司账号得,因为邓白氏编码用一块到苹果公司,所以当你点击申请公司账号时,在邓白氏代码个栏里会现灰色,代表还不曾一并到苹果公司,继续守候。如果没同到您苹果店你输入3不良后就会自行锁死。老记。


报名流程记录:

一.20160322:提交了上述过程的提请。

二.20160323:收到一模一样份邮件:

呼吁提交通知

大概意思是说:感谢您付出了邓白氏码的报名,在20160405面前就,或者更快。

汝报名之id:**********(无关紧要)

恐怕会见时有发生D&B公司之象征打电话联系而,会加快申请经过。

三.20160323,收到代表于来的电话机,还有雷同客邮件

对方发来的邮件

四.20160325,再次接到邮件

然,邓白氏码就曾申请到了,D-U-N-S
Number:*********不怕若公司的邓白氏码了,九各阿拉伯数字之。其他还是你付出的信。

五.20160405,我要失去申请公司关系了。有亟待之请到我的其余一样篇稿子中查看。



本身在原文上补偿加了有好撞问题之,也上了几乎碰。希望能够帮及大家,如果还发出另题目,请留言,我们共同探索。我今天正好交付申请,后续还见面更新该篇,尽量到全方位工艺流程。

转载于:http://www.cnblogs.com/hanguoqing/p/4522386.html?utm\_source=tuicool&utm\_medium=referral

啊足以参考:https://www.zhihu.com/question/29633574/answer/56724591,但是注意他管姓名写反了,我随即虽参考这的。

网站地图xml地图