iOS开发:关于URL解析

507 阅读3分钟

iOS与Android对URL的解析

首先分析了一下iOS与Android在解析URL上是否有差异。

iOS的解析:

guard let url = URLComponents(string: "http://www.example.com:80/path/to/resource.html?param=value#fragment") else {
    return
}

// 获取协议
let scheme = url.scheme ?? ""
print("url Protocol: " + scheme)

// 获取主机名
let host = url.host ?? ""
print("url Host: " + host)

// 获取端口号
let port = url.port ?? -1
print("url Port: \(port)")

// 获取路径
let path = url.path
print("url Path: " + path)

// 获取查询字符串
let query = url.query ?? ""
print("url Query: " + query)

var dict = [String: String]()
if let queryItems = url.queryItems {
    dict = queryItems.toDict
}
print("url dict: \(dict)")

// 获取片段
let ref = url.fragment ?? ""
print("url Ref: " + ref)

/**
url Protocol: http
url Host: www.example.com
url Port: 80
url Path: /path/to/resource.html
url Query: param=value
url Ref: fragment
*/

Android的解析:

import java.net.URL;
import java.net.MalformedURLException;

public class URLParsingExample {
    public static void main(String[] args) {
        try {
            URL url = new URL("http://www.example.com:80/path/to/resource.html?param=value#fragment");

            // 获取协议
            String protocol = url.getProtocol();
            System.out.println("Protocol: " + protocol);

            // 获取主机名
            String host = url.getHost();
            System.out.println("Host: " + host);

            // 获取端口号
            int port = url.getPort();
            System.out.println("Port: " + port);

            // 获取路径
            String path = url.getPath();
            System.out.println("Path: " + path);

            // 获取查询字符串
            String query = url.getQuery();
            System.out.println("Query: " + query);

            // 获取片段
            String ref = url.getRef();
            System.out.println("Ref: " + ref);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }
}

Protocol: http
Host: www.example.com
Port: 80
Path: /path/to/resource.html
Query: param=value
Ref: fragment

小结

其实可以看出,iOS和Android对于URL的解析基本上是一致的。

  • ?用于分割前后,前面可以认为是路径,后面的可以认为是参数

  • param=value&name=season,通过=与&用来分割参数

  • 最后通过#用来分割Fragment

遇到的异常情况

我们在通过name=value这种形式进行传参的时候,不可避免可能会使用到#与?符号,比如下面:

haha://abcd?param=value&id=12345678&jumpType=information&content=我关注的话题#你好啊?

content=我关注的话题#你好啊?其实是{ content: 我关注的话题#你好啊? }这样一个json,但是会被截取成下面这样子:

url Query: param=value&id=12345678&jumpType=information&content=我关注的话题
url dict: ["id": "12345678", "content": "我关注的话题", "jumpType": "information", "param": "value"]
url Ref: 你好啊

content=我关注的话题#你好啊?明明是一个完整的参数,但是因为解析的策略,#与?都被截掉了。

思路

为了保证语义的完整性。

我们可以考虑将name=value这种形式进行传参转换为json:{"id": "12345678", "content": "我关注的话题#你好啊?", "jumpType": "information", "param": "value"},然后再转成jsonString,最后使用base64进行加密获得string,这里使用base64进行加密是为了保证加密后的数据没有可以被解析的符号。

App侧拿到后,先将这个string通过base64解密,获得完整的jsonString,然后就可以正常解析了。

例子

这个例子中有jumpType、id、jsonString三个参数,然后jsonString里面包含了很多个参数

nm://home?jumpType=TopicDetail&id=d308e8ff62dbb382a106def90d946759&jsonString=e1widGFsa2luZ05hbWVcIjpcIuaIkeeahOaPkOi9puaXpeiusFwiLFwiaG90UmF0ZVwiOjEyMzgsXCJ2aWV3Q291bnRcIjo0NzY1MixcInN0YXR1c1wiOjF9

解析jsonString

"{\"talkingName\":\"我的提车日记\",\"hotRate\":1238,\"viewCount\":47652,\"status\":1}"

base64加解密会不会出现#?=这个符号呢?

有关与这个,我去查阅了一下资料

Swift 中,使用 Base64 编码后的字符串不会包含 ?#& 这些符号。Base64 编码的输出只会包含以下字符:

  • 大写字母:A-Z
  • 小写字母:a-z
  • 数字:0-9
  • 加号:+
  • 斜杠:/
  • 等号:=(用于填充)

这些字符是 Base64 编码标准的一部分,确保编码后的字符串可以安全地在文本环境中传输。

但是会不会出现异常情况呢?这个还真不能保证。

总结

URL解析其实不仅涉及到网络请求,有些路由规则与传参也会涉及到URL的拼接与规则,了解URL的细节,以及多端的异同点,可以提高开发效率。