How To Create MobileSubstrate Tweaks for iOS.

This tutorial has code and screenshots for both iOS 6 and under and iOS 7. Credit for adapting the code and the screenshot to the latest iOS version goes to anoadragon453 (anoa), a member of Saurik’s IRC channel.


Welcome to my second tutorial on iOS Open Development! In this tutorial, I will give you the first hand to get started with MobileSubstrate tweaks. If you are here, you should already know what MobileSubstrate is and why you would want to write tweaks for it, so I’m not going to get into too many details about MobileSubstrate and how it works.

Before we get started, there’s a couple of things I want to say first. First, if you don’t know what you are doing (new programmer, first time writing for iOS, whatever), then this is NOT a tutorial for you. MobileSubstrate protects the system from tweak errors and lousy programmers, but one can never be too careful. If you don’t know what you are doing, you could mess up your device, perhaps not bad enough to brick it, but bad enough to require a full restore. So if you follow this tutorial, I trust you know programming, have been doing it for a while, and that you take full responsibility of whatever happens to your device for writing “bad” tweaks.

Second, writing MobileSubstrate tweaks… There’s a lot you can do. It’s all about code hooking thanks to Objective-C’s dynamic nature and there’s a lot you can do with it. I cannot possibly teach you, not even in a thousand posts, everything you can modify with MobileSubstrate tweaks. This small tutorial is just meant to give you a hand getting started with tweaks. It’s not a comprehensive guide. It would really be impossible to write a full book about everything you could hook because there’s too much. Once you are finished with this guide, you will know enough about widgets and you will be able to research on your own: That is, once you are done with this tutorial, you will have to explore the private headers to find what you are looking for and hook it. Writing MobileSubstrate tweaks requires patience and familiarization with the private frameworks, so once you build your first project, start studying the private frameworks: I will tell you how to dump your own headers or where you can find headers that have already been dumped and modified for you to use.

Now, putting that aside…

In this tutorial you are going to write your first MobileSubstrate tweak. We will build a simple tweak that will show the user a message whenever he/she tries to open an app. Once the user taps an icon, we will display a message that says “Launching App…” and then we will launch the app once the user taps an “OK” button. Yes, it is a useless tweak, but you will learn a lot in your way.

In this tutorial, I will do the following:

I will explain you how to get the required headers to create tweaks.
I will explain what “hooking” code is in a nutshell
I will teach you how to hook code using Logos instead of the Objective-C runtime, so you will learn the basic Logos syntax along the way and you will be ready to hook your own things any time.
You will learn three very basic things but they should be powerful enough for you to write any tweak you can think of.

Okay, let’s get started!

First Things First: You Need The Private Headers To Work With.

You need to get the private iOS headers you want to “hook”. Otherwise, well, there’s nothing you can play with. So I will show you ways to do that.

The first and hardest method is to dump your own headers yourself using a command line tool called class-dump-z (or class-dump: refer to this post for more details on the tools). How to use this tools is beyond the scope of this tutorial but a word on them is due. Dumping your own headers is a tedious option. There’s a bunch of private frameworks and it can take a while to dump them all. Save each header to a respective framework directory when done.

Another (and easier) option is to download the headers from someone else. A lot of people have dumped their own headers and are hosting them free of charge on GitHub, so go on there and grab a copy. Personally, I recommend you use rpetrich’s headers, simply because he is a great developer with great reputation in the iOS open development community. But there’s lots of options out there shall you want/need them.

Once you have your headers downloaded, each header nicely inside a folder with the name of the framework, move or copy each framework to the directory called “include” inside the Theos directory. By default, you would save all the headers in the following location (Mac):

/opt/theos/include

Every private framework you download has to be saved there (so you can simple #import them when you want to use them, as you would include any other iOS framework in “official”, non-jailbreak projects).

That is all there is to downloading your headers: Once you are done, you can move on.

But Wait, What Exactly Is “Hooking”?

Objective-C is just a superset of C. Everyone who knows iOS or Mac programming knows that, and it’s the first thing a good book or tutorial on Objective-C tells you. But what exactly does this mean? It simply means that Objective-C has a lot of C code running under the hood. As so, you can freely mix any C code with Objective-C code.

Objective-C is mainly driven by what is called the Objective-C Runtime. The Objective-C Runtime is a C framework that, as you may imagine, controls everything that happens on Ojective-C under the hood. This runtime is responsible of creating classes, creating methods, ivars… Everything Objective-C does, is controlled by this run time. This runtime is in its most superficial level a bunch of C functions, and this framework is the reason Objective-C is such a dynamic language. This runtime can create classes, methods, ivars, and modify any of them along way on runtime rather than on compile time. Here are some functions provided by this framework:

class_addIvar
class_addMethod
objc_msgSend

This are just some functions found in the runtime. Their purpose is really clear: The first one adds an ivar to an existing class. The second one adds a method to an existing class, and the third one sends a message to a class.

Programmers can have full access to the Objective-C Runtime functions by just importing the framework as they would import anything else, granting them access to very powerful tools to modify running code as they wish on runtime and have a lot of control of whatever happens in their machine. In a running application, a developer can “hook” to a current method and make it behave like something completely to what was intended. In other words, to “hook” means to modify or extends the Objective-C code to do what you want. For example, someone could “hook” the NSString’s stringByAppendingString to append the passed parameter and to append a personal string at the end. Suppose I wanted that method to append “Leo” at the end of very string that receives that message. I could hook that method to append the wanted string and my own personal string at the end.

The Objective-C Runtime takes care of hooking. Writing tweaks require hooking, but the iOS Open development community has developed methods to abstract the Objective-C Runtime functions from the programmer. “Hooking” mechanisms have been created precisely to abstract the runtime and perhaps make it less intimidating. CaptainHook is one of them, and Logos is another one. Logos is a very nice hooking mechanism and it abstracts the runtime nicely with simple commands like “%hook” and “%orig”. No idea what I am talking about? In this tutorial I will show you how to create a tweak with Logos, so you will understand more once you see the actual tweak.

Without further ado, time to build the actual tweak and get your hands dirty. This is actually the shorter part of this tutorial but I hope everything I taught you so far will be useful for you in the future.

Getting Our Hands Dirty: Creating The MobileSubstrate Tweak

Alright, launch up the terminal and create a MobileSubstrate project (If this is your first time using Theos, or you don’t even have Theos installed yet, refer to this post. I mainly give links to instructions for installing Theos but the small content I dedicate to installation and configuring should help you getting started with it). I will call mine LaunchNotifier:

Once you have your project created, you will see a file called “Tweak.xm”. This is the file that has all the Logos hooking code and where you write your tweak. So open it up and be surprised for a short while at all that “%” syntax…

You also need to modify the makefile to add the UIKit framework. If you are in this tutorial you should know how to do that, but if you don’t, it’s very simply, just add this line:

LaunchNotifier_FRAMEWORKS = UIKit

And save it. That’s everything we need to do so close it now.

You will see a bunch of commented-out content. Please look at it for a while and try to understand it. It shows you the very basics of code hooking like:

%hook ClassName and %end. This is what I call a “Hook Block”. Everything you write in between is the block where you will be hooking things of the className (note that %hook and %end have no finishing semi-colon in their lines).
%orig calls the original version of the code you are hooking. You will find yourself calling %orig in all your methods most of the time, as they have most of the code needed for the code to be finished. Not calling %orig; can have disastrous consequences in your tweak, depending on what you are doing, although sometimes it’s desirable to avoid calling the original version of the method. Make sure you know when you want to call orig and when you don’t. Usually, it’s just common sense.
%orig(…) is %orig; but with arguments. In the parenthesis you pass in all the parameters to hand them over to the original method.
The rest of the commented code are examples for Logos. They can work, but in this tutorial I want to build something that works, because it’s easier to learn things with “real-world” examples.

Feel free to delete everything on that file for now. We will build everything from scratch (and it’s nothing too big, since it’s just a UIAlertView basically).

First things first, a quick review of what we are doing to do: When the user taps an icon in the SpringBoard, he will see a message telling him he’s about to launch an app.

Okay, so how do we do that? I need to say again, Tweak development requires lots of header browsing. You can never be certain of where things are. You know you want to a show message when an icon is tapped. You know icons are part of SpringBoard, so that’s a good start. You would head over to the SpringBoard framework folder and browse all the headers there. What are you looking for? Common sense is to be used here: You know, it’s an icon, so just look for anything that may have “Icon” on it’s name. What should you hook? You browse your headers for a while and find a class called SBIcon. Is this the one? Could be. Under normal circumstances, you would try to hook different classes and methods, writing code for them to do something (show an UIAlertView is a good idea), to see if you are hooking the right class and method. Okay, nothing interesting here. This can’t be the method. Oh, oh, what do I See? Is that a class called SBApplicationIcon? That sounds less generic and it may be exactly what you are looking for! In our case, yes, we want to hook that class.

You inspect that class and you see it has a method called -launch. Instinctively, we know this method will launch the respective app, so it makes sense to hook it.

The initial hooking will simply look like this:

%hook SBApplicationIcon
//Methods to hook here.
%end

Here we are just saying “I will hook some methods from the SBApplicationIcon class”.

-launch is the method that holds the magic for us, so to hook it, just write it’s implementation inside the hook block like you would anywhere else:

%hook SBApplicationIcon
-(void)launch
{
	//Hooked launch. What will it do now?
}
%end

And there you can just write any Objective-C code you want. We want to show a message, so just write a UIAlertView like this on iOS 6 and under:

%hook SBApplicationIcon
-(void)launch
{
	NSString *appName = [self displayName];
	NSString *message = [NSString stringWithFormat:@"The app %@ has been launched", appName, nil];
	UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:appName message:message delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
	[alert1 show];
	[alert1 release];
	%orig;
}
%end

Or this in iOS 7 and above (you can see we call %orig on this one, passing in the int parameter from the method’s signature:

@interface SBApplicationIcon
- (void)launchFromLocation:(int)arg;
- (id)displayName;
@end

%hook SBApplicationIcon

-(void)launchFromLocation:(int)location
{
	NSLog(@"Hello! I'm LaunchNotifier! Nice to meet you!");
	NSString *appName = [self displayName];
	NSString *message = [NSString stringWithFormat:@"The app %@ has been launched!", appName];
	UIAlertView *myAlert = [[UIAlertView alloc]initWithTitle:appName message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
	[myAlert show];
	[myAlert release];
	%orig(location);
}

%end

(the original -launch method from iOS 6 and under no longer exists on iOS 7)

And that’s really it! make package install your project (you should now that by now). Once the user taps an icon, the app will launch while showing a message:

(iOS 6)

(iOS 7)

A couple of things you have to note about the code we wrote above:

We are calling %orig;. If you don’t call %orig; here, your app won’t launch because you will override all the launch logic. Instead, you will just see your message but nothing will be launched. If a normal user installed this app (without the method calling %orig;), he/she would be screwed. Why? Because he/she wouldn’t be able to launch Cydia and uninstall it. The developer, on the other hand, can reverse the problem by simply fixing the problem and make package installing it again. This is why tweak programming is not for everyone and you should only do it if you plan on doing it well.
Note that we can call [self displayName]. Like I said, you can write any code like you normally code as you usually would, except you can “call hooks” whenever you want or need them.
Congratulations! You have now written your first MobileSubstrate tweak. If you have any questions, head over this post and ask all the questions you may have.

CHANGELOG:


Jan 4, 2014 at 5:03 PM [America/La_Paz]: Updated images. Added code and screenshot for iOS 7.
July 2, 2012 at 12:50 PM [America/La_Paz]: First version of this tutorial.

38 Comments

  1. Hi there,
    Great tutorial. I have tweak working using your instructions so thanks. However I now have an issue that I cant find a way around. My tweak creates a customer alertview with an image inside it. I can get the alertview to display. But not the image. THe code is correct as I have tested it outside a tweak (in a normal application). I believe the issue is that the system cant find the image file that my alert references.
    So question, how to do I package resources such as images into a tweak so that they are loaded and can be references at runtime
    For example i have the following line in my code:

    UIImageView *card2ImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"MasterCard"]];

    In my root folder i have the image [email protected]. I am testing on an iPhone 5.

    Reply
    • Don’t load images like that. Try to load them by creating a bundle and then load resources using that bundle.

      NSBundle *bundle = [[NSBundle bundleForClass:[self class]] retain];
      [bundle pathForResource:@"tweet" ofType:@"png"]
      Reply
  2. Hey andy, great tutorial.
    I followed it step by step but i keep getting an error when making the package. Here’s the error:

    mbp-di-erasmo:launchnotifier erasmo$ make
    /Users/erasmo/launchnotifier/theos/makefiles/targets/Darwin/iphone.mk:41: Deploying to iOS 3.0 while building for 6.0 will generate armv7-only binaries.
    Bootstrapping CydiaSubstrate…
    Compiling iPhoneOS CydiaSubstrate stub… default target? failed, what?
    Compiling native CydiaSubstrate stub…
    cp: /Users/erasmo/launchnotifier/theos/lib/libsubstrate.dylib: Permission denied
    Making all for tweak LaunchNotifier…
    Preprocessing Tweak.xm…
    Compiling Tweak.xm…
    Tweak.xm:16:85: error: use of undeclared identifier ‘icon’
    …_cmd, icon, location);
    ^
    1 error generated.
    make[2]: *** [obj/Tweak.xm.0481e318.o] Error 1
    make[1]: *** [internal-library-all_] Error 2
    make: *** [LaunchNotifier.all.tweak.variables] Error 2

    It’s my first time doing this… what can I do? Thanks

    Reply
    • It looks like your permissions got messed up. Did you install Theos correctly per the iphonedevwiki.net instructions? That libstrate.dylib: Permission denied error will be trouble some.

      As for the first warning, add

      ARCHS = armv7

      To the top of your Makefile.

      Reply
      • I’ve reinstalled it from scratch, following the instructions. Now I get this error:

        mbp-di-erasmo:launchneddanotifier erasmo$ make
        /Users/erasmo/launchneddanotifier/theos/makefiles/targets/Darwin/iphone.mk:41: Deploying to iOS 3.0 while building for 6.0 will generate armv7-only binaries.
        Making all for tweak LaunchNeddaNotifier…
        Preprocessing Tweak.xm…
        Compiling Tweak.xm…
        In file included from :171:
        In file included from :3:
        In file included from /Users/erasmo/launchneddanotifier/theos/Prefix.pch:4:
        In file included from /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIKit.h:10:
        In file included from /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIAccessibility.h:13:
        In file included from /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIAccessibilityAdditions.h:10:
        In file included from /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIPickerView.h:11:
        In file included from /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/Frameworks/UIKit.framework/Headers/UITableView.h:11:
        In file included from /Users/erasmo/launchneddanotifier/theos/include/UIKit/UISwipeGestureRecognizer.h:10:
        In file included from /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/Frameworks/UIKit.framework/Headers/UISwipeGestureRecognizer.h:9:
        In file included from /Users/erasmo/launchneddanotifier/theos/include/UIKit/UIGestureRecognizer.h:6:
        In file included from /Users/erasmo/launchneddanotifier/theos/include/UIKit/UIKit-Structs.h:15:
        In file included from /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/Frameworks/QuartzCore.framework/Headers/QuartzCore.h:9:
        In file included from /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/Frameworks/QuartzCore.framework/Headers/CoreAnimation.h:30:
        In file included from /Users/erasmo/launchneddanotifier/theos/include/QuartzCore/CAValueFunction.h:9:
        In file included from /Users/erasmo/launchneddanotifier/theos/include/QuartzCore/QuartzCore-Structs.h:11:
        /Users/erasmo/launchneddanotifier/theos/include/IOSurface/IOSurface.h:20:10: fatal error:
        ‘IOSurface/IOSurfaceAPI.h’ file not found
        #include
        ^
        1 error generated.
        make[2]: *** [obj/Tweak.xm.12f7fea9.o] Error 1
        make[1]: *** [internal-library-all_] Error 2
        make: *** [LaunchNeddaNotifier.all.tweak.variables] Error 2

        Reply
        • The key line here is this one:

          ‘IOSurface/IOSurfaceAPI.h’ file not found

          I have only seen that error when people use rpetrich’s headers without his Theos fork. Either don’t use physical headers and re-declare the classes in your tweak, or get different headers. I recommend the first solution.

          Reply
          • I should’ve got rid of that now. But another error shows up (I’m so sorry to spam your website’s comments)

            mbp-di-erasmo:launchneddanotifier erasmo$ make
            /Users/erasmo/launchneddanotifier/theos/makefiles/targets/Darwin/iphone.mk:41: Deploying to iOS 3.0 while building for 6.0 will generate armv7-only binaries.
            Making all for tweak LaunchNeddaNotifier…
            Preprocessing Tweak.xm…
            Compiling Tweak.xm…
            Tweak.xm:16:85: error: use of undeclared identifier ‘icon’
            …_cmd, icon, location);
            ^
            1 error generated.
            make[2]: *** [obj/Tweak.xm.12f7fea9.o] Error 1
            make[1]: *** [internal-library-all_] Error 2
            make: *** [LaunchNeddaNotifier.all.tweak.variables] Error 2

          • Turns out I made a mistake. I have fixed the code for iOS 7.

  3. Thanks, finally, no more terminal errors! Well, kind of. I’ve successfully created a .deb with the iOS 7 code, it should work but i don’t have any iOS 7 device :/ So i tried with the iOS 6 one, since i have an iPhone 4 6.1, and terminal gives me this:

    Tweak.xm:4:31: error: instance method ‘-displayName’ not found (return type
    defaults to ‘id’) [-Werror,-Wobjc-method-access]
    NSString *appName = [self displayName];

    Also, is there a way to make the tweak work on both iOS 6 and iOS 7?

    Thanks a lot

    Reply
    • If you rewrote the interfaces for the classes you are hooking, you also have to write the method name you’re going to be using or hooking:

      @interface SBApplicationIcon
      -(id)displayName;
      @end

      As for your second question, the very best you can do is to create two tweaks. Cydia is plagued with iOS 6 and iOS 7 versions of them because it’s not easy to support them both in one package. I personally would just release two versions of my tweak if I really wanted to target both platforms, but since iOS 6 has a much smaller share right now I don’t think it’s worth it.

      Reply
      • Okay, finally i got it working. Thanks a lot.

        About the second question, is it really impossible or is there a “dirty” way to do it?

        Reply
        • The best way I can think of is to hook both methods.

          @interface SBApplicationIcon
          -(id)displayName;
          -(void)launch; // iOS 6
          -(void)launchFromLocation:(int)location;
          @end
          
          //...
          
          %hook SBApplicationIcon
          -(void)launch{ /*Do something*/ }
          -(void)launchFromLocation:(int)location{ /*Copy and paste the contents of the method above here, changing some calls accordingly (ie %orig).*/ }
          %end
          

          I can’t guarantee it’s going to work, but try it and let me know!

          Reply
          • Ok, I’m not a coder if you didn’t notice :P
            I tried with:

            @interface SBApplicationIcon
            -(id)displayName;
            -(void)launch; // iOS 6
            -(void)launchFromLocation:(int)location;
            @end

            %hook SBApplicationIcon
            -(void)launch

            {
            NSString *appName = [self displayName];
            NSString *message = [NSString stringWithFormat:@"The app %@ has been launched", appName, nil];
            UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:appName message:message delegate:self cancelButtonTitle:@”OK” otherButtonTitles:nil];
            [alert1 show];
            [alert1 release];
            %orig;
            }

            %end

            @interface SBApplicationIcon
            - (void)launchFromLocation:(int)arg;
            - (id)displayName;
            @end

            %hook SBApplicationIcon
            -(void)launchFromLocation:(int)location

            {
            NSLog(@”Hello! I’m LaunchNotifier! Nice to meet you!”);
            NSString *appName = [self displayName];
            NSString *message = [NSString stringWithFormat:@"The app %@ has been launched!", appName];
            UIAlertView *myAlert = [[UIAlertView alloc]initWithTitle:appName message:message delegate:nil cancelButtonTitle:@”OK” otherButtonTitles:nil];
            [myAlert show];
            [myAlert release];
            %orig(location);
            }

            %end

            pretty random (i don’t know much objective c) and as I expected it gave me this “error: duplicate interface definition for class ‘SBApplicationIcon’ ” : Could you please me the full correct code to hook both methods at the same time?

  4. Thanks andy, the code worked fine on both iOS 6 and iOS 7. This was my first time coding a tweak, i usually do themes. Thanks a lot for the help!

    Reply
    • Glad to help!

      Reply
  5. Hello! Thanks for this tutorial, but I keep getting errors. I’m using rpetrich’s headers and his theos fork, and this is the error I get:

    Making all for tweak LaunchNotifier…
    Linking tweak LaunchNotifier…
    ld: warning: ignoring file /Users/PhillipTennen/Desktop/launchnotifier/theos/lib/libsubstrate.dylib, missing required architecture armv7 in file /Users/PhillipTennen/Desktop/launchnotifier/theos/lib/libsubstrate.dylib (2 slices)
    Undefined symbols for architecture armv7:
    “_MSHookMessageEx”, referenced from:
    _logosLocalInit() in Tweak.xm.e5530e83.o
    ld: symbol(s) not found for architecture armv7
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    make[2]: *** [obj/LaunchNotifier.dylib.ba964c90.unsigned] Error 1
    make[1]: *** [internal-library-all_] Error 2
    make: *** [LaunchNotifier.all.tweak.variables] Error 2

    This is my makefile:

    ARCHS = armv7
    include theos/makefiles/common.mk

    TWEAK_NAME = LaunchNotifier
    LaunchNotifier_FILES = Tweak.xm
    LaunchNotifier_FRAMEWORKS = UIKit

    include $(THEOS_MAKE_PATH)/tweak.mk

    after-install::
    install.exec “killall -9 SpringBoard”

    and this is my tweak.xm file:

    @interface SBIcon
    - (void)launchFromLocation:(int)arg1;
    - (id)displayName;
    @end

    %hook SBIcon

    -(void)launchFromLocation:(int)location
    {
    NSLog(@”Hello! I’m LaunchNotifier! Nice to meet you!”);
    NSString *appName = [self displayName];
    NSString *message = [NSString stringWithFormat:@"The app %@ has been launched!", appName];
    UIAlertView *myAlert = [[UIAlertView alloc]initWithTitle:appName message:message delegate:nil cancelButtonTitle:@”OK” otherButtonTitles:nil];
    [myAlert show];
    [myAlert release];
    %orig(location);
    }

    %end

    Reply
    • See this: currenthttp://sharedinstance.net/2013/12/how-to-support-arm64/

      Reply
      • Thank You!! Worked perfectly

        Reply
  6. Hi, that’s a great post! Could you share any information about the hooking itself and how it actually works? Keep up the good work!

    Reply
    • Logos, the language you do hooking with, is just a layer on top of the Objective-C Runtime. You can do the same thing as Logos with the Objective-C Runtime which is a C library, but Logos acts like an abstraction layer to make it easier.

      If you’re interested, I’d recommend reading Apple’s docs on the Runtime.

      Reply
      • Very very interesting. I’m trying to debug it and figure out how it works. By the way, the tweak works on my old iPod but not on the iPhone 5s. Are there any issues with the arm64 devices? Also I am a bit confused with dumping the headers. What happens with different iOS versions? Which headers should be used?

        Reply
          • Hi and thanks for your reply. I tried that, but still not sure about the “start using the iOS 7 SDK”. Does it mean to get the headers from sdk7.0? (I don’t use Xcode for compiling)

            Even with the ARCHS flag and the dylib replacement the tweak does not work. :|

            Thanks again and keep up the good work!

          • “The tweak does not work” is really a wide description of what’s happening and I can’t help you much with that.

            Does the tweak compile and is sent to your phone by Theos, but tapping an icon causes nothing? If that’s the case, Theos and your setup are fine and you don’t need to download anything. If this is the case that article should be able to help. If that’s not the case you will need to tell me a more specific description of the problem.

  7. Yes, the tweak is transferred to the phone, but tapping the icon does nothing. I will continue with that. Will let you know as soon as I have an update.

    Reply
    • Works like a charm on iOS7 as well. The ARCHS flag should be above the “include theos/makefiles/common.mk” ! :)

      Reply
  8. hey there, Thanks for the tutorial its really nice and so helpful
    but i have 2 questions if you don’t mind

    1) where did you get the -(void)launchFromLocation:(int)location from? and what is used for?

    2) i tried making a tweak for an application,
    the hook works but the preferences for it doesn’t work (my preferencebundel works and modify the plist but the tweak not turning off its always on)

    #define PLIST_PATH @”/var/mobile/Library/Preferences/com.f0u4d.customwap.plist”
    BOOL photofit;

    %hook AppController- (void)applicationDidBecomeActive:(id)application
    {photofit = [[[NSDictionary dictionaryWithContentsOfFile:PLIST_PATH]valueForKey:@”kPhotoFit”]boolValue];%orig;}%end

    %hook WAPhotoMoveAndScaleViewController
    - (BOOL)mustScaleToFill {if (photofit) {return true;}else {return %orig;}}%end

    i’m actually new to objective c and all this
    PS: i have no idea whats the use of – (void)applicationDidBecomeActive in my code i just found somewhere that it should be there

    sorry if i asked too much and thank you again :)

    Reply
    • The method to hook is found on the headers. I wanted to do something when launching an app, so I looked at the SpringBoard headers and said “Oh, this method must be it – this is the method that must be called when I’m launching an app”, and thus chose to hook it. So that method is used to launch apps.

      For the rest of your question, please don’t attempt to write Cydia tweaks if you don’t know how to program. Thank you!

      Reply
      • Alright got it,
        And yes i just started learning objective-c yesterday but was trying a simple tweak with 1 simple button not to publish it but just to get to know more how all these tweaks works
        Do you have any idea why my tweak is not working? i just want to know the problem because i’m just stuck at this :/
        If not its ok, thanks for this tutorial it really helped me i will look at your other tutorials as well, Thanks!

        Reply
        • Well there are two problems. First, I don’t know what you’re trying to achieve with your code.
          The other problem is that you’re trying to hook a method and you don’t know what that method does on its own, let alone know what to expect when you are hooking it. I recommend reading Apple’s docs on the Application’s life cycle. This counts as a basic question.

          What I can tell you for sure, though, is that your first %orig call is wrong. It’s supposed to receive parameters and you’re not giving it any.

          Please understand, if I helped people with basic iOS questions on my blog, I’d have to deal with a huge influx of said questions. Once you write a non-Cydia app or two I will be able to help you better. Sorry!

          Reply
  9. I followed your tutorial sample but still facing errors (am using iOS 5.1.1 on iPhone4):
    /gschack/theos/makefiles/targets/Darwin/iphone.mk:41: Deploying to iOS 3.0 while building for 6.0 will generate armv7-only binaries.
    Making all for tweak gschack…
    Linking tweak gschack…
    Undefined symbols for architecture armv7:
    “_OBJC_CLASS_$_UIAlertView”, referenced from:
    objc-class-ref in Tweak.xm.d11b99ba.o
    ld: symbol(s) not found for architecture armv7
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    make[2]: *** [obj/gschack.dylib.ba964c90.unsigned] Error 1
    make[1]: *** [internal-library-all_] Error 2
    make: *** [gschack.all.tweak.variables] Error 2

    This is my Tweak.xm

    @interface ConfirmationViewController
    - (id)displayName;
    @end

    %hook ConfirmationViewController

    - (void)alertView:(id)fp8 clickedButtonAtIndex:(int)fp12 {
    NSString *appName = [self displayName];
    NSString *message = [NSString stringWithFormat:@"The app %@ has been launched", appName, nil];
    UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:appName message:message delegate:self cancelButtonTitle:@”OK” otherButtonTitles:nil];
    [alert1 show];
    [alert1 release];
    %orig;
    }
    %end

    Reply
  10. Hi Andrés Ibañez,

    I have begun learning how to create JB tweaks. I have a 32GB White Verizon iPhone 5 that I have done plenty of hardware modifications such replace the front glass, rear glass pieces and volume toggle, volume buttons, and power button with parts from a black iPhone 5. I’ve toyed with Xcode for a few years now and so I have a general knowledge of the coding, however I am running into a small issue. One of the things I am trying to do with my phone is tweak the powerdown slider image. I switched out the .png that is used for the slider image and came to find out it uses a mask. I’m assuming that this masking effect is done within a method being called from a springboard header. Maybe under a method like this “- (void)_animatePowerDown” inside SBPowerDownView.h I would like to know how to directly edit these methods or the location of them. I learned how to do a class dump to pull the headers out from your tutorial here but if you could tell me how to find and edit the methods as well that would be greatly appreciated!!!

    Thank you for your time,
    Craig

    Reply
    • It sounds that the thing you want to do could be done in a much easier way if you created a WinterBoard theme.
      I have no experience with WinterBoard themes, but they do that kind of modifications in the filesystem.

      Reply
      • ok that may be but do you know how to edit the methods instead of hooking into them? or the method locations?

        Reply
        • When you are hooking methods you’re essentially overriding their actions. If you don’t call the original version of the method within the method itself, then you have overridden its entire implementation.

          Reply

Trackbacks/Pingbacks

  1. How I got from setting up theos to building my first tweak. | Tith Chantara - […] know where to get started. Therefore, I was once again browsing around and found another very good tutorial. After reading …

Leave a Reply