SwiftTweaks 4.1.2

SwiftTweaks 4.1.2

Bryan Clark 维护。




SwiftTweaks

在不重新编译的情况下即时调整您的 iOS 应用!

SwiftTweaks Icon

您的用户不会看到您的动画研究、Sketch 组件或原型。他们将会看到的是成品——因此确保您的应用程序在实际设备上感觉正确非常重要!

在您的笔记本电脑上看起来很棒的动画在使用时可能感觉太慢。在 27 英寸显示器上看起来完美的布局可能在小 4 英寸设备上显得过于拥挤。浅灰色文本在 Sketch 上可能看起来很微妙,但在阳光明媚的日子里在外面却几乎无法辨认。

这些动画时长、字体大小和颜色选择都是“魔法数字”的例子——这些常数赋予您的应用程序可用性和身份。SwiftTweaks 的目标:允许您在不等待 Xcode 重建应用程序的情况下,在 Swift 项目的调试构建中微调这些魔法数字。

Tweaks

Carthage compatible Version GitHub release Swift 5.0 platforms Build Status

概览

使用 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 组成。

Tweaks

操作

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 添加到项目中有三个步骤:

  1. 创建一个 TweakLibraryType,它包含一组 Tweak 和用于持久化它们的 TweakStore
  2. 参考该 TweakLibraryType 以使用一个 Tweak
  3. 在您的 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
  • 编译器可能会在 IntCGFloatDouble 之间混淆 —— 所以你可能需要告诉 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>是泛型,但我们必须限制TTweakableType,以便我们可以在编辑界面中显示每种类型的对象并将它们保存在磁盘上。支持更多类型将很棒!支持字典、闭包和其他东西会很有趣。

如果你想扩展TweakableType,你需要扩展一些内部组件,如TweakViewDataTypeTweakDefaultDataTweakViewDataTweakPersistency。如果你想要添加一个新类型,请随时打开一个拉取请求!

如何创建一个新的TweakGroupTemplate?

可能你正在使用不同的动画框架,或者想要一个针对 CGRect 或类似内容的模板 - 太棒了!只要你的模板中可调整的“组件”遵循 TweakableType,那么你就可以开始了。创建一个新的 TweakGroupTemplateType,并查看现有的模板以获取实现建议。(你可能还需要使用 SignedNumberTweakDefaultParameters,它们非常有帮助!)

如果你认为你的 TweakGroupTemplateType 可以为他人提供帮助,请提出一个拉取请求!