改进
为何
改进应用程序的最佳方式是每天都使用它。即使是那些可以提前测试出的想法——例如使用 Origami ——在实际应用程序中应用这些想法仍可能需要一些时间。
偶尔,第一次尝试就可能是完美的。有时,这个想法根本不起作用。但通常,它只需要一些小的调整。这正是改进用武之地。改进使得这些小调整变得容易:无需代码更改和电脑,您就可以尝试不同的选项并决定哪个效果最好。
一些最有用的调整参数包括动画时间、速度阈值、颜色和物理常数。在 Facebook,我们还在开发期间临时禁用新功能。这样,相关的设计师和工程师可以在他们的设备上启用它,而不会妨碍其他人测试应用程序。
改进对建造 Paper 至关重要。我们希望它对您的应用也很有用。
使用方法
每个可配置的值称为调整项。有多种方法设置它们,可以在 FBTweakInline.h
中找到。
值
创建调整项的最简单方法是使用 FBTweakValue
替换一个常量。
CGFloat animationDuration = FBTweakValue(@"Category", @"Group", @"Duration", 0.5);
前三个参数是调整项的列表位置和名称,最后一个参数是默认值。可以为默认值传递多种类型的值:布尔值、数字或字符串。
if (FBTweakValue(@"Category", @"Feature", @"Enabled", YES)) {
label.text = FBTweakValue(@"Category", @"Group", @"Text", @"Tweaks example.");
}
在发布构建中,FBTweakValue
宏展开为仅仅是默认值,因此没有性能影响。但在调试构建中,它将检索调整项的最新值。
您还可以传递第五个参数,这将限制调整项的可能值。第五个参数可以是数组、字典或 FBTweakNumericRange
。如果是字典,则值应显示在列表选项中的字符串。数组将显示值的 description
作为选项。(注意,您必须将数组和字典字面量用一对额外的大括号括起来。)
self.initialMode = FBTweakValue(@"Header", @"Initial", @"Mode", @(FBSimpleMode), (@{ @(FBSimpleMode) : @"Simple", @(FBAdvancedMode) : @"Advanced" }));
对于数值调整项(NSInteger
、CGFloat
等),您可以传递两个参数,这些参数将值限制为 FBTweakNumericRange
。
self.red = FBTweakValue(@"Header", @"Colors", @"Red", 0.5, 0.0, 1.0);
绑定
要使调整项实时更新,可以使用 FBTweakBind
。
FBTweakBind(self.headerView, alpha, @"Main Screen", @"Header", @"Alpha", 0.85);
第一个参数是绑定到的对象,第二个参数是属性。每当调整项被更改时,self.headerView
的 alpha
属性便会更新以匹配。一些更多示例
FBTweakBind(audioPlayer, volume, @"Player", @"Audio", @"Volume", 0.9);
FBTweakBind(webView.scrollView, scrollEnabled, @"Browser", @"Scrolling", @"Enabled", YES);
与 FBTweakValue
类似,在发布构建中 FBTweakBind
展开为仅仅是设置属性为默认值。
动作
动作允许您在选中调整项时运行一个(全局)块。要创建一个,请使用 FBTweakAction
。
FBTweakAction(@"Player", @"Audio", @"Volume", ^{
NSLog(@"Action selected.");
});
前三个参数是标准的调整项列出信息,最后一个参数是要调用的块。您可以在任何范围内使用 FBTweakAction
,但块必须是全局的:它不能依赖于任何局部或实例变量(它不知道应该调整哪个对象)。
动作对于启动调试 UI、检查更新,或者(如果您创建了一个有意崩溃的动作)测试崩溃报告非常有用。
调整UI
要配置你的调整,你需要一种方式来显示配置UI。为此有两个选择
- 传统上,调整通过摇晃手机激活。要使用此方法,只需将你的根
UIWindow
替换为FBTweakShakeWindow
。如果你在使用Storyboards,可以覆盖应用代理中的-window
- (UIWindow *)window
{
if (!_window) {
_window = [[FBTweakShakeWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
}
return _window;
}
- 你可以在应用的任何地方呈现
FBTweakViewController
。确保将激活UI限制在调试构建中!
- (void)showTweaks {
FBTweakViewController *tweakVC = [[FBTweakViewController alloc] initWithStore:[FBTweakStore sharedInstance]];
tweakVC.tweaksDelegate = self;
// Assuming this is in the app delegate
[self.window.rootViewController presentViewController:tweakVC animated:YES completion:nil];
}
- (void)tweakViewControllerPressedDone:(FBTweakViewController *)tweakViewController {
[tweakViewController dismissViewControllerAnimated:YES completion:NULL];
}
调整UI关闭通知
另外,当调整UI关闭时,你可以注册你的通知中心来监听 FBTweakShakeViewControllerDidDismissNotification
,这可以通过导入 FBTweakViewController.h
后使用
高级
你还可以访问上述宏所组成的对象。这在更复杂的场景中很有用,例如调整C结构体成员。
例如,手动创建一个调整
FBTweak *tweak = [[FBTweak alloc] initWithIdentifier:@"com.tweaks.example.advanced"];
tweak.name = @"Advanced Settings";
tweak.defaultValue = @NO;
FBTweakStore *store = [FBTweakStore sharedInstance];
FBTweakCategory *category = [[FBTweakCategory alloc] initWithName:@"Settings"];
[store addTweakCategory:category];
FBTweakCollection *collection = [[FBTweakCollection alloc] initWithName:@"Enable"];
[category addTweakCollection:collection];
[collection addTweak:tweak];
[tweak addObserver:self];
然后,你可以侦听调整何时发生变化
- (void)tweakDidChange:(FBTweak *)tweak
{
self.advancedSettingsEnabled = ![tweak.currentValue boolValue];
}
此外,你有实现可选方法 tweakWillChange:
的能力,以便处理调整的前一个值
- (void)tweakWillChange:(FBTweak *)tweak
{
NSLog(@"%@", tweak.currentValue); // Here current value is the previous value of the tweak
}
要覆盖调整启用时的行为,可以定义 FB_TWEAK_ENABLED
宏。建议在提交到App Store时避免包含它们。
从Swift项目中使用
Khan Academy的Swift项目 SwiftTweaks 专为Swift设计,可能更适合Swift项目。
调整可以从Swift项目中使用。在这种情况下,定义在 FBTweakInline.h
中的方便快捷宏不可用,因此调整需要以程序方式创建,类似于以下示例
let tweak = FBTweak(identifier: "com.tweaks.example.advanced")
tweak.name = "Advanced settings"
tweak.defaultValue = false
let collection = FBTweakCollection(name: "Enable");
collection.addTweak(tweak)
let category = FBTweakCategory(name: "Settings")
category.addTweakCollection(collection);
let store = FBTweakStore.sharedInstance()
store.addTweakCategory(category)
tweak.addObserver(self)
设置调整后,你可以侦听它何时发生变化
func tweakDidChange(tweak: FBTweak!)
{
self.advancedSettingsEnabled = tweak.currentValue as Bool;
}
工作原理
在调试构建中,修改宏使用 __attribute__((section))
静态存储关于每个修改的数据在 mach-o 的 __FBTweak
部分。修改在启动时加载数据,并从 NSUserDefaults
加载最新值。
在发布版本中,宏仅展开为默认值。二进制中不包含任何其他内容。
安装
有两种选择
- 修改在 CocoaPods 中作为
Tweaks
提供。 (如果您有自定义 Xcode 配置的问题,这篇评论可能有所帮助。) - 手动将
FBTweak/
中的文件添加到您的 Xcode 项目中。略简单,但更新也是手动的。
修改需要 iOS 6 或更高版本。
还有一个示例项目可供使用。要使用它,请确保打开 FBTweakExample.xcworkspace
(而不是 .xcodeproj
),以便正确构建依赖项。
贡献
请参阅 CONTRIBUTING 文件了解如何帮助。
许可
修改采用 BSD 许可。我们还提供额外的专利许可。