在 Swift 中使用 CocoaPods

本文详细介绍了如何在Swift项目中利用CocoaPods进行依赖管理,包括基础用法、安装步骤、使用流程以及如何解决Swift与Objective-C混编时的BridgingHeader问题。同时,提出了通过Hook方式扩展CocoaPods,使其支持module.map文件,实现Swift直接导入Objective-C库。实测验证了该方法的有效性和易用性。

本文介绍如何在 Swift 项目中使用 CocoaPods 。如果你已经精通 Bridging Header 的方法,请直接跳到 “扩展 CocoaPods” 一节。

什么是 CocoaPods

CocoaPods is the dependency manager for Objective-C projects. It has thousands of libraries and can help you scale your projects elegantly. 1

从介绍看,它是主要给 Objective-C 项目用的,但是我们可以很容易地混合 Objective-C 和 Swift 到同个项目,从而利用大量的 CocoaPods 库和 Swift 漂亮舒服的语法。

作为 iOS 开发新手,一定是要紧跟前人脚步,学习使用 CocoaPods 。

基础用法

这里简单略过,请参考其他无数的文章。

安装

系统默认安装,可以参考其他教程2 。在命令行下执行。

1
sudo gem install cocoapods

我的环境是 HomeBrew

1
2
3
4
5
6
7
8
9
# 添加 taobao Mirror 不然被墙掉没办法下载
gem sources -a http: //ruby.taobao.org/
# 安装
gem install cocoapods
# 更新命令
rbenv rehash
# 执行
pod
# 此时一般会下载官方的所有 PodSpec 库,也可以用 pod setup 初始化环境

本文不打算在安装部分耗费太多时间。希望看到这里保证你的命令行下有可用的 pod 命令。

使用

假设我们已经有个项目,叫 ProjName ,需要使用一些注明的 CocoaPods 库,比如 AFNetworking3.

首先,命令行 cd 到我们的项目目录,一般 ls 命令会看到如下几个文件夹

1
2
3
ProjName
ProjName.xcodeproj
ProjNameTests

赞,就是这里,创建一个 Podfile 文本文件,写入如下内容

1
2
platform :ios, "8.0"
pod "AFNetworking" , "~> 2.0"

一般这么简单的文件都是直接 nano 写。 :)

直接创建 Podfile , CocoaPods 会创建一个项目同名的 WorkSpace ,然后添加一个叫 Pods 的项目,这个项目编译结果是一个叫 libPods.a的链接库, 它会添加到我们之前的 ProjName 项目中作为编译依赖。

当然,通过命令行执行 pod init 也可以自动创建 Podfile,而且可以自动分析当前项目的 target ,相对来说更好,也更优雅。具体请参考官方手册。这样的好处是更细致,还可以区分多个子项目子 target 。原理大同小异。

然后接下来,命令行执行 open ProjName.xcworkspace,注意这个可不是 .xcodeproj,这个是 CocoaPods 为我们创建的一个 WorkSpace ,包含我们之前的项目,和 Pods 依赖。

开始编码过程。直接在代码里调用,比如写在某个按钮的 @IBAction 里:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let manager = AFHTTPRequestOperationManager()
    let url = "http://api.openweathermap.org/data/2.5/weather"
    println(url)
 
    let params = [ "lat" : 39.26, "lon" : 41.03, "cnt" :0]
    println(params)
 
    manager.GET(url,
        parameters: params,
        success: { (operation: AFHTTPRequestOperation!,
                    responseObject: AnyObject!) in
            println( "JSON: " + responseObject.description!)
        },
        failure: { (operation: AFHTTPRequestOperation!,
                    error: NSError!) in
            println( "Error: " + error.localizedDescription)
        })

这里直接抄了 JakeLin 的 SwiftWeather 代码4,就一小段,希望他不会打我。

Swift 坑爹了

看起来貌似我们已经可以在 Swift 中使用 AFNetworking 了。结果刚写几句代码一堆类和变量找不到定义,而且坑爹的是很多时候我们只能靠猜测,判断这些 Objective-C 的定义转换成 Swift 定义是什么样子,用起来就是完全靠蒙!

这不科学!

这都三礼拜了,所以大家都摸索出了调用的方法,那就是按照和 Objective-C 代码混编的例子,添加 Bridging Header !

继续

之前简单介绍过和 Objective-C 交互的内容5,大家可以去围观。

一般说来,你在 Swift 项目新建 Objective-C 类的时候,直接弹出是否创建 Bridge Header 的窗口,点 YES 就是了,这时候一般多出来个 ProjectName-Bridging-Header.h 。然后删掉这个类, Bridging Header 头文件还在。

在这个 Bridging Header 文件里写入要导入的 CocoaPods 库,就可以在 Swift 中使用了。

1
#import <AFNetworking/AFNetworking.h>

如果没有自动创建头文件的话,这个配置在项目的 Build Settings 中的 Swift Compiler – Code Generation 子项里。

创建一个头文件,指定为 Bridging Header 也可以。

然后编译,成功执行!

这就完事了?

实际上,前两天刚写一篇 Swift 的模块系统 , 把任意 Objective-C 库当做 Swift Module 是可行的。当时就觉得这个东西应该是可能完全进入 CocoaPods 的,但是在官方 repo 找了下发现,以前有人提过增加 module.map 支持,结果 CocoaPods 的人认为这个是 llvm 内部特性, issue 被关闭了。#2216 最近又被提起,我在后面提了下 Swift 支持,希望官方靠谱。

所以下面的内容,就是,我们是否可以在 CocoaPods 上加入 module.map 支持,然后直接在 Swift 中 import ModuleName ?

扩展 CocoaPods

考虑了多种方式,最后选择了 Hook 的方式。如果 Ruby 技术足够好,或许可以直接写个插件。或者直接改官方代码给官方提交。但是实在能力有限。相关的 module.map 语法参考 llvm 官方手册 Modules – Clang 3.5 documentation。用了最简单的功能。也许遇到复杂的 PodSpec 就不起作用了,但是原理如此,相信小伙伴们已经知道怎么做了。

目前我的 Podfile 大概是这个样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
platform :ios, "8.0"
pod "AFNetworking" , "~> 2.0"
pod "Baidu-Maps-iOS-SDK" , "~> 2.0"
 
post_install do |installer|
   File.open( "#{installer.sandbox_root}/Headers/module.map" , 'w' ) do |fp|
     installer.pods.each do |pod|
       normalized_pod_name = pod.name.gsub( '-' , '' )
       fp.write <<EOF
module #{normalized_pod_name} [ system ] {
   umbrella "#{pod.name}"
   export *
}
EOF
       puts "Generating Swift Module #{normalized_pod_name.green} for #{pod} OK!"
     end
   end
end

post_install 是 Podfile 的一种 hook 机制,可以用来加入自定义操作。我在这里的写的逻辑就是,针对所有的 Pod 生成一个 module.map 文件。 位于 Pods/Headers/,这个目录被 CocoaPods 自动设置为项目的 Header Search Path 所以不需要额外处理。默认我们的 Swift 文件就找得到。

其中 normalized_pod_name 用于处理百度地图 API SDK 这一类名字带减号的库,因为他们不能作为 Module Name ,实际上或许有更好的方法来处理。

实际效果

实测发现完全没有问题,直接 import AFNetworking 或者 import BaiduMapsiOSSDK 都可以。

而且很不错的一点是,按住 Command 键,然后鼠标点击模块名、类名等,会跳转到 Swift 定义。

遇到提示 .pcm 文件 outdate 的情况下需要你删除 $HOME/Library/Developer/Xcode/DerivedData/ModuleCache 目录,这个目录保存的是预编译模块,类似于预编译头文件。

目前 Swift 还是有很多 BUG 的,调用 NSObject 也许会让编译器直接 segment fault ,不带任何出错信息。很伤情。此时请第一时间检查语法是否有诡异,其次将所有用到字符串或者 Optional 的地方都额外用变量处理,避免用字面常量。(个人经验)

如果多次调用 pod install 并在其中修改过 Podfile,那么有可能你的项目依赖会乱掉,多了不存在的 .a 文件到依赖或者多次包含。手工在项目树和项目选项里删除就可以了。此类编译错误都是链接错误。

总结

本文提出了一种 Bridging Header 之外的使用 CocoaPods 库的方法。利用有限的 Ruby 知识写了个 Hook 。目前测试 OK 。

参考

【完美复现】面向配电网韧性提升的移动储能预布局与动态调度策略【IEEE33节点】(Matlab代码实现)内容概要:本文介绍了基于IEEE33节点的配电网韧性提升方法,重点研究了移动储能系统的预布局与动态调度策略。通过Matlab代码实现,提出了一种结合预配置和动态调度的两阶段优化模型,旨在应对电网故障或极端事件时快速恢复供电能力。文中采用了多种智能优化算法(如PSO、MPSO、TACPSO、SOA、GA等)进行对比分析,验证所提策略的有效性和优越性。研究不仅关注移动储能单元的初始部署位置,还深入探讨其在故障发生后的动态路径规划与电力支援过程,从而全面提升配电网的韧性水平。; 适合人群:具备电力系统基础知识和Matlab编程能力的研究生、科研人员及从事智能电网、能源系统优化等相关领域的工程技术人员。; 使用场景及目标:①用于科研复现,特别是IEEE顶刊或SCI一区论文中关于配电网韧性、应急电源调度的研究;②支撑电力系统在灾害或故障条件下的恢复力优化设计,提升实际电网应对突发事件的能力;③为移动储能系统在智能配电网中的应用提供理论依据和技术支持。; 阅读建议:建议读者结合提供的Matlab代码逐模块分析,重点关注目标函数建模、约束条件设置以及智能算法的实现细节。同时推荐参考文中提及的MPS预配置与动态调度上下两部分,系统掌握完整的技术路线,并可通过替换不同算法或测试系统进一步拓展研究。
先看效果: https://pan.quark.cn/s/3756295eddc9 在C#软件开发过程中,DateTimePicker组件被视为一种常见且关键的构成部分,它为用户提供了图形化的途径来选取日期与时间。 此类控件多应用于需要用户输入日期或时间数据的场景,例如日程管理、订单管理或时间记录等情境。 针对这一主题,我们将细致研究DateTimePicker的操作方法、具备的功能以及相关的C#编程理念。 DateTimePicker控件是由.NET Framework所支持的一种界面组件,适用于在Windows Forms应用程序中部署。 在构建阶段,程序员能够通过调整属性来设定其视觉形态及运作模式,诸如设定日期的显示格式、是否展现时间选项、预设的初始值等。 在执行阶段,用户能够通过点击日历图标的下拉列表来选定日期,或是在文本区域直接键入日期信息,随后按下Tab键或回车键以确认所选定的内容。 在C#语言中,DateTime结构是处理日期与时间数据的核心,而DateTimePicker控件的值则表现为DateTime类型的实例。 用户能够借助`Value`属性来读取或设定用户所选择的日期与时间。 例如,以下代码片段展示了如何为DateTimePicker设定初始的日期值:```csharpDateTimePicker dateTimePicker = new DateTimePicker();dateTimePicker.Value = DateTime.Now;```再者,DateTimePicker控件还内置了事件响应机制,比如`ValueChanged`事件,当用户修改日期或时间时会自动激活。 开发者可以注册该事件以执行特定的功能,例如进行输入验证或更新关联的数据:``...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值