strange behaviour Xcode - xcode4.3

In my view controller I have a method -(void) showDescription: (id) description witch does two things:
displays the description in the label
and runs a method in the view that gives a setNeedsDisplay to the
view.
Now here is the strange thing:
if i call showDescription from another method in my code, it goes to showdescription (i have an NSLog), reads the description OK ( another NSLog) but doesn't change the label or run the view method with setNeedsDisplay (no NSLog).
But... if i call the same method from a button it works just fine: puts up label.text and redraws my view.
I realised the same behaviour when I put two breakpoints one in showDescription and one in the view method. In the first case it doesn't go to the view method, in the second (UIAction) it does.
How strange is that? Does anybody have a clue why? because i'm lost....
Thanks a lot
Clemcore
classes:
GraphViewController: UIViewController
graphView: UIView
**GraphViewController.m*******
-(void) showDescription: (id) description
{
NSString* text= [(NSString*) description copy];
self.lableDescription.text=text; //display description in label
[self.graphView redrawView];
}
-(void)displayGraph
{
NSLog(#"GraphViewController.displayGraph");
NSLog(#"self.programData %#",self.programData); //these work fine
NSLog(#"description lable %#",self.programDescriptionData);
[self showDescription:self.programDescriptionData];
[self.graphView redrawView];
}
- (IBAction)redraw {
NSLog(#"IBAction redraw");
NSLog(#"myData %#",self.graphView.myData);
[self showDescription:#"CCCC"];
[self.graphView redrawView];
}
graphView.m***
-(void)redrawView //public method
{
NSLog(#"redrawView");
[self setNeedsDisplay];
}
I am using Xcode 4.3.3 on Lion 10.7.4
Here is what happens:
If i call displayGraph, the programData and programDescriptionData is fine.(NSLog displays it correctly) but… it doesn't change the label and it doesn't go to redrawView (no NSLog redrawView).
Here is the log:
2012-07-08 12:29:19.193 CalculatorGraph[2641:f803] GraphViewController.displayGraph
2012-07-08 12:29:19.194 CalculatorGraph[2641:f803] self.programData (
22
)
2012-07-08 12:29:19.194 CalculatorGraph[2641:f803] description lable 22
2012-07-08 12:29:19.195 CalculatorGraph[2641:f803] text is 22
Now, if i push the button it all seems to work: updates the label and redraws the view and the drawRect in the view. See my problem?
2012-07-08 14:16:54.358 CalculatorGraph[2743:f803] IBAction redraw
2012-07-08 14:16:54.358 CalculatorGraph[2743:f803] myData <GraphViewController: 0x6d3f1f0>
2012-07-08 14:16:54.359 CalculatorGraph[2743:f803] text is CCCC
2012-07-08 14:16:54.359 CalculatorGraph[2743:f803] redrawView
2012-07-08 14:16:54.360 CalculatorGraph[2743:f803] redrawView
2012-07-08 14:16:54.362 CalculatorGraph[2743:f803] graphView.drawRect
2012-07-08 14:16:54.363 CalculatorGraph[2743:f803] data in graphView DrawRect is: <GraphViewController: 0x6d3f1f0>
Screenshot of my storyboard: please see link lower in my comments...
Thank you

Are you sure your IBOutlet is lableDescription? Might it be labelDescription?
Plus: you should probably never "[self.graphView redrawView];"; you should be "[self.graphView setNeedsDisplay:YES]" instead. Is "showDescription" the appropriate method name? (Do you have a "hideDescription" method?).

Related

Xcode Totally dismiss ViewController

I have a very simple question:
How can I "dismiss" a ViewController completely?
After this I want the ViewController to load like if it had been the first time I load the ViewController.
How could I do this? I already tried setNeedsDisplay() but thats not what I want.
Thanks
Jannes
I think what you mean is to remove the view (not the view controller) That way, when you enter the main view, it will run viewDidLoad again. I have done something similar in a view controller within a navigation controller. When I click the 'back' button, I wanted to remove the view and force it to load again the next time I enter it. I was able to do that with this code:
NSArray *viewsToRemove = [self.view subviews];
for (UIView *v in viewsToRemove)
{
NSLog(#"removing view %#", v);
[v removeFromSuperview];
}

Display modally custom keyboard view controller for editing a UITextField

By default when tapping on a UITextField iOS will display a default keyboard. Is it possible to bypass this? I would like to display modally a custom view controller on tap on the textField and be able to edit the textField through this controller.
Is there a recommended way?
Following wil repalce the keyboard as the input view when the user clicks on the UItextField.
self.TextField.inputView = "your view ";
Ok tried out the exact requirement you asked for:-
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
[textField resignFirstResponder];
POCModalViewController *objPOCModalViewController = [[POCModalViewController alloc]init];
[self presentViewController:objPOCModalViewController animated:YES completion:nil];
return NO;
}
Where POCModalViewController is the controller you want to present.
I would like to post the solution i have finally implemented, which is the closest to Footyapps27 solution:
I have made the controller that will present the modal controller(which will contain internally multiple custom keyboard views) as the uitextfield delegate for any UITextField objects contained within the view of my controller.
I can now received any notification through the - (BOOL)textFieldShouldBeginEditing:(TWValueInput *)textField method when a textfield start to be edited:
Within that delegate method I have the following code snippet:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
MyCustomKeyboardVC* vc = [[UIStoryboard storyboardWithName:#"main" bundle:nil] instantiateViewControllerWithIdentifier:#"customKeyboardController"];
vc.delegate = self;
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:vc animated:NO completion:nil];
return NO;
}
returning NO within that method will prevent the default keyboard from being displayed. There is no need actually to call the resignFirstResponderon the textfield.
I should point out though that the Apple recommended way to display a custom keyboard is to provide a custom view to the textfield inputView property like Divya mentioned. Since i wanted to managed multiple keyboard view entries it was quicker for me to display a custom keyboard controller through the delegate method i mentioned above.

didSelectRowAtIndexPath, pushViewController and a little lable

I have a table controller in which I use didSelectRowAtIndexPath to navigate from the pushed cell to another view. In it I initialize new view controller and push some data in it. After that I do pushViewController.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
ServicesModel *service = [services objectAtIndex:indexPath.row];
ServiceViewController *serviceViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"ServiceView"];
serviceViewController.serviceModel = service;
NSLog(#"Set model %#", service.title);
// Pass the selected object to the new view controller.
[self.serviceController pushViewController:serviceViewController animated:YES];
}
In my ServiceViewController I have a label serviceTitle and ServiceModel property for selected service
#property (weak, nonatomic) IBOutlet UILabel *serviceTitle;
#property (strong, nonatomic) ServiceModel *serviceModel;
Using viewDidLoad I'm trying to change text of the label
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(#"viewDidLoad %#", self.serviceModel.title);
self.serviceTitle.text = self.serviceModel.title;
}
Also I'm trying to access model in viewDidAppear
- (void) viewDidAppear:(BOOL)animated
{
NSLog(#"viewDidAppear %#", self.serviceModel.title);
}
but when view opens, label is empty. Why? What am I doing wrong? The most strange is the log:
(-[ServiceViewController viewDidLoad]) (ServiceViewController.m:43) viewDidLoad (null)
(-[ServicesTableViewController tableView:didSelectRowAtIndexPath:]) (ServicesTableViewController.m:127) Set model Google.com
(-[ServiceViewController viewDidAppear:]) (ServiceViewController.m:36) viewDidAppear (null)
It shows that viewDidLoad fires before I assign the model property. And in viewDidAppear model property is still null. How it can be?
You have two problems. The first one, as 0x7fffffff mentioned, is that you're instantiating your controller incorrectly (it should be initWithNibName:bundle: if made in a xib, and like 0x7fffffff said if in a storyboard).
Second, you can't access the label in serviceViewController from didSelectRowAtIndexPath, because its view has not been loaded yet. So, instead of setting the label in didSelectRowAtIndexPath, you should have a string property in serviceViewController, and give it the value service.text. Then in viewDidLoad, you can populate your label with that string.
Is the label missing altogether, or do you see it and it just didn't receive updated text? If the label is missing, then it's probably a problem in how you're creating the view controller. If for example, you're using storyboards, you should be accessing the view controller like this:
ServiceViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"SomeStoryBoardID"];
Instead of this:
ServiceViewController *serviceViewController = [[ServiceViewController alloc] init];
If however, you can see the label, but it just hasn't updated it's text, the first thing you should to is examine the connections inspector in Interface Builder, and verify that the IBOutlet for the label is properly linked.

View controller unset his tag when pushed into nevigation controller

... I guess.
This is the situation:
here a simple method, in a view controller, where we can push a botton to go in another view:
- (IBAction)actionNext:(UIButton *)sender {
self.numeriUtiliListaViewController = [[ALCNumeriUtiliListaViewController alloc] init];
[self.numeriUtiliListaViewController.view setTag:[sender tag]];
[self.delegate vai:self.numeriUtiliListaViewController title:#"Numeri Utili"];
}
the delegate's method is:
- (void)vai:(id)view title:(NSString *)title
{
ALCParentViewController *viewController = (ALCParentViewController *)view;
viewController.delegate = self;
NSLog(#"tag: %d",[viewController.view tag]);
[self.myNavigationController pushViewController:viewController animated:YES];
}
This system works well, but the only thing is the tag that i've logged in this last method, here it was print correctly, but in the view loaded by the navigation controller, when i try to catch the value in the viewDidLoad, it's 0.
Any ideas?
Thanks in advance
Update 1 2013-01-30:
if i try to print the the tag in the viewWilAppear method of the viewcontroller pushed in the navigationcontroller, i'll give the right value... why? i don't know
Whats happening here is that in your actionNext method, when you are setting the tag of the viewController's view using : self.numeriUtiliListaViewController.view, as soon as you access the view propert of the viewController, viewDidLoad method is called in the viewController. So even before the setTag function is executed, viewDidLoad has already been executed, and it is showing tag = 0. But your viewWillAppear/viewDidAppear methods will be called only when the actual view appears and by then setTag has been executed, so it shows correct value.
Makes sense? Hope this helps

Navigating back to main ViewController dismissViewControllerAnimated dilemma

I have 2 ViewControllers directly connected with a push segue. I am navigating from first to second view controller by calling [self performSegueWithIdentifier:#"segueIdentifier" sender:sender]. On the second one I have an IBAction method that is bound to a "Done" button. Pressing that button should basically cause the first view controller to be displayed (sort of a back button). I managed to do that with:
NSArray *viewControllers = self.navigationController.viewControllers;
[self.navigationController popToViewController:[viewControllers
objectAtIndex:0] animated:YES];
I did try to achieve the same effect by using:
[self dismissViewControllerAnimated:YES completion:nil];
No matter what I tried though this didn't do the job. I am trying to understand what exactly am I missing but I can't figure it out. Does dismissViewControllerAnimated method work only with Modal segues ( this is the only thing that came to mind ).
Thank you
Yes,
- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion
is when a UIViewController is displayed modally.
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
should do what you are seeking.
So basically, in your second VC:
[self.navigationController popViewControllerAnimated:YES];
You will save you a lot of trouble if you read the UIViewController and UINavigationController references. Twice ;)