├── README.md ├── chapters ├── 1.md ├── 10.md ├── 2.md ├── 3.md ├── 4.md ├── 5.md ├── 6.md ├── 7.md ├── 8.md └── 9.md └── images ├── bash-create.png ├── brew.png ├── building.png ├── control-zebra.png ├── dependencies.png ├── final-build.png ├── hidden-property.png ├── iphone-dock.png ├── layout-prefs-main.png ├── mshookivar.png ├── prefs-choose.png ├── prefs-header-file.png ├── prefs-init.png ├── prefs-layout.png ├── prefs-main-file.png ├── sdks-folder.png ├── set-theos.png ├── theos-clone.png ├── theos-template.png ├── tweak-1.png ├── tweak-author.png ├── tweak-filter.png ├── tweak-folder.png ├── tweak-identifier.png ├── tweak-name.png ├── vscode-1.png └── xcode-select.png /README.md: -------------------------------------------------------------------------------- 1 | # TweakGuide 2 | 3 | This guide was created to help with the frequent Reddit posts asking how to get into developing iOS tweaks. A common misconception is that a full knowledge of Objective-C is needed to create tweaks. Whether you have any programming experience or not, I will try to step through the process from zero knowledge to creating your first tweak. I have decided to break this into chapters, from installing a text editor, to building a full tweak to be uploaded to a repo. This guide will be updated to add new topics, and is assuming you are using a computer to write tweaks, although the methods should work for writing tweaks on iOS. This is focused on Mac and Linux installations, if you are using Windows I suggest using [WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10) (Windows Subsystem for Linux) 4 | 5 | ## Requirements 6 | 7 | * A text editor 8 | * A Theos installation 9 | * A jailbroken iOS device 10 | 11 | ## Useful resources 12 | 13 | [iPhone Development Wiki](https://iphonedevwiki.net/index.php/Main_Page) 14 | 15 | [Limneos Headers](https://developer.limneos.net) 16 | 17 | [My open source tweaks](https://github.com/MTACS) 18 | 19 | [Other open source tweaks](https://iphonedevwiki.net/index.php/Open_Source_Projects) 20 | 21 | ## Chapter Index 22 | 23 | [Chapter 1: Installing Theos & Configuring your environment](https://github.com/MTACS/TweakGuide/blob/master/chapters/1.md) 24 | 25 | [Chapter 2: Creating your first tweak](https://github.com/MTACS/TweakGuide/blob/master/chapters/2.md) 26 | 27 | [Chapter 3: Editing your tweak](https://github.com/MTACS/TweakGuide/blob/master/chapters/3.md) 28 | 29 | [Chapter 4: Control files](https://github.com/MTACS/TweakGuide/blob/master/chapters/4.md) 30 | 31 | [Chapter 5: Logos](https://github.com/MTACS/TweakGuide/blob/master/chapters/6.md) 32 | 33 | [Chapter 6: Writing code](https://github.com/MTACS/TweakGuide/blob/master/chapters/6.md) 34 | 35 | [Chapter 7: Using MSHookIvar](https://github.com/MTACS/TweakGuide/blob/master/chapters/7.md) 36 | 37 | [Chapter 8: Building & Packaging](https://github.com/MTACS/TweakGuide/blob/master/chapters/8.md) 38 | 39 | [Chapter 9: Preference Bundles](https://github.com/MTACS/TweakGuide/blob/master/chapters/9.md) 40 | 41 | [Chapter 10: Linking Preferences](https://github.com/MTACS/TweakGuide/blob/master/chapters/10.md) 42 | 43 | ## Contributing 44 | 45 | If you feel something should be changed or added to this guide, create a pull request. 46 | 47 | ## Contact & Support 48 | 49 | This project wouldn't be possible without the help from [@2Klasic](https://twitter.com/2Klasic) who kickstarted my tweak development by setting up my first repo, definitely give him a follow. 50 | 51 | I can be reached at the following, and am always open to answering any questions about tweak development or jailbreak in general. 52 | 53 | [Twitter](https://twitter.com/mtac8) 54 | 55 | [GitHub](https://github.com/MTACS) 56 | 57 | [Reddit](https://reddit.com/u/-MTAC-) 58 | 59 | This guide took a long time to plan and create. If you want to support otherwise, here is my [PayPal](https://paypal.me/mtac) or by grabbing a copy of my tweak [Lynx](https://repo.twickd.com/package/com.twickd.mtac.lynx) from [Twickd Repo](https://repo.twickd.com) 60 | -------------------------------------------------------------------------------- /chapters/1.md: -------------------------------------------------------------------------------- 1 | # Chapter 1: Installing Theos & Configuring Your Environment 2 | 3 | Theos is a build system to help developers make tweaks easier. It was built to work on most systems, and uses [Logos](https://iphonedevwiki.net/index.php/Logos) to make hooking iOS much easier. 4 | 5 | In order to write your tweaks, you must have a text editor. While most built in editors will work, a editor that is built for writing code will make your life so much easier. This tutorial will be using Visual Studio Code (VSCode), but that is totally your choice. I chose VSCode because of its support for Objective-C syntax highlighting and built in terminal window, and works on Mac, Linux and Windows. A list of popular editors are linked below 6 | 7 | * [Visual Studio Code](https://code.visualstudio.com/) 8 | * [Atom](https://atom.io/) 9 | * [Sublime Text](https://www.sublimetext.com/3) 10 | 11 | # Terminal 12 | 13 | A terminal is required to build, debug and install tweaks. Despite my Mac having Terminal installed by default, I also suggest another app such as [iTerm 2](https://www.iterm2.com/). For Linux, you can find a terminal simply by searching for it in your operating system's search function. 14 | 15 | On Mac and Linux systems, each user has a specific file that allows for the customization of the terminal. Since I use ZSH as my shell, mine is located at ```~/.zshrc``` with the ```~``` representing my home folder ```/Users/mtac/```, although for most users, the file is name ```~/.bash_profile``` 16 | 17 | I have set up some terminal shortcuts to help with the building and writing of tweaks. Below is a snippet of my ```~/.zshrc``` (or ```~/.bash_profile```) and I highly suggest you add them to your terminal configuration file to help with typing the same commands over and over. 18 | 19 | ```bash 20 | alias c="clear" 21 | alias tweak="$THEOS/bin/nic.pl" 22 | alias tweaks="cd ~/Documents/Tweaks" 23 | alias install="find . -name '.DS_Store' -type f -delete; make clean; make package install" 24 | ``` 25 | 26 | This way when you type the word following ```alias``` your system will run the command inside the quotation marks, saving time. Here ```c``` stands for the command ```clear``` which clears the current terminal window of all previous output, ```tweak``` displays Theos' templates for a new tweak, ```tweaks``` changes the current working directory to the folder where all your tweaks are stored, and ```install``` removes unnecessary hidden files, cleans the build and installs it to your device. Note that this is built for macOS, and ```find . -name '.DS_Store' -type f -delete``` will not work on Linux. You can use these aliases to make shortcuts to commands for anything you like! 27 | 28 | Add these shortcuts to your terminal by following the steps below: 29 | 30 | Open a new terminal window and enter the following command in order to create a bash profile: 31 | 32 | ```bash 33 | nano ~/.bash_profile 34 | ``` 35 | 36 | ![bash-create](https://github.com/MTACS/TweakGuide/blob/master/images/bash-create.png) 37 | 38 | Once the new window is open you will then need to create your bash profile entries: 39 | 40 | ```bash 41 | export Path="/usr/local/sbin:$PATH" 42 | export THEOS="~/theos" 43 | 44 | alias c="clear" 45 | alias tweak="$THEOS/bin/nic.pl" 46 | alias tweaks="cd ~/Documents/Tweaks" 47 | alias install="find . -name '.DS_Store' -type f -delete; make clean; make package install" 48 | ``` 49 | Now lets save your bash enteries: 50 | 51 | ```bash 52 | Save the entries by pressing 53 | Ctrl+O and then Enter 54 | 55 | Close the editor by pressing 56 | Ctrl+X 57 | ``` 58 | Reload bash profile: 59 | 60 | ```bash 61 | source ~/.bash_profile 62 | ``` 63 | Create your tweaks directory (change this to anything you like): 64 | 65 | ```bash 66 | mkdir -p ~/Documents/Tweaks 67 | ``` 68 | 69 | # Installing Theos 70 | 71 | A full detailed guide is available [here](https://github.com/theos/theos/wiki/Installation) from the official Theos GitHub page. I will go over an installation on macOS here however. 72 | 73 | There are a few requirements that you must install before using Theos to build tweaks. First install [Xcode](https://apps.apple.com/us/app/xcode/id497799835?mt=12) from the Mac AppStore. Once this is installed, run the following code inside your terminal to install the required Command Line Tools 74 | 75 | ```xcode-select --install``` 76 | 77 | ![xcode-select](https://github.com/MTACS/TweakGuide/blob/master/images/xcode-select.png) 78 | 79 | This will pop up a window, and it may take a few minutes for it to install. Next we will install [Homebrew](https://brew.sh/) which is a package manager for macOS to help install the required dependencies. Install it by running the following command inside your terminal 80 | 81 | ```/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"``` 82 | 83 | ![homebrew](https://github.com/MTACS/TweakGuide/blob/master/images/brew.png) 84 | 85 | Packages can be installed by running ```brew``` followed by the name of the package. To install these dependencies run the following command inside a terminal 86 | 87 | ```brew install ldid xz``` 88 | 89 | ![dependencies](https://github.com/MTACS/TweakGuide/blob/master/images/dependencies.png) 90 | 91 | Now clone Theos to the directory you specified 92 | 93 | ```git clone --recursive https://github.com/theos/theos.git $THEOS``` 94 | 95 | ![theos-clone](https://github.com/MTACS/TweakGuide/blob/master/images/theos-clone.png) 96 | 97 | Lastly, we must use patched SDK's (Software Development Kits) with Theos. This is because Apple does not include the private frameworks that are used in tweaks. These can be downloaded from the official source [here](https://github.com/theos/sdks) or via my website [here](https://mtac.app/sdks/). Place these inside the sdks folder in your theos installation directory 98 | 99 | ![sdks-folder](https://github.com/MTACS/TweakGuide/blob/master/images/sdks-folder.png) 100 | 101 | [Home](https://github.com/MTACS/TweakGuide/blob/master/README.md) | [Chapter 2: Creating your first tweak](https://github.com/MTACS/TweakGuide/blob/master/chapters/2.md) 102 | -------------------------------------------------------------------------------- /chapters/10.md: -------------------------------------------------------------------------------- 1 | # Chapter 10: Linking Preferences 2 | 3 | Now we must link our preferences to the actual tweak. To do this, we will ```NSUserDefaults``` to store/read/write our preferences. Create a file called ```Tweak.h``` in the main tweak folder. 4 | 5 | The folder structure should now look like this. For future reference, the .vscode and .theos are arbitrary, they should be deleted before a tweak is open sourced 6 | 7 | ![layout-prefs-main](https://github.com/MTACS/TweakGuide/blob/master/images/layout-prefs-main.png) 8 | 9 | Copy and paste the following inside Tweak.h 10 | 11 | ```objective-c 12 | @interface NSUserDefaults (Centauri) 13 | - (id)objectForKey:(NSString *)key inDomain:(NSString *)domain; 14 | - (void)setObject:(id)value forKey:(NSString *)key inDomain:(NSString *)domain; 15 | @end 16 | ``` 17 | 18 | Next, we need to define two things, the domain in which ```NSUserDefaults``` reads our tweaks preferences, and the string that is posted when a value of a preference in that domain changes. 19 | 20 | Add the following to the Tweak.h 21 | 22 | ```objective-c 23 | static NSString *domain = @"com.mtac.testtweakprefs"; 24 | static NSString *PostNotificationString = @"com.mtac.testtweakprefs/preferences.changed"; 25 | static BOOL enabled; 26 | ``` 27 | 28 | The ```static BOOL enabled``` should be the key inside of our Root.plist 29 | 30 | Inside our Tweak.xm, add the following at the #1 line of the file ```#import "Tweak.h"``` this imports our header and allows for better organization of interface declarations, constants and is usually best practice. We need to add a constructor, as it is called with each new instance of the tweak. Copy and paste the following code, and then the file should match the image below 31 | 32 | ```objective-c 33 | static void notificationCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { 34 | NSNumber *enabledValue = (NSNumber *)[[NSUserDefaults standardUserDefaults] objectForKey:@"enabled" inDomain:domain]; 35 | enabled = (enabledValue) ? [enabledValue boolValue] : NO; 36 | } 37 | 38 | %ctor { 39 | notificationCallback(NULL, NULL, NULL, NULL, NULL); 40 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, notificationCallback, (CFStringRef)PostNotificationString, NULL, CFNotificationSuspensionBehaviorCoalesce); 41 | if (enabled) { 42 | %init(Tweak); 43 | } 44 | } 45 | ``` 46 | 47 | 48 | 49 | [Home](https://github.com/MTACS/TweakGuide/blob/master/README.md) | [Previous Chapter](https://github.com/MTACS/TweakGuide/blob/master/chapters/9.md) | [Chapter 10: PLACEHOLDER](https://github.com/MTACS/TweakGuide/blob/master/chapters/11.md) 50 | -------------------------------------------------------------------------------- /chapters/2.md: -------------------------------------------------------------------------------- 1 | # Chapter 2: Creating your first tweak 2 | 3 | Remember when we set up the aliases in our Terminal file for easier use? If you installed Theos to a different directory other than ```~/theos``` go back and change it to that. If everything is set up correctly, run the command ```tweaks``` to change to the folder where you will store your tweaks, then run ```tweak``` in Terminal, which should make an interface like this appear. 4 | 5 | ![theos-template](https://github.com/MTACS/TweakGuide/blob/master/images/theos-template.png) 6 | 7 | I will cover most of the options shown, but for now type the number corresponding to ```iphone/tweak``` for me it is 10. Enter a name for your tweak. I will be using the name testtweak to keep it simple for this tutorial 8 | 9 | ![tweak-name](https://github.com/MTACS/TweakGuide/blob/master/images/tweak-name.png) 10 | 11 | Enter a bundle identifier for your tweak. This part is important to remember as they should remain consistent and should be all lower case. I always use ```com.mtac.packagename``` for all my tweaks. For example my tweak Lynx uses the identifier ```com.mtac.lynx```. 12 | 13 | ![tweak-identifier](https://github.com/MTACS/TweakGuide/blob/master/images/tweak-identifier.png) 14 | 15 | Enter the name you want to appear as the author, obviously for me it is MTAC 16 | 17 | ![tweak-author](https://github.com/MTACS/TweakGuide/blob/master/images/tweak-author.png) 18 | 19 | This next step is important. Where it asks ```[iphone/tweak] MobileSubstrate Bundle filter [com.apple.springboard]:``` enter the bundle identifier of the app you want to hook. Here we just hit enter to leave it as the default, which is SpringBoard (com.apple.springboard). You should be very careful when setting this, if you only want to change one app, make sure this is set to the bundle identifier of it, otherwise issues can arise. We will go deeper into filtering and why it is important, especially when making system wide tweaks as explained [here](https://github/com/MTACS/TweakGuide). 20 | 21 | For ```[iphone/tweak] List of applications to terminate upon installation (space-separated, '-' for none) [SpringBoard]:``` again hit enter to set it to the default of SpringBoard. This is what Theos kills when the tweak is installed. This will be explained later on. 22 | 23 | Open the folder where your tweak was created and you should see this 24 | 25 | ![tweak-folder](https://github.com/MTACS/TweakGuide/blob/master/images/tweak-folder.png) 26 | 27 | [Home](https://github.com/MTACS/TweakGuide/blob/master/README.md) | [Previous Chapter](https://github.com/MTACS/TweakGuide/blob/master/chapters/1.md) | [Chapter 3: Editing your tweak](https://github.com/MTACS/TweakGuide/blob/master/chapters/3.md) 28 | -------------------------------------------------------------------------------- /chapters/3.md: -------------------------------------------------------------------------------- 1 | # Chapter 3: Editing your tweak 2 | 3 | Let's get your tweak opened in a text editor, and set everything up before we go into the workings of Logos and Objective-C. Below I am opening the folder in VSCode using ```CMD + O```. It should look something like this. 4 | 5 | ![vscode-1](https://github.com/MTACS/TweakGuide/blob/master/images/vscode-1.png) 6 | 7 | The latest versions of Theos create a file called ```Tweak.x```, but I prefer to rename it to Tweak.xm so I can use MobileSubstrate functions such as ```MSHookIvar```, which is a powerful way of modifying iOS and will be explained in great detail later on. 8 | 9 | Tweak.xm is the main file that you will be editing. This is where all the code for tweak is placed. In order for your tweak to build however, there are a few more steps that must be taken. Open your Makefile in the editor, and change it following the code below. 10 | 11 | ### Before 12 | 13 | ``` 14 | INSTALL_TARGET_PROCESSES = SpringBoard 15 | 16 | include $(THEOS)/makefiles/common.mk 17 | 18 | TWEAK_NAME = testtweak 19 | 20 | testtweak_FILES = Tweak.x 21 | testtweak_CFLAGS = -fobjc-arc 22 | 23 | include $(THEOS_MAKE_PATH)/tweak.mk 24 | ``` 25 | 26 | ### After 27 | 28 | ``` 29 | INSTALL_TARGET_PROCESSES = SpringBoard 30 | ARCHS = arm64 arm64e 31 | 32 | include $(THEOS)/makefiles/common.mk 33 | 34 | TWEAK_NAME = testtweak 35 | 36 | testtweak_FILES = Tweak.xm 37 | testtweak_CFLAGS = -fobjc-arc 38 | 39 | include $(THEOS_MAKE_PATH)/tweak.mk 40 | ``` 41 | 42 | At the top where you see the line ```ARCHS = , arm64 arm64e``` this is where we specify the architectures that the tweak will be built for. Since this guide is based on iOS 13, I will only be using ```arm64``` and ```arm64e```, but should work for tweaks built for iOS 7 and higher, and support iPhone 5s - iPhone X. These are important as iPhone XS and newer have a different architecture for the A12 and A13 chipsets, so make sure to include ```arm64e``` 43 | 44 | Next we will set up the IP address of your device in the Makefile. This will allow us to run the command ```install``` or ```make do```. To get the address of your device, go to Settings > Wi-Fi > Tap on the ⓘ next to your Wi-Fi network and note the numbers next to IP Address. For me, it is ```192.168.1.4```. Add this to your Makefile at the top like this: 45 | 46 | ``` 47 | THEOS_DEVICE_IP = 192.168.1.4 48 | 49 | ARCHS = arm64 arm64e 50 | 51 | include $(THEOS)/makefiles/common.mk 52 | 53 | TWEAK_NAME = testtweak 54 | 55 | testtweak_FILES = Tweak.xm 56 | testtweak_CFLAGS = -fobjc-arc 57 | 58 | include $(THEOS_MAKE_PATH)/tweak.mk 59 | 60 | after-install:: 61 | install.exec "sbreload" 62 | ``` 63 | 64 | When using Makefile, words that are capitalized are variables. These can be referenced by using a ```$(VARIABLE_NAME)```. 65 | 66 | ```THEOS_DEVICE_IP``` sets the address to which Theos will install the tweak to. 67 | 68 | ```ARCHS``` sets the architectures that Theos will build 69 | 70 | ```TWEAK_NAME``` is the name of the tweak. Sometimes tweaks may have more than one file to compile, so leave ```testtweak_FILES = Tweak.xm``` alone. The lines that include ```include $(THEOS)``` allows the tweak to use the Makefiles installed with Theos. 71 | 72 | ```$(THEOS)``` will always refer to the folder in which you installed Theos, and ```$(THEOS_MAKE_PATH)``` is a direct link to included Makefiles. 73 | 74 | [Home](https://github.com/MTACS/TweakGuide/blob/master/README.md) | [Previous Chapter](https://github.com/MTACS/TweakGuide/blob/master/chapters/2.md) | [Chapter 4: Control files](https://github.com/MTACS/TweakGuide/blob/master/chapters/4.md) 75 | -------------------------------------------------------------------------------- /chapters/4.md: -------------------------------------------------------------------------------- 1 | # Chapter 4: Control files 2 | 3 | Next we will edit our ```control``` file. This is the file that your package manager, and dpkg reads to show information about your Tweak. Edit this however you like, I always change the description and version. I like to use version numbers starting from 1.0.0, but this is totally your choice. This is what you will edit when upgrading a package. 4 | 5 | ``` 6 | Package: com.mtac.testtweak 7 | Name: testtweak 8 | Depends: mobilesubstrate 9 | Version: 0.0.1 10 | Architecture: iphoneos-arm 11 | Description: An awesome MobileSubstrate tweak! 12 | Maintainer: MTAC 13 | Author: MTAC 14 | Section: Tweaks 15 | ``` 16 | 17 | This is what our control file looks like for testtweak 18 | 19 | ``` 20 | Package: com.mtac.testtweak 21 | Name: Test Tweak 22 | Depends: mobilesubstrate 23 | Version: 1.0.0 24 | Architecture: iphoneos-arm 25 | Description: A test tweak for TweakGuide 26 | Maintainer: MTAC 27 | Author: MTAC 28 | Section: Tweaks 29 | ``` 30 | 31 | **Package:** is the identifier for the tweak that we created in [Chapter 2](https://github.com/MTACS/TweakGuide/blob/master/chapters/2.md). 32 | 33 | **Name:** is where you can rename your tweak. This is what will be shown in your package manager, and on a repo. 34 | 35 | **Depends:** is where you specify the packages that are required to be installed alongside your tweak in order for it to work properly. Here it says mobilesubstrate, which is the identifier for Mobile Substrate, the subsystem that all tweaks rely on. 36 | 37 | **Version:** As explained above, this doesn't really matter as long as you keep it consistent when updating your tweak: ```1.0.0 -> 1.0.1``` 38 | 39 | **Architecture:** Leave this how it is 40 | 41 | **Description:** Change this to a description of your tweak. It is not necessary to change this, but it is a pet peeve of mine when a tweak does not describe what it does when viewing it from a package manager. 42 | 43 | **Maintainer:** This should be set to the name we set in [Chapter 2](https://github.com/MTACS/TweakGuide/blob/master/chapters/2.md). 44 | 45 | **Author:** Also set in Chapter 2, this is what will be displayed as the author of the tweak 46 | 47 | **Section:** This can be changed to better organize where your tweak is located on a repo. Some common ones used are: Tweaks, Utilities, System, or Development. We can leave this as Tweaks for now. 48 | 49 | ## Example of control file data being shown in a package manager 50 | 51 | ![control-zebra](https://github.com/MTACS/TweakGuide/blob/master/images/control-zebra.png) 52 | 53 | [Home](https://github.com/MTACS/TweakGuide/blob/master/README.md) | [Previous Chapter](https://github.com/MTACS/TweakGuide/blob/master/chapters/3.md) | [Chapter 5: Logos](https://github.com/MTACS/TweakGuide/blob/master/chapters/5.md) 54 | -------------------------------------------------------------------------------- /chapters/5.md: -------------------------------------------------------------------------------- 1 | # Chapter 5: Logos 2 | 3 | Logos helps us developers hook, group and initialize parts of code, that would normally require a lot more code to write. I will show the basics of it, but a better detailed guide of Logos can be found [here](https://iphonedevwiki.net/index.php/Logos). 4 | 5 | ## Hooks - %hook 6 | 7 | You may have heard the term hooking before. This is what tweaks do. iOS is written mainly in Objective-C, and this allows us with the help of substrate/substitute to override values and change/add to the code that is already run. 8 | 9 | This is how hooks are done using Theos' Logos. ```%hook``` followed by the name of a [class](). When hooking a class, you must always end it with a corresponding ```%end```. This just tells Theos you are done with that class. When hooking something, I start by typing a ```%hook``` followed by three new lines and ending with a ```%end```. We will go more into Objective-C classes in the next chapter. 10 | 11 | ```objective-c 12 | %hook ClassName 13 | 14 | - (void)method; 15 | 16 | %end 17 | ``` 18 | 19 | ## Groups - %group 20 | 21 | Groups are used to break code into different sections. If your tweak is very simple and is only a few hooks this will not be necessary. As our testtweak gets more complicated over the course of the guide we will add groups, and show how to use them properly. Just like a ```%hook``` groups are closed with a ```%end```. 22 | 23 | ```objective-c 24 | %group GroupName 25 | 26 | %hook ClassName 27 | 28 | - (void)method; 29 | 30 | %end 31 | 32 | %end 33 | ``` 34 | 35 | Notice the two ```%end``` here, all hooks and groups must have a closing end. 36 | 37 | ## Constructors - %ctor 38 | 39 | A constructor is a piece of code that is run whenever a new instance of your tweak is loaded. If your tweak is only for one app, your constructor will be run every time the app is launched. For tweaks that modify system or SpringBoard stuff, the constructor can be called many times. This is why a constructor must be made properly, SpringBoard tweaks can accidentally be injected into processes that you did not intend to or even know about. Constructors must be used when using groups however, this is the only way to initialize one. Tweaks without a constructor will use a default hidden one which runs your hooks directly, treating them as their own default group. Notice unlike ```%hook``` or ```%group``` a constructor needs ```{}``` and does not require a ```%end```. 40 | 41 | ```objective-c 42 | %ctor { 43 | 44 | %init(GroupName); 45 | 46 | return; 47 | 48 | } 49 | ``` 50 | 51 | [Home](https://github.com/MTACS/TweakGuide/blob/master/README.md) | [Previous Chapter](https://github.com/MTACS/TweakGuide/blob/master/chapters/4.md) | [Chapter 6: Writing code](https://github.com/MTACS/TweakGuide/blob/master/chapters/6.md) 52 | -------------------------------------------------------------------------------- /chapters/6.md: -------------------------------------------------------------------------------- 1 | # Chapter 6: Writing code 2 | 3 | Here is where we will start writing the actual code for our tweak. It is important to start small, it is the easiest way to learn and can be used to build more complicated tweaks once you get the hang of Objective-C and Theos. When creating a tweak, think of something you want to change. For our test tweak, we will start by hiding the background of the Dock. 4 | 5 | I have mentioned the idea of classes a few times before. A class acts like a template, and can have properties that can be modified without affecting its parent class. In Objective-C and iOS, a class followed by a ```: OtherClass``` means its properties are inherited from ```OtherClass```. iOS uses the framework **UIKit** for all of the views displayed on the screen. This means that the base class ```UIView``` is the parent of most views. We can assume that any class that begins with UI is inherited from UIView and we can use its methods and properties without declaring them ourselves. 6 | 7 | To find which class to hook, I suggest downloading the tweak [Flexing](http://cydia.saurik.com/package/com.pantsthief.flexing/). To use this tweak, hold down on the Status Bar and a menu will appear. Click the arrow in the center and select the Dock. It may not appear in the list immediately so use the search bar to look for it 8 | 9 | ![iphone-dock](https://github.com/MTACS/TweakGuide/blob/master/images/iphone-dock.png) 10 | 11 | ```objective-c 12 | @interface UIView 13 | - (void)setBackgroundColor:(UIColor *)backgroundColor; 14 | @end 15 | 16 | @interface OurClass: UIView 17 | @end 18 | ``` 19 | 20 | Here we can see that the class OurClass is inherited from UIView. This means that the method ```- (void)setBackgroundColor:(UIColor *)backgroundColor;``` can be used by our class automatically. 21 | 22 | Before we get too ahead of ourselves, we should talk about Objective-C class declarations, methods, properties and instance variables. 23 | 24 | A method is a piece of code that can be called and runs code inside of it. The code above sets the background color of a view. Classes have properties and instance variables. Below is an example of the class SBDockView which managest the Dock on your homescreen. 25 | 26 | ```objective-c 27 | @interface SBDockView : UIView { 28 | UIView* _backgroundView; 29 | } 30 | @property (nonatomic, retain) UIView * backgroundView; 31 | @end 32 | ``` 33 | 34 | The piece between the ```{}``` is an instance variable or ivar for short. These can be modified using MSHookIvar. Under this we can see a ```@property```. This may seem redundant, but it is what allows us to access this variable. We can see that the ivar has a type of ```UIView```. This means if we want to hide the background of the Dock, we just need to hide this ivar. Lets hook ```SBDockView``` by adding this to our Tweak.xm. Notice we declared or put the interface of the class at the top of the file. 35 | 36 | There are a multitude of ways we can hide our background with. Each UIView has a few methods we can override to use. A common mistake is to use the method ```- (void)layoutSubviews``` as it exists on all UIViews, but this is where we must be smart. This is called many times, whenever the view changes. Adding code to this could cause it to be run many times as well, and could cause memory leaks and unwanted resprings. Most of the time you will be safe, but I **highly** suggest using other methods such as ```- (void)didMoveToWindow;``` as this is called once. 37 | 38 | ![tweak-1](https://github.com/MTACS/TweakGuide/blob/master/images/tweak-1.png) 39 | 40 | Next we must talk about ```%orig;``` and ```orig();```. This is a part of Logos that runs the code that Apple originally put inside a method. For instance in our ```- (void)didMoveToWindow {}``` we must add an ```%orig;``` in order for our Dock to function properly. Any code added after ```%orig;``` will be run after the original function. 41 | 42 | We will hide our background view using ```MSHookIvar``` in the next chapter 43 | 44 | [Home](https://github.com/MTACS/TweakGuide/blob/master/README.md) | [Previous Chapter](https://github.com/MTACS/TweakGuide/blob/master/chapters/5.md) | [Chapter 7: Using MSHookIvar](https://github.com/MTACS/TweakGuide/blob/master/chapters/7.md) 45 | -------------------------------------------------------------------------------- /chapters/7.md: -------------------------------------------------------------------------------- 1 | # Chapter 7: Using MSHookIvar 2 | 3 | MSHookIvar is a function included in Cydia Substrate that allows developers to hook a class' instance variable and make changes to it. This is what will allow us to modify our Dock background by itself. An example of MSHookIvar from the iPhone Dev Wiki shows what syntax to use 4 | 5 | ```c 6 | type ivar = MSHookIvar(object, ivar_name); 7 | ``` 8 | 9 | In our test tweak, add the following to grab the Dock's ivar for the background view. The first ```UIView *bgView``` is regular Objective-C syntax for creating a new variable. ```MSHookIvar<>();``` is the hooking function. Inside the ```<>``` we add our variable type again, followed by a ```*```. Inside the parenthesis, ```self``` is the class that contains the ivar. Self simply points to the class were hooking, but can be used with other classes such as ivars themselves. The name of the ivar goes inside the ```""```. Notice that there is no ```@``` before the name, this is C syntax and not Objective-C. Add the following to your code. 10 | 11 | ![mshookivar](https://github.com/MTACS/TweakGuide/blob/master/images/mshookivar.png) 12 | 13 | Now that we have our new hook UIView, we can make changes to this however we like. For our test tweak, let's hide the Dock. This is as simple as adding ```bgView.hidden = YES;``` 14 | 15 | ![hidden-property](https://github.com/MTACS/TweakGuide/blob/master/images/hidden-property.png) 16 | 17 | [Home](https://github.com/MTACS/TweakGuide/blob/master/README.md) | [Previous Chapter](https://github.com/MTACS/TweakGuide/blob/master/chapters/6.md) | [Chapter 8: Building & Packaging](https://github.com/MTACS/TweakGuide/blob/master/chapters/8.md) 18 | -------------------------------------------------------------------------------- /chapters/8.md: -------------------------------------------------------------------------------- 1 | # Chapter 8: Building & Packaging 2 | 3 | Now that our tweak is written, it's time to package it. To do this, open a terminal and ```cd``` to your tweak folder. If using VSCode, you can run it from the integrated shell by pressing ```⌘ + ` ``` or ```CTRL + ` ```. Now type ```make do``` followed by Enter. This will build your tweak and put the completed .deb inside the packages folder in your tweak directory. 4 | 5 | ![building](https://github.com/MTACS/TweakGuide/blob/master/images/building.png) 6 | 7 | Your tweak is packaged and ready to be uploaded to a repo or installed directly 8 | 9 | ![final-build](https://github.com/MTACS/TweakGuide/blob/master/images/final-build.png) 10 | 11 | [Home](https://github.com/MTACS/TweakGuide/blob/master/README.md) | [Previous Chapter](https://github.com/MTACS/TweakGuide/blob/master/chapters/7.md) | [Chapter 9: Preference Bundles](https://github.com/MTACS/TweakGuide/blob/master/chapters/9.md) 12 | -------------------------------------------------------------------------------- /chapters/9.md: -------------------------------------------------------------------------------- 1 | # Chapter 9: Preference Bundles 2 | 3 | If your tweak has many options, you might want to add a preference bundle. This will allow you full control over options, styles and anything you might want to change with your tweak. To add a preference bundle, open VSCode to your testtweak folder. Next, in the integrated terminal ```⌘ + ` ``` or ```CTRL + ` ``` and type tweak (this is the shortcut set up in [Chapter 1](https://github.com/MTACS/TweakGuide/blob/master/chapters/1.md)) and choose ```iphone/preference_bundle_modern```. Give this a name that is easy to remember, and is related to your tweak, I will choose testtweakprefs. Follow the steps which are almost identical to when making a tweak. Give it a bundle identifier, but make sure to use something you'll remember as the preferences we will use this as our prefs suite. When you get to the step where it asks for ```[iphone/preference_bundle_modern] Class name prefix (three or more characters unique to this project) [XXX]:``` choose anything you'd like as we'll be changing this later. 4 | 5 | ![prefs-init](https://github.com/MTACS/TweakGuide/blob/master/images/prefs-init.png) 6 | 7 | ![prefs-choose](https://github.com/MTACS/TweakGuide/blob/master/images/prefs-choose.png) 8 | 9 | Your tweak folder layout should look similar to this. 10 | 11 | ![prefs-layout](https://github.com/MTACS/TweakGuide/blob/master/images/prefs-layout.png) 12 | 13 | Rename your xxxRootListController.m and xxxRootListController.h files to something related to the tweak. I will use TestTweakListController. Make sure it is not named something simple like PreferencesListController, as PreferenceLoader might load another preference bundle when you click on your tweak. 14 | 15 | Inside TestTweakListController.m, rename the first line to the name of the ```.h``` file you just renamed. This ```#import``` just tells the compiler to look for an included header file. Now where it says ```@implementation xxxRootListController```, rename this to the same as before. 16 | 17 | TestTweakListController.h should look like this 18 | 19 | ![prefs-header-file](https://github.com/MTACS/TweakGuide/blob/master/images/prefs-header-file.png) 20 | 21 | TestTweakListController.m should look like this 22 | 23 | ![prefs-main-file](https://github.com/MTACS/TweakGuide/blob/master/images/prefs-main-file.png) 24 | 25 | Change the value of the key ```NSPrincipalClass``` inside the Info.plist file to that of the class in your .m (```TestTweakListController```). 26 | 27 | ```property-list 28 | 29 | 30 | 31 | 32 | CFBundleDevelopmentRegion 33 | English 34 | CFBundleExecutable 35 | testtweakprefs 36 | CFBundleIdentifier 37 | com.mtac.testtweakprefs 38 | CFBundleInfoDictionaryVersion 39 | 6.0 40 | CFBundlePackageType 41 | BNDL 42 | CFBundleShortVersionString 43 | 1.0.0 44 | CFBundleSignature 45 | ???? 46 | CFBundleVersion 47 | 1.0 48 | NSPrincipalClass 49 | TestTweakListController 50 | 51 | 52 | ``` 53 | 54 | In order for a tweak's preference pane to be loaded in Settings, it loads a .plist file for the tweak from ```/Library/PreferenceLoader/Preferences/```. For our tweak, this is the entry.plist file inside the testtweakprefs folder. Change the value for the key detail, from the current to ```TestTweakListController```. This must be exactly the same as your .m file or the bundle will not load. 55 | 56 | ```property-list 57 | 58 | 59 | 60 | 61 | entry 62 | 63 | bundle 64 | testtweakprefs 65 | cell 66 | PSLinkCell 67 | detail 68 | TestTweakListController 69 | icon 70 | icon.png 71 | isController 72 | 73 | label 74 | testtweakprefs 75 | 76 | 77 | 78 | ``` 79 | 80 | Next, inside the .m file again, there is an NSArray being return with the specifiers ```- (NSArray *)specifiers;```. This is loaded from the root file, and appears first when the section is opened in Settings. ```[self loadSpecifiersFromPlistName:@"Root" target:self];``` is self explanatory, and loads the specifiers as an array from Root.plist. 81 | 82 | Currently, our Root.plist should look like this. Edit the lines with comments. `````` 83 | 84 | ```property-list 85 | 86 | 87 | 88 | 89 | items 90 | 91 | 92 | cell 93 | PSGroupCell 94 | label 95 | testtweakprefs First Page 96 | 97 | 98 | cell 99 | PSSwitchCell 100 | default 101 | 102 | defaults 103 | com.mtac.testtweakprefs 104 | label 105 | Awesome Switch 1 106 | key 107 | AwesomeSwitch1 108 | 109 | 110 | title 111 | testtweakprefs 112 | 113 | 114 | ``` 115 | 116 | [Home](https://github.com/MTACS/TweakGuide/blob/master/README.md) | [Previous Chapter](https://github.com/MTACS/TweakGuide/blob/master/chapters/8.md) | [Chapter 10: Linking Preferences](https://github.com/MTACS/TweakGuide/blob/master/chapters/10.md) 117 | -------------------------------------------------------------------------------- /images/bash-create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/bash-create.png -------------------------------------------------------------------------------- /images/brew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/brew.png -------------------------------------------------------------------------------- /images/building.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/building.png -------------------------------------------------------------------------------- /images/control-zebra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/control-zebra.png -------------------------------------------------------------------------------- /images/dependencies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/dependencies.png -------------------------------------------------------------------------------- /images/final-build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/final-build.png -------------------------------------------------------------------------------- /images/hidden-property.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/hidden-property.png -------------------------------------------------------------------------------- /images/iphone-dock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/iphone-dock.png -------------------------------------------------------------------------------- /images/layout-prefs-main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/layout-prefs-main.png -------------------------------------------------------------------------------- /images/mshookivar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/mshookivar.png -------------------------------------------------------------------------------- /images/prefs-choose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/prefs-choose.png -------------------------------------------------------------------------------- /images/prefs-header-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/prefs-header-file.png -------------------------------------------------------------------------------- /images/prefs-init.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/prefs-init.png -------------------------------------------------------------------------------- /images/prefs-layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/prefs-layout.png -------------------------------------------------------------------------------- /images/prefs-main-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/prefs-main-file.png -------------------------------------------------------------------------------- /images/sdks-folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/sdks-folder.png -------------------------------------------------------------------------------- /images/set-theos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/set-theos.png -------------------------------------------------------------------------------- /images/theos-clone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/theos-clone.png -------------------------------------------------------------------------------- /images/theos-template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/theos-template.png -------------------------------------------------------------------------------- /images/tweak-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/tweak-1.png -------------------------------------------------------------------------------- /images/tweak-author.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/tweak-author.png -------------------------------------------------------------------------------- /images/tweak-filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/tweak-filter.png -------------------------------------------------------------------------------- /images/tweak-folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/tweak-folder.png -------------------------------------------------------------------------------- /images/tweak-identifier.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/tweak-identifier.png -------------------------------------------------------------------------------- /images/tweak-name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/tweak-name.png -------------------------------------------------------------------------------- /images/vscode-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/vscode-1.png -------------------------------------------------------------------------------- /images/xcode-select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/TweakGuide/37802701b02513f67160d64788521478a7ed4bf6/images/xcode-select.png --------------------------------------------------------------------------------