无需重新编译,即可动态调整您的 iOS 应用!
您的用户不会看到您的动画研究、Sketch 组件或原型。他们将看到的是最终产品 - 因此确保您的应用在真实设备上感觉良好非常重要!
在笔记本电脑上看起来很棒的动画,在手中往往感觉太慢。在 27 英寸显示器上看起来完美的布局,在 4 英寸设备上可能过于拥挤。浅灰色文本在 Sketch 中看起来可能很微妙,但在阳光明媚的户外却完全难以辨认。
这些动画时间、字体大小和颜色选择都是“魔法数字”的例子 - 这些常量赋予您的应用可用性和特性。SwiftTweaks 的目标:允许您在 Swift 项目的调试版本中微调这些魔法数字,而无需等待 Xcode 重新构建应用。
在代码中使用 Tweak
代替布尔值、数字或颜色。您可以调整该 Tweak
而无需重新编译,这意味着您可以在没有 Xcode 的情况下调整动画时间、颜色和布局!
目前,您可以调整以下类型
Bool
Int
CGFloat
Double
UIColor
TweakAction
String
StringOption
一个 Tweak
看起来像这样
public static let colorTint = Tweak("General", "Colors", "Tint", UIColor.blueColor())
还有一些有用的 TweakGroupTemplate
类型,因此您可以快速声明常用的组合。它们都具有合理的默认值,但当然,您可以设置自己的值!
// Controls delay and duration for UIView.animate
// Use it with UIView.animate(basicTweakTemplate:...)
public static let basicAnimation = BasicAnimationTweakTemplate("Animation", "Basic Animation")
// Controls delay, duration, damping, and initial spring velocity for UIView.animate
// Use it with UIView.animate(springTweakTemplate:...)
public static let springAnimation = SpringAnimationTweakTemplate("Animation", "Spring Animation")
// Controls shadow color, radius, offset, and opacity for CALayer
// Use it with CALayer.apply(shadowTweakTemplate:...)
public static let shadowTweak = ShadowTweakTemplate("Shadows", "Button Shadow")
// Controls top/right/bottom/left for UIEdgeInsets
// Use it with UIEdgeInsets.init(edgeInsetsTweakTemplate)
public static let edgeInsets = EdgeInsetsTweakTemplate("Layout", "Screen Edge Insets")
当然,如果您愿意,您可以创建自己的 TweakGroupTemplate
类型 - 每当您有一组需要一起使用的 tweaks 以获得所需效果时,它们会很方便。 它们可以由任何 Tweak
组合构建。
SwiftTweaks 现在支持闭包,因此您可以执行不依赖于 SwiftTweaks 中数据的操作。为此,请在您的 TweakStore
中使用 TweakAction
作为类型来创建一个执行自定义闭包的 Tweak。
public static let action = Tweak<TweakAction>("Actions", "Action", "Perform some action")
稍后在代码中,您可以将闭包添加到该 tweak,这些闭包在按下 Tweaks 窗口中的按钮时执行。
let idenfitier = ExampleTweaks.action.addClosure {
/// Some complicated action happens here
print("We're all done!")
}
如果您愿意,您也可以使用 addClosure
方法提供的唯一标识符来删除闭包。
ExampleTweaks.action.removeClosure(with: idenfitier)
好问题!很高兴你问到。SwiftTweaks 存在的全部原因是因为我们非常喜欢 FBTweaks。 我们一直是 Objective-C 项目中 FBTweaks 的长期粉丝:用 FBTweak
宏替换魔法数字,就搞定了!您可以将 FBTweak 宏留在您的生产代码中,因为它在编译时会被 tweak 的默认值替换。
但是 Swift 不支持这种宏魔法,因此在 Swift 代码中使用 FBTweaks 很麻烦。我们的应用几乎都是 Swift 写的,所以我们想看看是否可以制作一些更容易的东西!
将 SwiftTweaks 添加到您的项目有三个步骤
TweakLibraryType
,它包含一组 Tweak
和一个 TweakStore
来持久化它们。TweakLibraryType
以使用 Tweak
。TweakWindow
作为您应用的窗口(还有其他选项,但这是最直接的!稍后会详细介绍。)现在构建并运行,然后摇动您的手机以调出 Tweaks UI!调整 tweaks,当您对所获得的内容感到满意时,从 Tweaks UI 中与他人分享您的 tweaks。
tweak 库负责列出许多 public static
tweaks,并构建一个 TweakStore
。tweak 库看起来像这样
public struct ExampleTweaks: TweakLibraryType {
public static let colorTint = Tweak("General", "Colors", "Tint", UIColor.blue)
public static let marginHorizontal = Tweak<CGFloat>("General", "Layout", "H. Margins", defaultValue: 15, min: 0)
public static let marginVertical = Tweak<CGFloat>("General", "Layout", "V. Margins", defaultValue: 10, min: 0)
public static let font = Tweak<StringOption>("General", "Layout", "Font", options: ["AvenirNext", "Helvetica", "SanFrancisco"])
public static let featureFlagMainScreenHelperText = Tweak<Bool>("Feature Flags", "Main Screen", "Show Body Text", true)
public static let buttonAnimation = SpringAnimationTweakTemplate("Animation", "Button Animation")
public static let defaultStore: TweakStore = {
let allTweaks: [TweakClusterType] = [colorTint, marginHorizontal, marginVertical, featureFlagMainScreenHelperText, buttonAnimation]
let tweaksEnabled = TweakDebug.isActive
return TweakStore(
tweaks: allTweaks,
enabled: tweaksEnabled
)
}()
}
让我们分解一下这里发生了什么
ExampleTweaks
中有五个 tweaks:一个色调颜色、两个用于布局的 CGFloat
、一个用于字体选择的 StringOption
和一个切换开发中功能的 Bool
。Int
、CGFloat
和 Double
之间混淆 - 因此您可能会发现有必要告诉 Tweak<T>
它的 T
是什么类型 - 就像我们在这里对边距 tweaks 所做的那样。TweakStore
来创建一个 defaultStore
,它需要知道 tweaks 是否 enabled
,以及所有 tweaks
的列表。TweakStore
上的 enabled
标志存在,因此您的用户无法在生产环境中访问 SwiftTweaks
。您可以随意设置它;我们喜欢使用项目构建设置中的 DEBUG
标志。要使用 tweak,您需要用 Tweak
引用替换代码中的数字或 UIColor
,如下所示
这是我们的原始代码
button.tintColor = UIColor.green
assign 返回 tweak 的当前值
button.tintColor = ExampleTweaks.assign(ExampleTweaks.colorTint)
bind 立即调用其闭包,并在每次 tweak 更改时再次调用
ExampleTweaks.bind(ExampleTweaks.colorTint) { button.tintColor = $0 }
bindMultiple 立即调用其闭包,并在其任何 tweaks 更改时再次调用
// A "multipleBind" is called initially, and each time _any_ of the included tweaks change:
let tweaksToWatch: [TweakType] = [ExampleTweaks.marginHorizontal, ExampleTweaks.marginVertical]
ExampleTweaks.bindMultiple(tweaksToWatch) {
let horizontal = ExampleTweaks.assign(ExampleTweaks.marginHorizontal)
let vertical = ExampleTweaks.assign(ExampleTweaks.marginVertical)
scrollView.contentInset = UIEdgeInsets(top: vertical, right: horizontal, bottom: vertical, left: horizontal)
}
有关更多示例,请查看示例项目的 ViewController.swift
文件。
默认情况下,SwiftTweaks 使用摇晃手势来调出 UI,但您也可以使用自定义手势!
SwiftTweaks 可通过 Swift Package Manager 获得;使用此 URL 将其添加到 Xcode
https://github.com/Khan/SwiftTweaks
它也列在(优秀的)Swift Package Index 中!
要将 SwiftTweaks
添加到您的应用程序,请将其添加到您的 Cartfile
github "Khan/SwiftTweaks"
此外,在项目的构建设置中为您的 _Debug_ 配置将 -DDEBUG
添加到**其他 Swift 标志**。
pod 'SwiftTweaks'
# Enable DEBUG flag in Swift for SwiftTweaks
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == 'SwiftTweaks'
target.build_configurations.each do |config|
if config.name == 'Debug'
config.build_settings['OTHER_SWIFT_FLAGS'] = '-DDEBUG'
end
end
end
end
end
不!无论您喜欢在哪里/如何,只需创建一个 TweaksViewController
,如下所示
let tweaksVC = TweaksViewController(tweakStore: ExampleTweaks.defaultStore, delegate: self)
当然!您可以使用唯一的 storeName
标识符初始化它们的 defaultStore
,如下所示
public struct FirstTweaksLibrary: TweakLibraryType {
// ...
public static let defaultStore: TweakStore = {
let allTweaks: [TweakClusterType] = //...
return TweakStore(
tweaks: allTweaks,
storeName: "FirstTweaksLibrary", // Here's the identifier
enabled: tweaksEnabled
)
}()
}
虽然 Tweak<T>
是通用的,但我们必须将 T
限制为 TweakableType
,以便我们可以保证每种 T
都可以呈现在我们的编辑界面中并持久保存在磁盘上。 更多类型会很棒! 支持字典、闭包和其他东西会很棒。
如果您想扩展 TweakableType
,您需要扩展一些内部组件,如 TweakViewDataType
、TweakDefaultData
、TweakViewData
和 TweakPersistency
。 如果您想添加新类型,请随时打开 pull request!
也许您正在使用不同的动画框架,或者想要一个用于 CGRect
或类似的东西的模板 - 太棒了! 只要模板的可调整“组件”符合 TweakableType
,一切就绪。 创建一个新的 TweakGroupTemplateType
,并查看现有模板以获取实现建议。(您可能也想使用 SignedNumberTweakDefaultParameters
- 它们非常有用!)
如果您认为您的 TweakGroupTemplateType
会帮助其他人,请提交 pull request!