Swift中是否有类似于Android中的R.java的功能?

12

我是iOS和Swift的初学者。

我以前写过Android,认为R.java文件是管理标识符、drawable图片、字符串和其他资源的好方法。所以我很惊讶iOS没有提供一个好的功能来访问资源。

如果我想从资源库中获取一张图片,我会调用 UIImage(named: "img_name"),但我不认为这是最佳的访问img_name的方式,因为我可能使用错误的名称而无法获取到图片。

我发现了一些开源项目如SharkSwiftGen,但Shark只支持图像,而SwiftGen似乎需要手动运行命令。

你有更好的解决方案吗?谢谢!

5个回答

4

Xcode本身没有这样的功能,但有一个开源项目可以实现: R.swift

它可以自动更新生成的文件,并支持许多不同的资源类型,如图像、字体、segue等。


安装步骤看起来很复杂,但似乎是一个不错的解决方案。 - Findley Tyler

4
我有一个开源项目R.swift-plugin,它提供了你所需的功能。您只需要通过Alcatraz安装Xcode插件并搜索R.swift
插件将自动生成资源文件以管理您的图像、本地化字符串和颜色,并且您可以像使用R.java一样访问它们。
用法: enter image description here 真诚建议您尝试一下。欢迎随时给我提出任何改进的建议 :)

看起来确实是我想要的!但它只支持字符串、图像和颜色。不管怎样,我会试一试。 - Findley Tyler
是的,我认为字符串、图像和颜色应该是最常见的资源。 - Azure Chen
但是我计划稍后使其支持id(reuseidentifier,segue),布局(nib),bool,dimen和integer!我真的希望这个插件能够有所帮助。 - Azure Chen
请注意,虽然这个“R.swift-plugin”使用了非常相似的名称,但它与R.swift工具无关。 - Tom Lokhorst

4
  • 如果您使用的是InterfaceBuilder(也称为Storyboard, xib),则无需为每个视图定义ID。您可以在代码中绑定输出口。

  • 如果您想要使用它们的ID检索视图(如您所提问的R.java),则可以为每个视图设置标记并在代码中操作它们。enter image description here

与AndroidStudio不同,Xcode不会生成任何文件。

func viewDidLoad() {
    let labelView = self.view.viewWithTag(0) as? UILabel
}

谢谢。但是它只支持 IDs 和布局,对吗?有没有管理图像、颜色或字符串的功能? - Findley Tyler
将您的图像添加到 Xcode 的“资产”文件夹中。通常,只需添加3x图像即可正确显示和缩放。 UIImage(named: "hello") 将从“资产”中检索名为 hello 的图像。 - GRiMe2D
是的,但是使用图像名称进行初始化可能会因为打字错误而失败。 - Findley Tyler
@FindleyTyler 是的,你说得对。不过,在Swift中有一种特殊的泛型类型叫做Optional。默认情况下,所有类型和类都是"不兼容"的空值。也就是说,你不能将nil赋值给它们,否则编译代码会失败。Optional使它们可以赋值,所以你的应用程序不会崩溃,除非你强制解包它们。这里有更多信息:https://dev59.com/PmAg5IYBdhLWcg3wE3nQ#24026093 - GRiMe2D
另外,UIImageView 有一个类型为 UIImage? 的属性 image,意味着它是一个 Optional<UIImage>。你可以将 nil 赋值给 image,这样视图就不会渲染任何内容。因此,如果你期望看到某些图片但却什么都没有看到,很可能是你打错了字。 - GRiMe2D

1
你可以使用扩展和枚举来实现类似的功能。
使用枚举可以避免拼写错误,并受益于Xcode的自动建议/自动完成功能。
UIImage的示例:
extension UIImage {

    enum ImageId: String {
        // These are your images NAMES,
        // as in "SpriteMonster.jpg"
        case SpriteMonster, SpriteHero, BaseLandscape
    }

    convenience init!(id: ImageId) {
        self.init(named: id.rawValue)
    }
}

使用方法:

let monster = UIImage(id: .SpriteMonster)  // the "SpriteMonster.jpg" image

对于这个例子,我强制解包了方便初始化器,所以请注意确保您的捆绑包中实际上有正确名称的图像。
对于字符串:
extension String {

    enum StringId: String {
        case Welcome = "Welcome to the game!"
        case GameOver = "You loose! Game over!"
    }

    init(id: StringId) {
        self = id.rawValue
    }

}

使用方法:

let label = String(id: .Welcome) // "Welcome to the game!"

关于字体:

extension UIFont {

    enum FontId {
        case HelveticaNeueLarge
        case HelveticaNeueMedium
        case HelveticaNeueSmall

        func font() -> UIFont {
            switch self {
            case .HelveticaNeueLarge:
                return UIFont(name: "HelveticaNeue", size: 18)!
            case .HelveticaNeueSmall:
                return UIFont(name: "HelveticaNeue", size: 12)!
            default:
                return UIFont(name: "HelveticaNeue", size: 14)!
            }
        }
    }

    class func get(id: FontId) -> UIFont {
        return id.font()
    }

}

使用方法:

let font = UIFont.get(.HelveticaNeueLarge) // <UICTFont: 0x7ffd38f09180> font-family: "Helvetica Neue"; font-weight: normal; font-style: normal; font-size: 18.00pt

这些只是示例,旨在展示概念,您可以进一步扩展。

0

如果你使用Tuist,它内置了SwiftGen 工具。这使得你可以直接使用,无需添加第三方解决方案。缺点是每次更改资源时都需要运行它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接