Swift 是否有一种与C#和#x27 ;;s';名称()';函数获取变量或成员';她叫什么名字?

Swift 是否有一种与C#和#x27 ;;s';名称()';函数获取变量或成员';她叫什么名字?,swift,reflection,nameof,Swift,Reflection,Nameof,好的,这里有一个关于s/O的问题,标题如下: 从名字上看,这似乎正是我想要的。然而,看看公认的答案(以及其他不被认可的答案),他们指的是关键路径操作,这不是我想要的(即,这不是重复的!) 在我的例子中,我希望一个变量的名称存储在第二个字符串类型的变量中 在C#中,使用nameof是很简单的,就像这样。。。 我相信这发生在编译时,而不是运行时,因此不需要反射或其他任何东西,符号名称也不必出现在可执行文件中。编译器只是在变量名中加入子变量 例如,当您想要定义一个查询对象,其中您的成员名称与URL

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

从名字上看,这似乎正是我想要的。然而,看看公认的答案(以及其他不被认可的答案),他们指的是关键路径操作,这不是我想要的(即,这不是重复的!)

在我的例子中,我希望一个变量的名称存储在第二个字符串类型的变量

在C#中,使用
nameof
是很简单的,就像这样。。。

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

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

下面是一个伪代码示例(即,这显然不会编译,但显示了我的目标):

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

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

let urlString = queryObject.getUrl
返回值为:

www.ScoreTracker.com/postScore?userName=Maverick&highScore=123456
访问变量的字符串表示形式而不是使用字符串常量的优点是:

  • 成员的名称用作查询参数,保持结构的使用干净和简单
  • 不需要定义常量来保存查询参数名称,因为它们是成员名称中隐式的
  • 您可以获得实际符号的完全重构支持,而不是字符串的查找替换
  • 例如,假设API将查询参数从
    userName
    更改为
    userId
    。我所要做的就是相应地重构我的成员名称,现在输出将是

    www.ScoreTracker.com/postScore?userId=Maverick&highScore=123456
    
    …无需我更改任何字符串常量

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


    那么,这可以用Swift实现吗?您能否获取实际变量名并将其存储在第二个变量中?

    是的,您可以。我将此用作下一个场景的解决方案:当我在控制台中打印对象/结构时,我希望看到变量名称以及相关值:

    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)
    获得您想要的。

    您不能,Swift变量名在编译时被抽象掉。它们只是由编译器确定的寄存器和内存地址的占位符。这些信息可能会进入调试可执行文件,但这不是公开可用的API。一方面,您应该避免使用
    String
    对URL进行编码。使用
    URL
    ,您会轻松得多。另外,请查看
    URLComponents
    URLQueryItem
    ,以获得一种更好的方法来生成带有参数的URL。@MarqueIV:我相当肯定Swift中不存在直接等价物
    #keyPath
    可能接近它(但需要
    @objc
    属性和类),而
    镜像(反射:)
    可以在运行时执行某些操作。Swift 4
    KeyPath
    没有字符串表示形式()另一方面,如果实际目的是对自定义结构进行编码/序列化,则可能会使用Swift 4
    Codable
    协议,请看一些JSONECoder示例。是否可以在(实际)用例中利用
    Codable
    ?下面是一个如何构建URL查询编码器的快速示例:嘿@Hamish,我刚刚重温了这篇旧文章,看到了您尝试实现此功能的链接。看了一遍,但没有完全听懂。你让它工作过吗?只是好奇。
    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