Swift中的URL

所属分类:ios | 发布于 2024-02-13 20:08:06

URL在外面构建的应用程序中无处不在,通常URL有两类。

1、本地文件URL,我们使用URL绑定路径引用本地文件。

2、远程URL,使用URL从指定的API的路径获取数据,或获取图像并显示。

URL基本操作

将字符串值转化为URL

let url = URL(string: "https://www.google.com")!

这种初始化方法的缺点是,生成的URL是一个可选值,在使用的时候需要强制解包。创建一个简单的扩展,通过使用自定义初始值来帮我们实现自动解包。

extension URL {
    init(_ string: StaticString) {
        self.init(string: "\(string)")!
    }
}

var unwrappedURL = URL("https://www.google.com")

URL转String

可以使用URL的absoluteString属性把URL转换成String

print(unwrappedURL.absoluteString) // Prints: https://www.google.com

使用相对URL

在Swift中构建API时经常使用的一种场景是通过使用基本URL来构建连接。

例如,我们可以构建一个博客文章类别页面,如下

let category = "ios"
let baseURL = URL(string: "https://wenge365.com")!
let blogURL = URL(string: category, relativeTo: baseURL)!
print(blogURL) // Prints: swift -- https://wenge365.com
print(blogURL.absoluteString) // Prints: https://wenge365.com/ios

同时,如果URL本身是相对的,我们可以获得某个链接的基础URL

let absoluteURL = URL(string: "https://wenge365.com")!
let relativeURL = URL(string: "ios", relativeTo: baseURL)!
print(absoluteURL.baseURL) // Prints: nil
print(relativeURL.baseURL!) // Prints: https://wenge365.com

打印host和scheme

let swiftLeeURL = URL(string: "https://wenge365.com")!
print(absoluteURL.host!) // Prints: wenge365.com
print(absoluteURL.scheme!) // Prints: https

URL Components组件

链接基本上是由几个组件组成的。我们之前已经在印刷声明中看到了一些内容,但还有更多的内容需要涵盖:

let twitterAvatarURL = URL(string: "https://twitter.com/twannl/photo.png?width=200&height=200")!
print(twitterAvatarURL.path) // Prints: /twannl/photo.png
print(twitterAvatarURL.pathComponents) // Prints: ["/", "twannl", "photo.png"]
print(twitterAvatarURL.pathExtension) // Prints: png
print(twitterAvatarURL.lastPathComponent) // Prints: photo.png

获取查询参数

上面的twitter链接中有width和height两个参数,我们需要获取这两个参数以便于按正确的比例显示头像。

可以使用URLComponents来初始化链接。它返回一个新的属性集合,可以将其视为一个URL解析器,它让我们能访问参数项:

let components = URLComponents(string: "https://twitter.com/twannl/photo.png?width=200&height=200")!
print(components.query!) // width=200&height=200
print(components.queryItems!) // [width=200, height=200]

我们可以通过遍历查询项数组来直接访问值:

let width = components.queryItems!.first(where: { queryItem -> Bool in
    queryItem.name == "width"
})!.value!
let height = components.queryItems!.first(where: { queryItem -> Bool in
    queryItem.name == "height"
})!.value!
let imageSize = CGSize(width: Int(width)!, height: Int(height)!)
print(imageSize) // Prints: (200.0, 200.0)

但是,上面的代码使用了大量的unwrap,显得臃肿,代码可读性不高。因此我们可以使用自定义下标扩展,使代码看起来更好

extension Collection where Element == URLQueryItem {
    subscript(_ name: String) -> String? {
        first(where: { $0.name == name })?.value
    }
}
let imageWidth = Int(components.queryItems!["width"]!)!
let imageHeight = Int(components.queryItems!["height"]!)!
let size = CGSize(width: imageWidth, height: imageHeight)

 

构建一个带参数的URL

有一个需求时从字典中构建一个带请求参数的URL,例如:

let parameters = [
    "width": 500,
    "height": 500
]
var avatarURLComponents = URLComponents(string: "https://twitter.com/twannl/photo.png")!
avatarURLComponents.queryItems = parameters.map({ (key, value) -> URLQueryItem in
    URLQueryItem(name: key, value: String(value))
})
print(avatarURLComponents.url!) // Prints: https://twitter.com/twannl/photo.png?width=500&height=500

编写一个扩展,该扩展更容易地讲字典转换为查询项数组:

extension Array where Element == URLQueryItem {
    init<T: LosslessStringConvertible>(_ dictionary: [String: T]) {
        self = dictionary.map({ (key, value) -> Element in
            URLQueryItem(name: key, value: String(value))
        })
    }
}
let pagingParameters = [
    "offset": 2,
    "limit": 50
]
var twitterFeedURLComponents = URLComponents(string: "https://twitter.com/feed")!
twitterFeedURLComponents.queryItems = .init(pagingParameters)
print(twitterFeedURLComponents.url!) // Prints: https://twitter.com/feed?offset=2&limit=50

文件URL

使用isFileURL属性可以区分远程URL和本地URL

var remoteFileURL = URL(string: "https://www.twitter.com/avatar.jpg")!
var fileURL = URL(string: "file:///users/antoine/avatar.jpg")!
print(remoteFileURL.isFileURL) // Prints: false
print(fileURL.isFileURL) // Prints: true

isFileURL属性只有在URL scheme为file:时才返回true。

获取本地文件URL扩展

print(fileURL.pathExtension) // Prints: jpg

获取本地文件的文件名(不包含扩展)

要从文件URL中获取文件名,我们可以使用lastPathComponent并通过删除文件扩展名来提取文件名:

print(fileURL.deletingPathExtension().lastPathComponent) // Prints: avatar

 

文哥博客(https://wenge365.com)属于文野个人博客,欢迎浏览使用

联系方式:qq:52292959 邮箱:52292959@qq.com

备案号:粤ICP备18108585号 友情链接