EDIT:
Running on an iPad Mini on iOS 8.1
I tried a test project to hook viewDidLoad in the app to show a UIAlertView, but nothing happened. Does anyone have idea what could cause the tweak to compile but not run properly?
10 hours of debugging, I'm turning to SO.
There's obviously something wrong with this code, and I have no idea what could be causing it. I'm hooking the TestOut view in the ChineseSkill app, but when I get to the view it acts as if nothing changed from the original app.
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#interface TestOutViewController : UIViewController <UIAlertViewDelegate>
- (UIButton *)quitButton;
#end
%hook TestOutViewController
- (void)viewDidAppear:(BOOL)view {
%orig;
UIButton *infiniteLivesButton = [UIButton buttonWithType:UIButtonTypeSystem];
[infiniteLivesButton setTitle:#"Infinite Lives" forState:UIControlStateNormal];
[infiniteLivesButton setFrame:CGRectMake(/*[self quitButton].frame.origin.x + [self quitButton].frame.size.width, [self quitButton].frame.origin.y + 20*/50, 50, 200, 50)];
[infiniteLivesButton setBackgroundColor:[UIColor redColor]];
[infiniteLivesButton addTarget:self
action:#selector(makeLivesInfinite:)
forControlEvents:UIControlEventTouchUpInside];
UIButton *passTestButton = [UIButton buttonWithType:UIButtonTypeSystem];
[passTestButton setTitle:#"Skip Test" forState:UIControlStateNormal];
[passTestButton setFrame:CGRectMake(infiniteLivesButton.frame.origin.x + infiniteLivesButton.frame.size.width + 10,
infiniteLivesButton.frame.origin.y,
150,
50)];
[passTestButton addTarget:self
action:#selector(skipTest:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:passTestButton];
[self.view addSubview:infiniteLivesButton];
UIAlertView *successAlertView = [[UIAlertView alloc] initWithTitle:#"Success!" message:#"Infinite hearts for the rest of this test." delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[successAlertView show];
}
- (void)touchesBegan:(id)began withEvent:(id)event {
UIAlertView *testView = [[UIAlertView alloc] initWithTitle:#"Test" message:#"Test Alert" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[testView show];
}
%new
- (void)makeLivesInfinite:(UIButton *)sender {
[self performSelector:#selector(setNNumberofLeftHearts:) withObject:#1000000];
UIAlertView *successAlertView = [[UIAlertView alloc] initWithTitle:#"Success!" message:#"Infinite hearts for the rest of this test." delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[successAlertView show];
}
%new
- (UIButton *)quitButton {
return objc_getAssociatedObject(self, #selector(quitButton));
}
%new
- (void)skipTest:(UIButton *)sender {
[self performSelector:#selector(setNTotalTest:) withObject:#1];
[self performSelector:#selector(CheckOrContinueButtonClick:) withObject:NULL];
[self performSelector:#selector(CheckOrContinueButtonClick:) withObject:NULL];
}
%end
There's no alert views, no added views, no nothing. Nearly anything will help.
Your problem is you have to set the right filters in your tweak's plist file. By default the plist file has a bundle identifier filter com.apple.springboard. You should change this to the bundle identifier of the app you want your code injected.
Furthur information (Just a little):
What is happening in behind? MobileLoader is responsible for patching your code into a program. These plist files tell MobileLoader to patch the code in which program(s), in which framework(s) or in which running process. So your process is the app and not SpringBoard. This link
has good explanation about CydiaSubstrate (MobileSubstrate). You could also have a look at its documentation.
Related
Here is my code:
UIAlertView *theAlert = [[UIAlertView alloc] initWithTitle:#"Alert" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
UITextField *textField = [[UITextField alloc] initWithFrame: CGRectMake(12, 45, 260, 30)];
[textField setBackgroundColor: [UIColor clearColor]];
textField.borderStyle = UITextBorderStyleRoundedRect;
[theAlert addSubview:textField];
[theAlert show];
[textField release];
[theAlert release];
There is no textFiled in alertView, only a title "Alert" and a button "OK"
I will refer you the Apple Documentation in regards to UIAlertView Class Reference. Specifically
Subclassing Notes
The UIAlertView class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified
So what this means is you can't add subviews to an instance of UIAlertView the recent UIAlertView still has the addSubview: method is because UIAlertView is a subclass of UIView which has this method, but as of iOS7 the method addSubview: for UIAlertView no longer calls the super method on UIView it just does nothing.
So basically what you are after is not possible.
There are however alertViewStyles that you can use like UIAlertViewStylePlainTextInput which will add a single UITextField to the UIAlertView which you can then access using the method textFieldAtIndex:. However please be aware that you can't really do anything with this again because it is part of the UIAlertViews hierarchy so again it is made to be used as is.
Messing with the UIAlertView hierarchy will get your app rejected from the Apple Review process under
2.5 - Apps that use non-public APIs will be rejected
your background color is clear so It's not showing
[textField setBackgroundColor: [UIColor redColor]];.
and also show default text field
theAlert.alertViewStyle = UIAlertViewStylePlainTextInput;
//or for username and password
theAlert.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
// or for password
theAlert.alertViewStyle = UIAlertViewStyleSecureTextInput;
Try this
You can use the default alertView with textfield.For that you need to set the alertViewStyle
[message setAlertViewStyle:UIAlertViewStylePlainTextInput];
Here message is object of alertView.
You can get the textfield value using the delegate method as shown below
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"Login"]) {
UITextField *username = [alertView textFieldAtIndex:0];
UITextField *password = [alertView textFieldAtIndex:1];
NSLog(#"Username: %#\nPassword: %#", username.text, password.text);
}
}
Or you can set alert.alertViewStyle = UIAlertViewStylePlainTextInput;
This will add a text field for you. You can access it in the
UIAlertView delegate callback by using
UITextField *textField = [alertView textFieldAtIndex:0];
If your using ios 7 then add below code to your set of code
theAlert.alertViewStyle=UIAlertViewStylePlainTextInput;
Full code
UIAlertView *theAlert = [[UIAlertView alloc] initWithTitle:#"Alert" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
UITextField *textField = [[UITextField alloc] initWithFrame: CGRectMake(12, 45, 260, 30)];
[textField setBackgroundColor: [UIColor greenColor]];
textField.borderStyle = UITextBorderStyleRoundedRect;
theAlert.alertViewStyle=UIAlertViewStylePlainTextInput;
[theAlert show];
What is wrong with my code?? I am somewhat new to the whole jailbreak development process. If anyone could help me with this. I was trying to do a test of something new that I learned and I was trying to display a UIButton that creates a UIAlertView on the home screen.
%hook SBUIController
- (void)finishLaunching
{
UIButton *myButton;
myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
myButton.frame = CGRectMake(25, 85, 100, 35);
[myButton setTitle:#"Test" forState: UIControlStateNormal];
[myButton addTarget:self action:#selector(myButtonPressed) forControlEvents:UIControlEventTouchUpInside];
SBUIController *ui = MSHookIvar<id>(self, "_uiController");
[[ui window] addSubview:myButton];
}
%new(v#:)
-(void)myButtonPressed{
UIAlertView *theAlert = [[UIAlertView alloc] initWithTitle:#"Title of Alert" message:#"Message of Alert" delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[theAlert show];
[theAlert release];
}
%end
#selector(myButtonPressed)
simply add : after my button pressed so it become
#selector(myButtonPressed:)
I have this code on my program
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *saveMessageBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[saveMessageBtn setImage:[UIImage imageNamed:#"btn_done.png"] forState:UIControlStateNormal];
[saveMessageBtn addTarget:self action:#selector(saveMessage) forControlEvents:UIControlEventTouchUpInside];
[saveMessageBtn setFrame:CGRectMake(0, 0, 49, 30)];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:saveMessageBtn];
}
-(IBAction)saveMessage:(id)sender{
UIActionSheet *actionSheet = [[UIActionSheet alloc]initWithTitle:nil delegate:nil cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Send Now",#"Non Recurring",#"Recurring", nil];
[actionSheet showInView:self.view];
}
- (void)actionSheet:(UIActionSheet *) actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0){
NSLog(#"Send Now");
}
else if (buttonIndex == 1){
[self performSegueWithIdentifier:#"modalNonRecurring" sender:self];
}
else if (buttonIndex == 2){
[self performSegueWithIdentifier:#"modalRecurring" sender:self];
}
else{
NSLog(#"Cancel Clicked");
}
}
as you can see in the code, it supposed to perform a segue or do 'NSLog' when a particular button clicked.
But when I click a button, it does not perform what I want it to do, instead it displays this message in the debug area..
Presenting action sheet clipped by its superview. Some controls might not respond to touches. On iPhone try -[UIActionSheet showFromTabBar:] or -[UIActionSheet showFromToolbar:] instead of -[UIActionSheet showInView:].
By the way, I am using a UINavigationController that is inside a UITabBarController.
Anyone that has a great idea how to fix this? your help would be much appreciated. Thanks!
Add UIActionSheetDelegate delegate in .h file and try like this then it'l work.
UIActionSheet *actionSheet = [[UIActionSheet alloc]initWithTitle:nil delegate:nil cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Send Now",#"Non Recurring",#"Recurring", nil];
actionSheet.delegate = self;
[actionSheet showInView:self.view];
Just learning to add actions with code in my .m file and my first attempt throws an exception and crashes the app.
This is an authentication script that I hope will communicate with my web server. Here is the relevant code (this is all in the .m file, very simple .h file):
.h (header) file:
#import <UIKit/UIKit.h>
#interface Login_ViewController : UIViewController <UITextFieldDelegate>
#end
.m (implementation) file:
- (void)viewDidLoad {
UILabel *emailLabel = [[UILabel alloc] initWithFrame:CGRectMake(31.0f, 75.0f, 256.0f, 20.0f)];
emailLabel.text = #"Email Address";
emailLabel.backgroundColor = [UIColor grayColor];
emailLabel.textColor = [UIColor whiteColor];
UITextField *emailField = [[UITextField alloc] initWithFrame:CGRectMake(31.0f, 100.0f, 256.0f, 32.0f)];
emailField.delegate = self;
emailField.placeholder = #"Enter email address";
emailField.borderStyle = UITextBorderStyleRoundedRect;
[self.view addSubview:emailLabel];
[self.view addSubview:emailField];
UILabel *passLabel = [[UILabel alloc] initWithFrame:CGRectMake(31.0f, 175.0f, 256.0f, 20.0f)];
passLabel.text = #"Password";
passLabel.backgroundColor = [UIColor grayColor];
passLabel.textColor = [UIColor whiteColor];
UITextField *passField = [[UITextField alloc] initWithFrame:CGRectMake(31.0f, 200.0f, 256.0f, 32.0f)];
passField.delegate = self;
passField.placeholder = #"Enter Password";
passField.borderStyle = UITextBorderStyleRoundedRect;
passField.secureTextEntry = YES;
UIButton *loginButton = [[UIButton alloc] initWithFrame:CGRectMake(31.0f, 275.0f, 256.0f, 32.0f)];
[loginButton setTitle:#"Login" forState:UIControlStateNormal];
[loginButton addTarget:self action:#selector(authenticate) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:passLabel];
[self.view addSubview:passField];
[self.view addSubview:loginButton];
[self.view setBackgroundColor: [UIColor grayColor]];
UIAlertView *noAccount = [[UIAlertView alloc] initWithTitle:#"Welcome to T-of-U" message:#"Please enter your TofU credentials." delegate:self cancelButtonTitle:#"continue" otherButtonTitles: nil];
[noAccount show];
[super viewDidLoad];
}
also in the .m file (IBAction for the button):
-(IBAction)authenticate:(id)sender{
// This will be the validation code
// if we validate we will set the default Setting with accountID here.
UIAlertView *auth1 = [[UIAlertView alloc] initWithTitle:#"You clicked a button" message:#"Oh, do you want to login do you?" delegate:self cancelButtonTitle:#"Sure.. Why not!" otherButtonTitles: nil];
[auth1 show];
}
I am using a storyboard with a View that has a custom class of login_ViewController and it loads successfully based on a check for a local setting for account ID. This window is only pulled up if they have not logged in before, so I can authenticate and get that account ID to store locally. I am still experimenting with programmatically creating all these items as you can see in the viewDidLoad section.
Is this failing because I don't have the button/IBAction reference in the .h file , or is it ok to use the addTarget method where its all in the .m file?
Crash info from the log:
2012-01-08 04:54:32.868 TofU-5[10452:10103] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Login_ViewController authenticate]: unrecognized selector sent to instance 0x6c94780'
Your fix may be as easy as:
[loginButton addTarget:self action:#selector(authenticate:) forControlEvents:UIControlEventTouchUpInside];
(add a COLON after the authenticate name in your #selector). If a method takes any parameter, there will be a colon after it and for the run time environment to be able to send a message to it, that colon needs to be included in the selector of the action target.
I hope this makes sense and helps you out!
p.s. it wouldn't hurt to add
-(IBAction)authenticate:(id)sender
to the .h file.
IBAction here is an abbreviation for InterfaceBuilder-Action so this actually helps a lot more if you're building the interface in a XIB file. Because you're setting the target programatically, you could just use -(void) authenticate (no colon, because your method uses or needs no parameters), but don't do this yet until you get more overall experience with Objective C coding and actions.
-(void)buPressed{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Game Over"
message:#"YOU LOST! ALL YOUR BASE ARE BELONG TO US!"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Publish", nil];
[alertView show];
[alertView release];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if(buttonIndex==0){
NSLog(#"%d",buttonIndex);
}
else{
[self bPressed];
}
}
-(void)bPressed{
ModalViewConroller *yeniSayfa=[[ModalViewConroller alloc] init];
yeniSayfa.modalTransitionStyle=UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:yeniSayfa animated:YES];
[yeniSayfa release];
//Restore to Defaults
[button_1 setSelected:NO];
[button_2 setSelected:NO];
[button_3 setSelected:NO];
[button_4 setSelected:NO];
[button_5 setSelected:NO];
[button_6 setSelected:NO];
slider.value=50.00;
UIImage *image = [UIImage imageNamed:#"Smiley_00025.png"];
imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = CGRectMake(81, 43, image.size.width, image.size.height);
[self.view addSubview:imageView];
}
This is my code i want to make the publish button to call bPressed function but it is giving a warning and the program crashes when i touch the publish button i want to open a modalview when i push the publish button can anybody help me?
You need to declare the function in your header file so that other objects (in this case an instance of UIAlertView, since its delegate is set to your class) know that this method exists.
So, in your whatever_class.h file, add the following line below the #interface{ }:
-(void)bPressed;