随着移动互联网的发展,移动端iOS开发的技术选择也划分了好几个方向,有用 React-Native
进行开发的,有用 Objective-C
开发的,也有用 Swift
开发的,或者 混合 着来。
不同的语言存在都有其可取的优秀之处,也有不足的地方。也应了那句俗话 : 金无足赤,人无完人。
我们都知道 2014 年 Swift
的横空出世,其首要目的就是 剑指 Objective-C
。 但是现在看来也没有完全达到其问世的目的。但是大家对于 Swift 的喜爱依然是一路包容,比如从14年以来一年一学,其情况犹如一年学习一门新语言,但是 Swift
也没有让我们失望,一路高歌猛进,今年也迎来了 Swift 4
, 从这一路上来看,有一部分人好多放弃在 Swift 2.X
的路上了,一部分人没有体会到 Swift 3
到 Swift 4
的喜悦. 也有一些人始终徘徊在 Swift 的门口; 一只脚在里面,一只脚在外面。
从始至终坚持的人是抱着 “苹果(Swift)” 虐我千百遍,我待 苹果(Swift) 如初恋的执着,也正所谓: 拨开云雾见天日 守得云开见月明, 从目前来看 Swift 4 给了开发者很大的 支持与信心。
两种语言熟悉的人都知道 Objective-C
与 Swift
底层是完全不同的机制。
Objective-C
Objective-C
的那一套跑不了 运行时, 我相信 KVC
的概念在每个面试者的脑海中都能 信手拈来。
KVC, NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性。
KVO 就是基于 KVC 实现的关键技术之一以类似字典键值对的方式存储信息,以及强大的动态派发,与C
的结合.......
太多太多
Swift
Swif 这门语言是恰恰不同,其类型成员在编译的时候就已经决定,完全是一门安全性的语言。
尤其对协议的支持。比如对协议的实现有:class | struct | enum |
---|---|---|
这里不得不提到 enum
对协议的支持:
protocol Source {}enum Action: Source { case handler(sender: UIButton) case touchUp(sender: UIButton)}复制代码
由此对协议的支持可见一斑。
苹果在15年提出 Swift 的一种面向协议编程 (Protocol Oriented Programming
)
protocol Work {}extension Work { func doWork() { print("do Work") }}class action { }extension action: Work {}action().doWork()// 结果:do Work复制代码
我们看到这个 action
类,并没有对协议进行任何代码方面的书写,而通过 extension
可以直接为协议进行扩展,并给出默认实现。这对于大量重复的代码绝对是一个优秀的解决方案。
Objective-C
的时代就有 对重复代码进行封装通过继承来实现也是一种解决方案。但是这种做法是有一定的风险的. 比如通过继承的方式来:
class Action1: base1 { override func doWork() { print("do Work") }}class Action2: base1 {}Action2().doWork()// 结果:do Work复制代码
貌似结果是一样的,但是面对大量的代码的时候结构构造的好处是显而易见的,尤其是协议的扩展:根据入口提供额外实现,也可以提供默认的一个实现。往外每个类都是通过其特定的组合方式来实现不同的业务需求的,如果通过以往的继承方式构建在业务繁琐的时候是无法很好的对业务进行抽象封装了,这个时候 Swift协议就可以闪亮登场啦
其实写过 C++ 的都知道支持多继承,其带来的风险也是显而易见的:
比如:class base1 { func doWork() { print("do Work") }}class Action1: base1 { override func doWork() { print("do Work") }}class Action2: base1 { override func doWork() { print("do Work") }}Action2().doWork()class Commad: Action1,Action2 {}Commad().doWork()复制代码
这种性质的继承是致命的。当然 Swift
与 Objective-C
是不支持多继承的,所以上面代码是无效的。但是很重要的是 通过协议,并对协议进行默认实现也是可以达到异曲同工的多继承作用。
Swift 与 Objective-C 混合
上面讲过两种语言的底层是完全不同的,但是我相信混合开发的时候怎么去处理呢?
尤其是在Objective-C
代码中调用 Swift
的时候,Swift
没有运行时这种东西,而OC调用混导致异常问题。这个时候我们见到的 @objc
就挺身而出了。 @objc
只有不是继承 NSObject
的 Swift
写的 Class
的非私有类型, 在 OC
中调用的时候都是需要加上这个标志
Swift 建立模型
基于目前的习惯用到了
使用实例我相信官方介绍的比我详细,我这里就不做僭越 ?
我这里代码中放出一部分实例:class HomeModel: Mappable { var money: NSNumber = 0 // 人民币 var hlbAmnt: NSNumber = 0 // 合链币 var etcAmnt: NSNumber = 0 // 以太经典 var btcAmnt: NSNumber = 0 // 比特币 var ltcAmnt: NSNumber = 0 // 莱特币 var ethAmnt: NSNumber = 0 // 以太坊 var btcAddress: String = "" // 比特币提币地址 var btcPercent: String = "" // 比特币资产百分率 var totalMoney: NSNumber = 0 // 总资产 var etcPercent: String = "" // 以太经典的资产百分率 var moneyPercent: String = "" // RMB资产百分率 var ltcPercent: String = "" // 莱特币的资产百分率 var ethPercent: String = "" // 以太坊的资产百分率 var hlcPercent: String = "" // 合链币的资产百分率 var frozeBtcAmnt: NSNumber = 0 // 冻结的BTC 的数量 var frozeEtcaAmnt: NSNumber = 0 // 冻结的以太经典数量 var frozeHlcAmnt: NSNumber = 0 // 冻结的合链币数量 var frozeEthAmnt: NSNumber = 0 // 冻结的以太坊数量 var frozeLtcAmnt: NSNumber = 0 // 冻结的莱特币数量 var btcRate: String = "" // 比特币单价 var etcRate: String = "" // 以太经典单价 var ethRate: String = "" // 以太坊价格 var ltcRate: String = "" // 莱特币价格 var hlbRate: String = "" // 合链币价格 required init?(map: Map) { } func mapping(map: Map) { money <- map["money"] hlbAmnt <- map["hlc_amnt"] etcAmnt <- map["etc_amnt"] btcAmnt <- map["btc_amnt"] ltcAmnt <- map["ltc_amnt"] ethAmnt <- map["eth_amnt"] btcAddress <- map["btc_address"] btcPercent <- map["btc_percent"] totalMoney <- map["totalMoney"] etcPercent <- map["etcPercent"] moneyPercent <- map["money_percent"] ltcPercent <- map["ltc_percent"] ethPercent <- map["eth_percent"] hlcPercent <- map["hlc_percent"] frozeBtcAmnt <- map["froze_btc_amnt"] frozeEtcaAmnt <- map["froze_etc_amnt"] frozeHlcAmnt <- map["froze_hlc_amnt"] frozeEthAmnt <- map["froze_eth_amnt"] frozeLtcAmnt <- map["froze_ltc_amnt"] btcRate <- map["btc_rate"] etcRate <- map["etc_rate"] ethRate <- map["eth_rate"] ltcRate <- map["ltc_rate"] hlbRate <- map["hlc_rate"] }}复制代码
那么解析是这样的:
struct ResultSum { var status: Bool = false var message: String = "未知错误" var property: HomeModel? init(data: Any) { let json = JSON(data) if json["errorCode"].intValue == 0 { status = true if let info = json["data"]["userWallet"].dictionaryObject { property = Mapper().map(JSONObject: info) } } message = json["message"].stringValue }}复制代码
其中 property 是可选的,因为理想的情况下才会成功,也有不返回的情况。
这里的网络请求用到的是 POP (Protocol Oriented Programming
) 思想。
Swift 隐式解包 多重 Optional
在 Swift
中 Optional
先看例子:
var searchController: UISearchController!lazy var reducer: (State, Action) -> (state: State, command: Command?) = { [weak self] (state: State, action: Action) in var state = state var command: Command? = nil switch action { case .loadData: command = Command.loadCycleDate { self?.store.dispatch(.reloadCycleData(images: $0))} case .reloadCycleData(let items): state.cycleSource = CycleDataSource(images: items, collection: state.cycleSource.collectionView) case .selectCycleView(let index): command = Command.selectCycleView(index: index) break case .selectMenu(let index): command = Command.selectMenu(index: index) } return (state, command) }复制代码
例如的示例中 Command?
与 var searchController: UISearchController!
在对其成员或者方法调用的时候,编译器会对其进行自动解包。!
是用来告诉编译器它是一个可以隐式解包的 Optional
值。
searchController
如果没有被实例化的时候是 nil ,直接使用会导致程序直接崩溃,而使用的时候也会会被人误以为能直接访问 比如使用相关操作的时候:
var searchController: UISearchController!searchController.hidesNavigationBarDuringPresentation = falsesearchController.searchBar.searchBarStyle = .minimal没有实例化:直接崩溃 ?复制代码
如果是 ?的时候
var searchController: UISearchController?searchController?.searchResultsUpdater = searchResultsControllersearchController?.hidesNavigationBarDuringPresentation = false复制代码
在示例中 Command?
表示是一个可选空值,可以是空,可以用
Optional Binding
来处理 if let resul = result, let models = resul.arrModel { if !resul.status { return } }复制代码
像这些基本性的问题你可以去 挑几本看看。作者是一个值得敬重的人。
我这里也没法在短时间内细致的介绍太多,还在招人,证明活比较多 (⊙﹏⊙)b
Swift 的世界有太多的东西,有时间在说
......
如果你看到这里,插播一条广告:
公司需要 需要 两名iOS开发人员
坐标:北京望京 Soho T3 30层要求是:Swift, OC 都在中等以上,扎实的计算机基础公司不打卡,各种补贴,技术团队来自知名企业:IBM,微软,惠普,三星,百度等等 CTO 早年跟乔布斯有过合作。氛围很好。 简历这里: sirBliar@gmail.com我直接面试,算是内推。?