[译]iOS开发者在Swift中应避免过度使用

简介: 本文讲的是[译]iOS开发者在Swift中应避免过度使用,为了达到本文的目的,我简化了工作中项目的代码,但所有核心的思想都保留着。
本文讲的是[译]iOS开发者在Swift中应避免过度使用,

 
 

就在前几天,我终于把项目迁移到了Swift2.2,在使用SE-0022建议的#selector语句时,我遇到了一些问题。如果在protocol extension中使用#selector,这个protocol必须添加@Objc修饰符。而之前的Selector("method:")语句则不需要添加。

通过协议的扩展配置视图控制器

为了达到本文的目的,我简化了工作中项目的代码,但所有核心的思想都保留着。一种我经常在swift里用的模式是:为了重用的配置写protocols(协议)和extensions(扩展),特别是有Uikit的时候

假设我们有一组视图控制器,每个控制器都需要一个 view model 和 一个“取消”按钮。每一个控制器需要各自响应
“cancel”按钮的点击事件。我们可以这样写:

struct ViewModel {
    let title: String
}

protocol ViewControllerType: class {
    var viewModel: ViewModel { get set }

    func didTapCancelButton(sender: UIBarButtonItem)
}

如果就写成这样,那每个控制器都需要自己去添加和写一个一样的取消按钮。这样就会有很多一样的代码。我们可以通过扩展(用老的 Selector("") 语句)来解决:

extension ViewControllerType where Self: UIViewController {
    func configureNavigationItem() {
        navigationItem.leftBarButtonItem = UIBarButtonItem(
            barButtonSystemItem: .Cancel,
            target: self,
            action: Selector("didTapCancelButton:"))
    }
}

现在每个符合协议的控制器都可以通过在viewDidLoad()里调用协议的configureNavigationItem() 方法来配置取消按钮,是不是好多了~我们的控制器看起来是这样的:

class MyViewController: UIViewController, ViewControllerType {
    var viewModel = ViewModel(title: "Title")

    override func viewDidLoad() {
        super.viewDidLoad()
        configureNavigationItem()
    }

    func didTapCancelButton(sender: UIBarButtonItem) {
        // handle tap
    }
}

这仅是一个简单的例子,但我们可以想象通过这个方式制造更多复杂的配置。

把以上代码段升级到 Swift 2.2后,是这样的:

extension ViewControllerType where Self: UIViewController {
    func configureNavigationItem() {
        navigationItem.leftBarButtonItem = UIBarButtonItem(
            barButtonSystemItem: .Cancel,
            target: self,
            action: #selector(didTapCancelButton(_:)))
    }
}

但现在我们有了个问题,一个新的编译错误

Argument of '#selector' refers to a method that is not exposed to Objective-C.

Fix-it   Add '@objc' to expose this method to Objective-C

@objc试图破坏所有的东西

因为一系列的原因, 在原始的ViewControllerType协议中,我们并不能简单的给这个方法添加一个@objc修饰符。如果我们这么做了,那么所有的protocol都需要用@objc来标记,这将意味着:

  • 所有这个protocol的父protocol都需要用@objc来标记。
  • 所有继承自这个protocol的protocol都会被自动添加@objc
  • 我们在protocol中的结构体(ViewModel)不能用Objective-C来表示。

到目前,@objc在这里的唯一功能就是定义了一个普通的target-action selectors。尽管我们可以使用swift的强大功能,但是因为Cocoa依然贯穿我们的代码Cocoa all the way down,我们并没有正真的在写纯粹的swift - 除非我们开始在各个地方引入@objc。

我们在这的例子很简单,但是想象一下更复杂的类依赖关系图,大量使用Swift的值类型和当这个协议处在多个协议的中间层时。把引入@objc作为解决方案真是app的末日。如果我们这样做,@objc这种做法会让我们的Swift代码毫无美感并变得乱糟糟。这会毁了所有的东西。

但是希望还是有的。

不使用@objc来避免乱糟糟

我们大可不必让为了让我们的Swifit代码能使用Objcetive-C的语法而使用@objc

我们可以把protocol分解成多个protocol来去除@objc,然后我们再重组这些protocol。事实上,我们可以让编译器顺利编译和避免更改任何视图控制器的代码。

第一步,我们把protocol拆成2个。ViewModelConfigurableNavigationItemConfigurable。把ViewControllerType里的extension放到NavigationItemConfigurable

protocol ViewModelConfigurable {
    var viewModel: ViewModel { get set }
}

@objc protocol NavigationItemConfigurable: class {
    func didTapCancelButton(sender: UIBarButtonItem)
}

最终,我们可以把原ViewControllerType protocol定义成typealias

typealias ViewControllerType = protocol<ViewModelConfigurable, NavigationItemConfigurable>

和迁移到Swift2.2之前比一切都很正常,而且我们定义的原视图控制器也没有发生任何改变,没有东西被破坏。如果你曾经遇到类似的情况,或者你也想阻止@objc带来的破坏(你应该这么做),我强烈建议采用这个策略。

这并不是显而易见的

现在的代码,我还是觉得有点不爽,当然,针对这个问题,这就是最Swift化的答案。当Xcode突然开始提示你并且很快的应用它的修复方案依然会把所有都破坏掉。特别是当Xcode提供的修复方案正中你下怀的时候,这个时候,上面说的到的这类解决方案并不能立即很清楚。

最后,在做了以上那些更改之后,我意识到总的来说这其实是一个很好的解决方案。。没有什么理由在一个地方只用一个协议。像ViewModelConfigurableNavigationItemConfigurable这两个协议分工明确。把不同的协议组合在一起始终都是最优雅、最适当的设计。



作者:donghuan1
链接:http://www.jianshu.com/p/b50a8ed6a00b
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。




原文发布时间为:2016年06月27日

本文来自云栖社区合作伙伴掘金,了解相关信息可以关注掘金网站。
目录
相关文章
|
3月前
|
iOS开发 开发者
苹果iOS App Store上架操作流程详解:从开发者账号到应用发布
很多开发者在开发完iOS APP、进行内测后,下一步就面临上架App Store,不过也有很多同学对APP上架App Store的流程不太了解,下面我们来说一下iOS APP上架App Store的具体流程,如有未涉及到的部分,大家可以及时咨询,共同探讨。
|
4月前
|
安全 编译器 Swift
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
106 2
|
4月前
|
开发工具 iOS开发 开发者
2023开发者必备iOS开发工具
2023开发者必备iOS开发工具
54 1
|
3天前
|
Web App开发 开发者 iOS开发
iOS开发者帐号申请指南(转)
iOS开发者帐号申请指南(转)
10 1
|
12天前
|
存储 Swift iOS开发
使用Swift开发一个简单的iOS应用的详细步骤。
使用Swift开发iOS应用的步骤包括:创建Xcode项目,设计界面(Storyboard或代码),定义数据模型,实现业务逻辑,连接界面和逻辑,处理数据存储(如Core Data),添加网络请求(必要时),调试与测试,根据测试结果优化改进,最后提交至App Store或其它平台发布。
32 0
|
12天前
|
安全 Swift iOS开发
【Swift 开发专栏】Swift 与 UIKit:构建 iOS 应用界面
【4月更文挑战第30天】本文探讨了Swift和UIKit在构建iOS应用界面的关键技术和实践方法。Swift的简洁语法、类型安全和高效编程模型,加上与UIKit的紧密集成,使开发者能便捷地创建用户界面。UIKit提供视图、控制器、布局、动画和事件处理等功能,支持灵活的界面设计。实践中,遵循设计原则,合理组织视图层次,运用布局和动画,以及实现响应式设计,能提升界面质量和用户体验。文章通过登录、列表和详情界面的实际案例展示了Swift与UIKit的结合应用。
|
12天前
|
存储 安全 Swift
【Swift 开发专栏】使用 Swift 开发一个简单的 iOS 应用
【4月更文挑战第30天】本文介绍了使用 Swift 开发简单 iOS 待办事项应用的步骤。首先,阐述了 iOS 开发的吸引力及 Swift 语言的优势。接着,详细说明了应用的需求和设计,包括添加、查看和删除待办事项的功能。开发步骤包括创建项目、界面搭建、数据存储、功能实现,并提供了相关代码示例。最后,强调了实际开发中需注意的细节和优化,旨在帮助初学者掌握 Swift 和 iOS 开发基础。
|
5月前
|
开发工具 iOS开发 开发者
2023开发者必备iOS开发工具
工欲善其事,必先利其器。进行开发工作时,利用并熟练使用恰当的工具可以让工作效率得到大幅度提高。下边会介绍一些在进行iOS开发工作时常用的一些工具,本文并不对其进行展开,对使用方法及工作原理感兴趣的同学可以自行进行更深入的研究。
|
3月前
|
监控 API Swift
用Swift开发iOS平台上的上网行为管理监控软件
在当今数字化时代,随着智能手机的普及,人们对于网络的依赖日益增加。然而,对于一些特定场景,如家庭、学校或者企业,对于iOS设备上的网络行为进行管理和监控显得尤为重要。为了满足这一需求,我们可以利用Swift语言开发一款iOS平台上的上网行为管理监控软件。
213 2
|
3月前
|
iOS开发 开发者
苹果 iOS App Store 上架操作流程详解:从开发者账号到应用发布
苹果 iOS App Store 上架操作流程详解:从开发者账号到应用发布