我目前正在开发一款必须解析网址的iOS应用。必须解析的URL始终具有相同的格式。
此类网址的示例:
myprotocol://标签姓名=约翰&安培;姓=史密斯
我的第一个想法是编写一个“解析器”类,它使用URL的String初始化,并使用 getter 方法返回label
,从网址解析firstname
和lastname
。
这类的伪代码:
import Foundation
class URLParser {
var url: URL
init(url: String) {
self.url = URL(string: url)
}
func label() -> String? {
// code to determine label
}
func firstname() -> String? {
// code to determine firstname
}
func firstname() -> String? {
// code to determine lastname
}
}
但后来我阅读了更多关于Swift扩展的内容,并看到它们在几个places中被使用和推荐。
对于我的用例,我可以为URL
类创建一个扩展,它可能如下所示:
import Foundation
extension URL {
var label: String {
// code to determine label
}
var firstname: String {
// code to determine label
}
var lastname: String {
// code to determine label
}
}
一方面使用这样的扩展似乎是一个好主意,因为它感觉非常轻巧和精确。但另一方面它也感觉有点不对,因为值label
,firstname
和lastname
与一般的概念没有任何关系。 URL。它们特定于我的用例。
我希望在我的代码中清楚地传达正在发生的事情,并使用MyUseCaseURLParser
或URL
MyUseCaseURL
这类名为{{1}}的类似乎做得更好。
但这完全基于其他语言的过去编程经验。
Swifty 这样做的方式是什么,并围绕它组织代码?除了使用扩展和类之外,还有更好的方法吗?
答案 0 :(得分:1)
有两件事需要代表:
您的第一个解决方案很好,但您不应该将其称为URLParser
。解析在那里发生,但是类不代表解析器,它代表结果。
我会将其简化为:
class MyProtocolData {
init?(url: URL) {
// parsing happens here, it's a failable initializer
// no need to store the URL
}
let label: String
let firstName: String
let lastName: String
}
您还可以使用struct
。
第二种解决方案也没问题。 Apple也使用了这样的解决方案(例如NSDictionary
)。但是,这种解决方案的问题是在所有URL
个实例上都具有属性,即使是那些不属于您的方案的实例。此外,每次访问函数(或属性)时都必须再次解析URL。
我使用extension
的第一个解决方案是:
extension URL {
func parseMyProtocol() -> (label: String, firstName: String, lastName: String)? {
}
}
请注意,我们将解析与结果分开。另请注意,该方法的名称不是通用的,它不会与其他解析方法冲突。
我的第二个解决方案是用结构替换结果元组:
struct MyProtocolData {
let label: String
let firstName: String
let lastName: String
}
extension URL {
func parseMyProtocol() -> MyProtocolData? {}
}
根据网址所代表的内容,您可能会想到更好的名称,例如: UserData
和parseUserData
。
正如您所看到的,有多种解决方案,都是惯用的Swift。使用类没有什么不合适的。
答案 1 :(得分:0)
在您的示例中,扩展程序不适合这种情况。如果要提供检查URL是否包含参数的函数,则将使用扩展名。更好的方法是使用带有可用初始化程序的结构,并使用let。
使其不可变struct CustomURL {
let url: URL
let label: String
let firstname: String
let lastname: String
init?(url: URL) {
//Check if url contains all elements you need, if not return nil
}
}