# 闲谈 Objective-C 与 Swift

本文对比了Swift与Objective-C这两种iOS开发语言的特点与优劣。介绍了Swift的安全性、面向协议编程的优势,以及Objective-C的强大运行时特性。同时讨论了两者在实际项目中的混合使用策略。

bk

个人博客

随着移动互联网的发展,移动端iOS开发的技术选择也划分了好几个方向,有用 React-Native进行开发的,有用 Objective-C开发的,也有用 Swift开发的,或者 混合 着来。

不同的语言存在都有其可取的优秀之处,也有不足的地方。也应了那句俗话 : 金无足赤,人无完人。

我们都知道 2014Swift 的横空出世,其首要目的就是 剑指 Objective-C。 但是现在看来也没有完全达到其问世的目的。但是大家对于 Swift 的喜爱依然是一路包容,比如从14年以来一年一学,其情况犹如一年学习一门新语言,但是 Swift 也没有让我们失望,一路高歌猛进,今年也迎来了 Swift 4, 从这一路上来看,有一部分人好多放弃在 Swift 2.X 的路上了,一部分人没有体会到 Swift 3Swift 4 的喜悦. 也有一些人始终徘徊在 Swift 的门口; 一只脚在里面,一只脚在外面。

从始至终坚持的人是抱着 “苹果(Swift)” 虐我千百遍,我待 苹果(Swift) 如初恋的执着,也正所谓: 拨开云雾见天日 守得云开见月明, 从目前来看 Swift 4 给了开发者很大的 支持与信心

两种语言熟悉的人都知道 Objective-CSwift 底层是完全不同的机制。

Objective-C

Objective-C 的那一套跑不了 运行时, 我相信 KVC 的概念在每个面试者的脑海中都能 信手拈来

KVC, NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性。
KVO 就是基于 KVC 实现的关键技术之一
以类似字典键值对的方式存储信息,以及强大的动态派发,与 C 的结合
.......

太多太多

Swift

Swif 这门语言是恰恰不同,其类型成员在编译的时候就已经决定,完全是一门安全性的语言。
尤其对协议的支持。比如对协议的实现有:

classstructenum

这里不得不提到 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()复制代码

这种性质的继承是致命的。当然 SwiftObjective-C 是不支持多继承的,所以上面代码是无效的。但是很重要的是 通过协议,并对协议进行默认实现也是可以达到异曲同工的多继承作用。

Swift 与 Objective-C 混合

上面讲过两种语言的底层是完全不同的,但是我相信混合开发的时候怎么去处理呢?
尤其是在 Objective-C 代码中调用 Swift 的时候,Swift 没有运行时这种东西,而OC调用混导致异常问题。这个时候我们见到的 @objc 就挺身而出了。

@objc

只有不是继承 NSObjectSwift 写的 Class 的非私有类型, 在 OC 中调用的时候都是需要加上这个标志

Swift 建立模型

基于目前的习惯用到了 ObjectMapper

使用实例我相信官方介绍的比我详细,我这里就不做僭越 ?
我这里代码中放出一部分实例:

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<HomeModel>().map(JSONObject: info)
            }
        }
        message = json["message"].stringValue
    }
}复制代码

其中 property 是可选的,因为理想的情况下才会成功,也有不返回的情况。

这里的网络请求用到的是 POP (Protocol Oriented Programming) 思想。

Swift 隐式解包 多重 Optional

SwiftOptional

先看例子:

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 = false
searchController.searchBar.searchBarStyle = .minimal

没有实例化:直接崩溃 ?复制代码

如果是 ?的时候

var searchController: UISearchController?

searchController?.searchResultsUpdater = searchResultsController
searchController?.hidesNavigationBarDuringPresentation = false复制代码

在示例中 Command? 表示是一个可选空值,可以是空,可以用
if let 的 Optional Binding 来处理

            if let resul = result, let models = resul.arrModel {
                if !resul.status { return }
            }复制代码

像这些基本性的问题你可以去 Objc 挑几本看看。作者是一个值得敬重的人。

我这里也没法在短时间内细致的介绍太多,还在招人,证明活比较多 (⊙﹏⊙)b

Swift 的世界有太多的东西,有时间在说

......

如果你看到这里,插播一条广告:

公司需要 需要 两名iOS开发人员
坐标:北京望京 Soho T3 30层
要求是:Swift, OC 都在中等以上,扎实的计算机基础
公司不打卡,各种补贴,技术团队来自知名企业:IBM,微软,惠普,三星,百度等等 CTO 早年跟乔布斯有过合作。
氛围很好。 简历这里: sirBliar@gmail.com
我直接面试,算是内推。?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值