{"id":3180,"url":"https://github.com/facebookarchive/Tweaks","last_synced_at":"2025-08-03T13:32:11.096Z","repository":{"id":15008193,"uuid":"17733708","full_name":"facebookarchive/Tweaks","owner":"facebookarchive","description":"An easy way to fine-tune, and adjust parameters for iOS apps in development.","archived":true,"fork":false,"pushed_at":"2020-10-15T14:17:09.000Z","size":578,"stargazers_count":4740,"open_issues_count":23,"forks_count":417,"subscribers_count":145,"default_branch":"master","last_synced_at":"2024-10-29T17:49:56.731Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"House-FengFeng/Get-Link-Picasa","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/facebookarchive.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-03-14T02:58:52.000Z","updated_at":"2024-10-29T05:26:57.000Z","dependencies_parsed_at":"2022-09-05T07:40:26.858Z","dependency_job_id":null,"html_url":"https://github.com/facebookarchive/Tweaks","commit_stats":null,"previous_names":["facebook/tweaks"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebookarchive%2FTweaks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebookarchive%2FTweaks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebookarchive%2FTweaks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebookarchive%2FTweaks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/facebookarchive","download_url":"https://codeload.github.com/facebookarchive/Tweaks/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228548567,"owners_count":17935221,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-01-05T20:16:33.699Z","updated_at":"2024-12-07T01:30:39.443Z","avatar_url":"https://github.com/facebookarchive.png","language":"Objective-C","funding_links":[],"categories":["Tools","Objective-C","HarmonyOS"],"sub_categories":["Web View","Windows Manager"],"readme":"# Tweaks\nTweaks is an easy way to fine-tune an iOS app.\n[![Build Status](https://travis-ci.org/facebook/Tweaks.svg?branch=master)](https://travis-ci.org/facebook/Tweaks)\n\n![Tweaks](https://github.com/facebook/Tweaks/blob/master/Images/Tweaks.gif?raw=true)\n\n## Why\nThe best way to improve an app is to use it every day. Even when ideas can be tested out in advance — for example, with [Origami](http://origami.facebook.com) — it can still take some time with the app to see how it works in practice.\n\nOccasionally, it's perfect the first try. Sometimes, the idea doesn't work at all. But often, it just needs a few minor adjustments. That last case is where Tweaks fits in. Tweaks makes those small adjustments easy: with no code changes and no computer, you can try out different options and decide which works best.\n\nSome of the most useful parameters to adjust are animation timings, velocity thresholds, colors, and physics constants. At Facebook, we also use tweaks to temporarily disable new features during development. That way, the designers and engineers involved can enable it on just their devices, without getting in the way of others testing the app.\n\nTweaks was invaluable for building [Paper](http://www.facebook.com/paper). We hope it can be useful for your app too.\n\n## Usage\nEach configurable value is called a tweak. There's a few ways to set them up, found in `FBTweakInline.h`.\n\n### Value\nThe simplest way to create a tweak is to replace a constant with `FBTweakValue`:\n\n```objective-c\nCGFloat animationDuration = FBTweakValue(@\"Category\", @\"Group\", @\"Duration\", 0.5);\n```\n\nThe first three parameters are where the tweak is listed and what it's called, and the last one is the default value. You can pass in many types of values for the default: booleans, numbers, or strings.\n\n```objective-c\nif (FBTweakValue(@\"Category\", @\"Feature\", @\"Enabled\", YES)) {\n  label.text = FBTweakValue(@\"Category\", @\"Group\", @\"Text\", @\"Tweaks example.\");\n}\n```\n\nIn release builds, the `FBTweakValue` macro expands to just the default value, so there's no performance impact. In debug builds, though, it fetches the latest value of the tweak.\n\nYou can also pass a fifth parameter, which will constrain the possible values for a tweak. The fifth parameter can be an array, dictionary, or an `FBTweakNumericRange`. If it's a dictionary, the values should be strings to show in the list of choices. Arrays will show the values' `description` as choices. (Note that you have to surround array and dictionary literals with an extra set of parentheses.)\n\n```objective-c\nself.initialMode = FBTweakValue(@\"Header\", @\"Initial\", @\"Mode\", @(FBSimpleMode), (@{ @(FBSimpleMode) : @\"Simple\", @(FBAdvancedMode) : @\"Advanced\" }));\n```\n\nFor numeric tweaks (`NSInteger`, `CGFloat`, and others), you can instead pass two parameters, which constrain the value to a `FBTweakNumericRange`:\n\n```objective-c\nself.red = FBTweakValue(@\"Header\", @\"Colors\", @\"Red\", 0.5, 0.0, 1.0);\n```\n\n### Bind\nTo make tweaks update live, you can use `FBTweakBind`:\n\n```objective-c\nFBTweakBind(self.headerView, alpha, @\"Main Screen\", @\"Header\", @\"Alpha\", 0.85);\n```\n\nThe first parameter is the object to bind to, and the second is the property. Whenever the tweak is changed, `self.headerView`'s `alpha` property is updated to match. A few more examples:\n\n```objective-c\nFBTweakBind(audioPlayer, volume, @\"Player\", @\"Audio\", @\"Volume\", 0.9);\nFBTweakBind(webView.scrollView, scrollEnabled, @\"Browser\", @\"Scrolling\", @\"Enabled\", YES);\n```\n\nAs with `FBTweakValue`, in release builds `FBTweakBind` expands to just setting the property to the default value.\n\n## Action\nActions let you run a (global) block when a tweak is selected. To make one, use `FBTweakAction`:\n\n```objective-c\nFBTweakAction(@\"Player\", @\"Audio\", @\"Volume\", ^{\n  NSLog(@\"Action selected.\");\n});\n```\n\nThe first three parameters are the standard tweak listing information, and the last is a block to call. You can use `FBTweakAction` in any scope, but the block must be global: it can't depend on any local or instance variables (it wouldn't know which object to adjust).\n\nActions are useful for things like launching debug UIs, checking for updates, or (if you make one that intentionally crashes) testing crash reporting.\n\n### Tweaks UI\nTo configure your tweaks, you need a way to show the configuration UI. There's two options for that:\n\n - Traditionally, tweaks is activated by shaking your phone. To use that, just replace your root `UIWindow` with a `FBTweakShakeWindow`. If you're using Storyboards, you can override `-window` on your app delegate:\n\n```objective-c\n- (UIWindow *)window\n{\n  if (!_window) {\n    _window = [[FBTweakShakeWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];\n  }\n\n  return _window;\n}\n```\n\n - You can present a `FBTweakViewController` from anywhere in your app. Be sure to restrict the activation UI to debug builds!\n\n ```objective-c\n - (void)showTweaks {\n    FBTweakViewController *tweakVC = [[FBTweakViewController alloc] initWithStore:[FBTweakStore sharedInstance]];\n    tweakVC.tweaksDelegate = self;\n    // Assuming this is in the app delegate\n    [self.window.rootViewController presentViewController:tweakVC animated:YES completion:nil];\n}\n\n- (void)tweakViewControllerPressedDone:(FBTweakViewController *)tweakViewController {\n    [tweakViewController dismissViewControllerAnimated:YES completion:NULL];\n}\n```\n\n#### Tweaks UI Dismiss Notification\n\nAlternatively, when the Tweaks UI is dismissed, you can register your notification center to listen to `FBTweakShakeViewControllerDidDismissNotification`, which can be used after importing `FBTweakViewController.h` \n\n### Advanced\nYou can also access the objects that make up the macros mentioned above. That can be useful for more complex scenarios, like adjusting members of a C structure.\n\nFor example, to manually create a tweak:\n\n```objective-c\nFBTweak *tweak = [[FBTweak alloc] initWithIdentifier:@\"com.tweaks.example.advanced\"];\ntweak.name = @\"Advanced Settings\";\ntweak.defaultValue = @NO;\n\nFBTweakStore *store = [FBTweakStore sharedInstance];\nFBTweakCategory *category = [[FBTweakCategory alloc] initWithName:@\"Settings\"];\n[store addTweakCategory:category];\nFBTweakCollection *collection = [[FBTweakCollection alloc] initWithName:@\"Enable\"];\n[category addTweakCollection:collection];\n[collection addTweak:tweak];\n\n[tweak addObserver:self];\n```\n\nThen, you can watch for when the tweak changes:\n\n```objective-c\n- (void)tweakDidChange:(FBTweak *)tweak\n{\n  self.advancedSettingsEnabled = ![tweak.currentValue boolValue];\n}\n```\n\nAlso you have de ability to implement the optional method `tweakWillChange:` in order to handle the previous value of your tweak:\n\n```objective-c\n- (void)tweakWillChange:(FBTweak *)tweak\n{\n  NSLog(@\"%@\", tweak.currentValue); // Here current value is the previous value of the tweak\n}\n```\n\nTo override when tweaks are enabled, you can define the `FB_TWEAK_ENABLED` macro. It's suggested to avoid including them when submitting to the App Store.\n\n### Using from a Swift Project\n\n*Khan Academy's project [SwiftTweaks](http://engineering.khanacademy.org/posts/introducing-swifttweaks.htm) is designed for Swift, and might be a better choice for Swift projects.*\n\nTweaks can be used from Swift projects. In this case the handy shortcut macros defined in `FBTweakInline.h` are not available, meaning tweaks need to be created programmatically, similar to this example:\n\n```swift\nlet tweak = FBTweak(identifier: \"com.tweaks.example.advanced\")\ntweak.name = \"Advanced settings\"\ntweak.defaultValue = false\n\nlet collection = FBTweakCollection(name: \"Enable\");\ncollection.addTweak(tweak)\n        \nlet category = FBTweakCategory(name: \"Settings\")\ncategory.addTweakCollection(collection);\n        \nlet store = FBTweakStore.sharedInstance()\nstore.addTweakCategory(category)\n\ntweak.addObserver(self)\n```\n\nAfter setting up a tweak you can watch for when it changes:\n\n```swift\nfunc tweakDidChange(tweak: FBTweak!)\n{\n    self.advancedSettingsEnabled = tweak.currentValue as Bool;\n}\n```\n\n### How it works\nIn debug builds, the tweak macros use `__attribute__((section))` to statically store data about each tweak in the `__FBTweak` section of the mach-o. Tweaks loads that data at startup and loads the latest values from `NSUserDefaults`.\n\nIn release builds, the macros just expand to the default value. Nothing extra is included in the binary.\n\n## Installation\nThere are two options:\n\n 1. Tweaks is available as `Tweaks` in [CocoaPods](http://cocoapods.org). (If you have issues with custom Xcode configurations, [this comment](https://github.com/facebook/Tweaks/issues/4#issuecomment-40629741) might help.)\n 2. Manually add the files from `FBTweak/` into your Xcode project. Slightly simpler, but updates are also manual.\n\nTweaks requires iOS 6 or later.\n\nThere's also a demo project available. To use it, make sure to open `FBTweakExample.xcworkspace` (rather than the `.xcodeproj`) so the dependencies build correctly.\n\n## Contributing\nSee the CONTRIBUTING file for how to help out.\n\n## License\nTweaks is BSD-licensed. We also provide an additional patent grant.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffacebookarchive%2FTweaks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffacebookarchive%2FTweaks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffacebookarchive%2FTweaks/lists"}