SwiftTweaks
在不重新编译的情况下即时调整您的 iOS 应用!
您的用户不会看到您的动画研究、Sketch 组件或原型。他们将会看到的是成品——因此确保您的应用程序在实际设备上感觉正确非常重要!
在您的笔记本电脑上看起来很棒的动画在使用时可能感觉太慢。在 27 英寸显示器上看起来完美的布局可能在小 4 英寸设备上显得过于拥挤。浅灰色文本在 Sketch 上可能看起来很微妙,但在阳光明媚的日子里在外面却几乎无法辨认。
这些动画时长、字体大小和颜色选择都是“魔法数字”的例子——这些常数赋予您的应用程序可用性和身份。SwiftTweaks 的目标:允许您在不等待 Xcode 重建应用程序的情况下,在 Swift 项目的调试构建中微调这些魔法数字。
概览
使用 Tweak
代替代码中的布尔值、数字或颜色。您可以调整该 Tweak
而无需重新编译,这意味着您可以玩转动画时长、颜色和布局,而无需使用 Xcode!
目前,您可以调整以下类型
布尔值
整型
CGFloat
双精度浮点型
UIColor
TweakAction
字符串
字符串选项
一个 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
类型——当您需要使用可以一起使用的 tweak 集合以达到某种效果时,它们非常有用。它们可以由任何组合的 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)
等等,Facebook Tweaks 呢?
这是一个很好的问题!很高兴你问了。SwiftTweaks 存在的根本原因是因为我们特别喜欢 FBTweaks。 我们是 Objective-C 项目中长期支持 FBTweaks 的粉丝:用 FBTweak
宏替换魔法数字,然后你就大功告成了!您可以把 FBTweak 宏留在您的生产代码中,因为在编译时它会用特设的默认值替换掉。
但是 Swift 不支持这种魔术宏,所以 FBTweaks 在 Swift 代码中使用起来有些麻烦。我们的应用程序几乎全部是用 Swift 编写的,所以我们想看是否可以使其更易于使用!
调整步骤
将 SwiftTweaks 添加到项目中有三个步骤:
- 创建一个
TweakLibraryType
,它包含一组Tweak
和用于持久化它们的TweakStore
。 - 参考该
TweakLibraryType
以使用一个Tweak
。 - 在您的 AppDelegate 中,将
TweakWindow
设为您应用程序的窗口(还有其他选项,但这是最直接的方法!稍后会详细介绍。)
现在构建并运行,然后摇动手机以弹出 Tweaks UI!调整特设,在满意后,您可以从此 Tweaks UI 中与他人共享您的特设。
第一步:创建 TweakLibrary
调整库负责列出大量 public static
调整,并构建一个 TweakStore
。一个调整库看起来是这样的
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
中我们有五个调整:一个着色颜色,用于布局的两个CGFloat
,一个用于字体选择的StringOption
,以及一个切换开发中功能的Bool
。 - 编译器可能会在
Int
、CGFloat
和Double
之间混淆 —— 所以你可能需要告诉Tweak<T>
它的T
是什么类型 —— 就像我们在我们的外边距调整中这样做一样。 - 我们通过创建一个
TweakStore
来创建一个defaultStore
,它需要知道调整是否被启用
,以及所有调整的列表。 - 在
TweakStore
中存在启用
标志,以便在产品中用户无法访问SwiftTweaks
。你可以随意设置它;我们喜欢使用项目构建设置中的DEBUG
标志。
第二步:使用您的 TweakLibrary
要使用调整,您可以将代码中的数字或 UIColor
替换为 Tweak
引用,如下所示
这是我们的原始代码
button.tintColor = UIColor.green
assign 返回调整的当前值
button.tintColor = ExampleTweaks.assign(ExampleTweaks.colorTint)
bind 立即调用其闭包,并且在调整更改时再次调用
ExampleTweaks.bind(ExampleTweaks.colorTint) { button.tintColor = $0 }
bindMultiple 立即调用其闭包,并且在任何调整更改时再次调用
// 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
文件。
第三步:将 TweakWindow 设置为您的根视图控制器
默认情况下,SwiftTweaks 使用摇晃手势来弹出 UI,但您也可以使用自定义手势!
安装
Carthage
要将 SwiftTweaks
添加到您的应用程序中,请将其添加到您的 Cartfile
github "Khan/SwiftTweaks"
此外,将-DDEBUG
添加到项目构建设置中的其他Swift标志,针对您的调试配置。
CocoaPods
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
常见问题解答(FAQ)
我是否需要将TweakWindow设置为应用程序的根组件?
不必!您可以根据喜好在哪里创建,就像这样创建一个TweaksViewController
let tweaksVC = TweaksViewController(tweakStore: ExampleTweaks.defaultStore, delegate: self)
TweakLibraryType
?
我能否在应用程序中安装多个当然可以!您可以用唯一的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?
虽然Tweak<T>
是泛型,但我们必须限制T
为TweakableType
,以便我们可以在编辑界面中显示每种类型的对象并将它们保存在磁盘上。支持更多类型将很棒!支持字典、闭包和其他东西会很有趣。
如果你想扩展TweakableType
,你需要扩展一些内部组件,如TweakViewDataType
、TweakDefaultData
、TweakViewData
和TweakPersistency
。如果你想要添加一个新类型,请随时打开一个拉取请求!
如何创建一个新的TweakGroupTemplate?
可能你正在使用不同的动画框架,或者想要一个针对 CGRect
或类似内容的模板 - 太棒了!只要你的模板中可调整的“组件”遵循 TweakableType
,那么你就可以开始了。创建一个新的 TweakGroupTemplateType
,并查看现有的模板以获取实现建议。(你可能还需要使用 SignedNumberTweakDefaultParameters
,它们非常有帮助!)
如果你认为你的 TweakGroupTemplateType
可以为他人提供帮助,请提出一个拉取请求!