有一个Swift相当于C#的'nameof()'函数来获取变量或成员的名字吗?

时间:2017-12-19 16:34:35

标签: swift reflection nameof

好的,这里有一个关于S / O的问题,标题如下:

Swift: Get Variable Actual Name as String

通过它的名字,它似乎正是我想要的。然而,看着接受的答案(以及其他未被接受的答案),他们指的是关键路径操纵,这不是我所追求的。 (即这不重复!)

就我而言,我希望将 一个变量的名称 存储在 的第二个变量 中输入字符串。

在C#中,使用nameof这是微不足道的,就像这样......

int someVar = 3

string varName = nameof(someVar)
// 'varName' now holds the string value "someVar"
  

我相信这发生在编译时,而不是运行时,因此不需要反射或其他任何东西,符号名称也不必在可执行文件中。编译器只是在变量的名称中。

例如,当您想要定义一个查询对象,其中您的成员名称与URL中传递的查询参数匹配时,这非常方便。

这是一个伪代码示例(即显然不会编译,但显示我正在追求的内容):

struct queryObject{

    let userName  : String
    let highScore : Int

    var getUrl:String{
        return "www.ScoreTracker.com/postScore?\(nameof(userName))=\(userName)&\(nameof(highScore))=\(highScore)"
    }
}

以下是您如何使用它以及它将返回的内容:

let queryObject = QueryObject(userName:"Maverick", highScore:123456)

let urlString = queryObject.getUrl

返回值为:

www.ScoreTracker.com/postScore?userName=Maverick&highScore=123456

访问变量的字符串表示而不是使用字符串常量的优点是:

  1. 您的成员名称用作查询参数,保持结构的用法简洁明了
  2. 没有必要定义常量来保存查询参数名称,因为它们是隐含在成员名称中的
  3. 您获得了对实际符号的完全重构支持,而不是find-replace of strings
  4. 例如,假设API将查询参数从userName更改为userId。我所要做的就是相应地重构我的会员名称,输出现在是......

    www.ScoreTracker.com/postScore?userId=Maverick&highScore=123456
    

    ...没有我必须更改任何字符串常量。

      

    注意:上面的示例只是为了简单说明一种可以使用变量名称的方法。这不是我们实际处理URL的方式,也不是为它们添加查询参数;这篇文章的讨论过于冗长和偏离主题。

    那么,这可以在Swift中完成吗?你能得到实际的变量名并将其存储在第二个变量中吗?

2 个答案:

答案 0 :(得分:0)

是的,你可以。我用它作为下一个场景的解决方案:当我在控制台中打印一个对象/结构时,我喜欢看到 vars 名称以及关联的值:

extension CustomStringConvertible {
    var description: String {
        var description = "\n          *****  \(type(of: self)) *****\n"
        let mirrorS = Mirror(reflecting: self)
        for child in mirrorS.children {
            if let propertyName = child.label {
                description += "   \(getSpaces(forWord: propertyName))\(propertyName):  \(child.value)\n"
            }
        }

        return description
    }
}

为了使用它,让我们以以下结构为例:

public struct FavoriteApp: Codable, CustomStringConvertible, Hashable {
    let appId: String
    let appName: String
    let bundleId: String
    let image: NSImage
    let isMacApp: Bool
    let rating: String
    let screenshotUrls: [String]
    let sellerName: String
    let sellerUrl: String
    let releaseDate: String
    let genres: String
    let latestVersion: String

}

let anApp:FavoriteApp = getTheAppInfoFromServer()
print(anApp) 

// This will print into console: 
    //        *****  FavoriteApp *****
    //        appId:          1438547269
    //        appName:        Dynamic wallpaper
    //        bundleId:        com.minglebit.DynamicWallpaper
    //        image:           -not visible- (but is there, trust me :))
    //        isMacApp         true
    //        rating:          0
    //
    //        screenshotUrls:  https://is1-ssl.mzstatic.com/image/thumb/Purple128/v4/5c/08/b8/5c08b824-12eb-e0b6-22fb-0e234f396b9e/pr_source.jpg/800x500bb.jpg
    //                        https://is1-ssl.mzstatic.com/image/thumb/Purple128/v4/f3/34/0e/f3340e21-714c-0a17-4437-73ba1828cbba/pr_source.jpg/800x500bb.jpg
    //        sellerName:      MingleBit SRL
    //        sellerUrl:       https://minglebit.com/products/dynamicwallpaper.php
    //        releaseDate:     2018-10-18T14:59:47Z
    //        genres:          Entertainment, Lifestyle
    //        latestVersion:   2.3

因此,要集中回答,请使用 Mirror(reflecting: object) 来获得您想要的。

答案 1 :(得分:0)

如果只处理 URL,建议使用 URLComponents,比较好。

型号:

['link_car_1', 'link_car_12', 'link_car_23', '...']

然后:

struct QueryObject{

    var params = [String: String]()

    var getUrl: String{
        let result = "www.ScoreTracker.com/postScore"
        guard var url = URL(string: result) else { return result}
        url.appendQueryParameters(params)
        return url.absoluteString
    }

    init(params: [String: String]) {
        self.params = params
    }

}

Github link