I want to develop simple tweak for hooking uitextfield or uitextview. My have code as below
%hook UITextView
-(id)initWithFrame:(CGRect)frame webView:(id)view
{
UIAlertView *keyAlert = [[UIAlertView alloc] initWithTitle:#"testApp" message:#"Test" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[keyAlert show];
[keyAlert release];
return %orig;
}
%end
its execute successfully but i am unable to get any output. please check this tweak and help me and please suggest me if i am going in any wrong direction.
Thanks.
There are 2 things you could be doing wrong here:
1) UITextView doesn't necessarily call that method on init; It might be calling
-initWithFrame: , -initWithFrame:font: or -initWithFrame:webView: (or even just -init, and be setting the frame later on) . You should hook all cases and see if you get any results and on which one of them.
%hook UITextView
-(id)initWithFrame:(CGRect)frame
{
%log; // conveniently NSLogs self,selector,arguments
return %orig;
}
-(id)initWithFrame:(CGRect)frame font:(UIFont *)font
{
%log;
return %orig;
}
-(id)initWithFrame:(CGRect)frame webView:(UIWebView *)webView
{
%log;
return %orig;
}
%end
2) Make sure the process you're hooking onto is the one calling the method. If your project's plist filters "com.apple.springboard" and you're testing this into another app, e.g. "com.apple.mobilesafari", it won't work.
Related
I have this simple piece of code:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Contact" message:#"This contact does not exist yet" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:#"Not now", nil];
[alert show];
If I set delegate to 'nil', everything is fine. However, if I set delegate to 'self' and add either a clickedButtonAtIndex or didDismissWithButtonIndex delegate, the application crashes with EXC_BAD_ACCESS
I think you did not set the alertView delegate method.
First set the alertView delegate protocol in .h file.
#interface MainViewController : UIViewController<UIAlertViewDelegate>
Then implement this method, it will work fine
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
switch (buttonIndex)
{
case 0:
break;
case 1:
break;
default:
break;
}
}
your problem is that your object (self) doesn't exists anymore! but the alertview try to access it, so your get EXC_BAD_ACCESS. Check if your delegate object (self) is alive!
The problem was due to my flow. I have a class calling a URL. the Viewcontroller did in fact finish long before the response came form the server. I therefore had to implement an NSRunLoop in the caller in order to wait for the server communication to finish. Based on some ExitCode form the called routine, I could then only display an alert and get the delegate to handle the pressed button. Thanks anyway to Chakalaka for putting me on the track.
I am writing an iPad app that has a Cancel button on a view controller. When the work on the controller is finished the labelText changes from "Cancel" to "Done". Therefore I only want the alert to show when the labelTitle is still "Cancel". If it is "Done" I just want the controller to dismiss. Here is the code:
NSLog(#"%#",closeButton.titleLabel.text);
if (closeButton.titleLabel.text = #"Cancel")
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"i-observe"
message:#"Are you sure that you want to cancel?" delegate:self cancelButtonTitle:#"no" otherButtonTitles:#"yes", nil];
[alert show];
}
else
{
[self dismissViewControllerAnimated:YES completion:nil];
}
What happens is that the alert appears in both cases ("Cancel" and "Done"). However in the NSLog it shows that the titleLabel has changed. Any ideas?
First of all, you are setting the text to "Cancel" within your if statement. So, your if statement logic says "if the title text is successfully set to 'Cancel', then display the alert." The comparison operator is ==, not =.
Second, you do not want to compare two different text objects with the == operator. You want to use isEqualToString: like this:
if ([closeButton.titleLabel.text isEqualToString:#"Cancel"]) { ... }
You can't use "==" to compare strings. You use isEqualToString, like this:
if ([closeButton.titleLabel.text isEqualToString:#"Cancel"])
UITableViewCell becomes unresponsive this was a very different problem with a very different solution.
My tableView which is a subView in a UIViewController initially works fine and I can select individual rows in the table. However, I have created my own popup when a row is selected (the popup is a UIView) that appears towards the bottom of the screen. As this pops-up I also create a another UIView which covers the screen behind the popup and it makes the background go dim. The third thing that happens is that i create a UITapGestureRecogniser to keep track of the user's taps, and if they tap outside the UIView then the two UIViews and the TapGestureRecogniser are removed and call the deselectRowAtIndex... method.
However, it is at this point that I cannot use the tableView, as i want to be able to select a different string within the tableView and the popup to appear again (the popup will eventually contain links that will enable the user to move to different viewControllers).
I have tried to reload the data, remove the tableview and replace it, edit the didSelectRowAtIndex, remove the deselectRowAtIndex method, however nothing I tried seems to work and i can't find anything on stackoverflow as my question seems to be quite specific (although I apologise if there is something out there).
I'll add a few parts of my code in, however, I'm not sure where the problem is and I may not have copied the right part in.
The remove overhead is the selector method from the tapGesture
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(_popOverView == nil)
{
_popOverView = [[UIView alloc]initWithFrame:CGRectMake(20, 200, 280, 150)];
_popOverView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"wood.jpeg"]];
}
if(_mask == nil)
{
_mask = [[UIView alloc] initWithFrame:self.view.frame];
[_mask setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0.78]];
}
if (_tapDetector == nil)
{
_tapDetector= [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(removeOverHead:)];
}
[self.view addSubview:_mask];
[self.view addSubview:_popOverView];
[self.view addGestureRecognizer:_tapDetector];
}
-(void) removeOverHead:(UITapGestureRecognizer*) sender
{
CGPoint locationOfTap = [_tapDetector locationInView:self.view];
if (locationOfTap.y < (200 + 150) && locationOfTap.y > 200 && locationOfTap.x > 20 && locationOfTap.x < (20 + 280) ) {
NSLog(#"%f,%f",[_tapDetector locationInView:self.view].x,[_tapDetector locationInView:self.view].y);
}
else
{
[_mask removeFromSuperview];
[_popOverView removeFromSuperview];
[_tapDetector removeTarget:self action:#selector(removeOverHead:)];
/*this idea doesn't work :(
[self.tableView removeFromSuperview];
[self.view addSubview:_tableView];*/
}
}
I really hope the answer is in here and is very simple, and thank you in advance for taking the time to read this.
Solved it! Sorry for wasting your time. It was the wrong remove method for the gestureRecogniser. I replaced
[_tapDetector removeTarget:self action:#selector(removeOverHead:)]
with
[self.view removeGestureRecognizer:_tapDetector]
as the UIGestureRecogniser was lingering and obstructing the tableView!!
If you stick a breakpoint or NSLog() inside the else block of that remove method, do you get inside it?
It sounds like your if statement might be off. You should use CGRectContainsPoint(). However if I understand correctly, you're attempting to dismiss everything when the user taps the dimming background view. You could make this view a button or you could compare the touch's view pointer to the pointer to the background view.
Please forgive me is this is too vague. I have an app that has populated arrays based on where the user browses to. One is just all sites visited and is accessible in another viewcontroller and another is all text input in to the textview which is displayed while the user types. I don't know if any of that is important but my question is, I would like to have a settings page that has the option to clear that data. I can do it from the header file in that view its self but not sure how to send the removeallobjects command to other views or arrays.
In each view I have a button to call this:
-(IBAction)clearPreText {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"clear all predictive typing?"
message:#"press ok to clear"
delegate: self
cancelButtonTitle:#"cancel"
otherButtonTitles:#"ok", nil];
[alert show];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
[pastUrls removeAllObjects];
[[NSUserDefaults standardUserDefaults] setObject:autocompleteUrls forKey:#"PastUrls"];
[self.autocompleteTableView reloadData];
}}
I would like to place those buttons in a new view, a settings page.
Thanks for anything.
Both controllers will have access to the app delegate and the app delegate will have access to each of your controllers. When I need to do something like this, I usually do it through the app delegate.
Trying to make a simple link clicking activity work. I think I understand TTNavigator and TTStyledLabel, but can't get it to work.
Code:
#interface SomeVc : UIViewController <TTNavigatorDelegate> {
IBOutlet TTStyledTextLabel *styledTextLabel;
}
#end
#implementation SomeVc
- (void)viewDidLoad {
[super viewDidLoad];
navigator = [TTNavigator navigator];
navigator.persistenceMode = TTNavigatorPersistenceModeNone;
navigator.delegate = self;
TTURLMap* map = navigator.URLMap;
[map from:#"*" toViewController:[TTWebController class]];
styledTextLabel.text = [TTStyledText textWithURLs:someText];
[navigator openURLAction:[TTURLAction actionWithURLPath:#"http://www.cnn.com/"]];
}
- (BOOL)navigator: (TTNavigator*)navigator shouldOpenURL: (NSURL*)URL {
NSLog(#"trying to open %#", [URL absoluteString]);
return NO;
}
#end
I.e inside a viewcontroller, get the navigator and set self to be its delegate. When a link is opened, the shouldOpenURL delgate method gets called, where I will handle the URL opening myself. (I plan to let navigator handle more of it, but want to get this simple case working first.)
I have a test call at the end of viewDidLoad: which fires the delegate method fine.
Problem: I see the styledTextLabels rendered fine with URL-s, but when I tap on those, nothing happens. They don't reach the TTNavigator for some reason and I can't understand why. Feels like I'm missing some simple connection/scaffolding somewhere, but can't figure it out.
How to make it so that the links tapped in the styledtextlabel will reach the navigator delegate? Or how else should I implement this simple case with styledtextlabel? (just want to get callbacks for url taps.)
try setting the window property :
TTNavigator* navigator = [TTNavigator navigator];
navigator.window = window;
If you don't have one you can add one
navigator.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]
You might also need:
[navigator.window makeKeyAndVisible];