I have the following code:
#interface MyCell : UITableViewCell<UITextFieldDelegate>
{
IBOutlet UITextField *txtFields;
}
- (IBAction)textFieldAction:(id)sender;
#property (nonatomic,retain) IBOutlet UITextField *txtFields;
#end
I also have the following delegate function:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
return NO;
}
However, I notice that it's NEVER being called. I set the delegate from the interface builder as well as from code as per: [txtFields setDelegate:self]; but neither seems to work. Is there something else i'm missing for this?
You are obviously using this in conjunction with a UITableView. First, if you want to support user interaction, the txtFields must be a subview of the cell's contentView, not the backgroundView.
Assuming that the txtFields object is a subview of the contentView, then lets look at the connections.
The tableView has a a method cellForRowAtIndexPath: where you either return a new cell or a recycled cell. At the very bottom of that cell, add:
NSLog(#"textFields=%# delegate=%#", cell.txtFields, cell.txtFields.delegate);
assert(cell.txtFields.delegate == cell); // lets make sure this is proper
If in fact both arguments are there, you now know that the txtFields object is in the proper container (contentView), that the property is working, and that the delegate is set to the cell.
If that is all proper and you do not get the keyboard when you tap, then most likely something else is overlaying the txtFields - some other transparent view and its eating the touches.
In that case you should throw together a little demo app using the MyCell class, with even just one hardcoded cell, that demonstrates the problem, then upload that (zipped) to your DropBox account where others like myself can take a look at it and find the problem.
Try removing:
{
IBOutlet UITextField *txtFields;
}
since you have a #property already.
Also, did you #synthesize txtFields;?
Related
I'm actually in big troubles on how to get the Text from a TextField (and optionally a TextView ).
I'll try to make it simple: I have my PostIt.xib which is composed of 2 labels (which I don't really care about) and also one TextField and one TextView. Here is how I tried to get the text from these:
First, in my PostIt.h :
#interface PostIt : UIView {
IBOutlet UITextField *titre;
IBOutlet UITextView *commentaire; }
Then secondly, in my PostIt.m : (the real action of this method is that it close a view and normally throw back the information I want to get to another view, here: parent )
-(IBAction)doubleTap:(UITapGestureRecognizer *)recognizer{
[_parent setTitre:titre.text];
[_parent setCommentaire:commentaire.text];
[_parent setIsEdited:true];
[self removeFromSuperview]; }
My problem here is, when I call a NSLog (for example) to show me the Strings which are caught (probably a mistake here? sorry) it show me every time : (null)
I have been looking and trying a lot of answer i found but no one seems to be able to solve my problem...
If someone could help me it will be really nice, thanks in advance :)
Is there any more code pertaining to the UITextField?
Based on what I see here you need you first convert the input from the UITextField
into a string and then you can set the string where you want.
Updated to add the conversion code,
NSString *stringFromTextField = [yourTextField text];
Here is some more details,
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UITextField *yourTextField;
#end
Your Action,
- (IBAction)yourAction:(id)sender {
//Converting UItextfields into strings
NSString *stringFromTextField = [self.yourTextField text];
}
Here is a sample project I made for you on GitHub -
stringFromTextView
You should try to input to your code an object part if that's not already done, where you could directly pick up the data that you need and that's also from here that you should update your view.
Screencast: https://www.youtube.com/watch?v=ZwehDwITEyI
This is really bizarre. The problem is to do with a label outlet sitting in a custom-designed table cell. That cell is of my CustomCell class. (actually called RA_FormCell if you watch the screencast).
CustomCell.h
#property (weak, nonatomic) IBOutlet UILabel *dayOutlet;
-(void)controller:(id<CustomCellDelegate>)controller didUpdateDay:(NSString *)theDay;
CustomCell.m
// Method is called by a view controller
// (which is itself a delegate of the CustomCell class,
// hence the identifier you see below)
-(void)controller:(id<CustomCellDelegate>)controller didUpdateDay:(NSString *)theDay;
{
NSLog(#"Method called") // confirms to me that method is called
self.dayOutlet.text = #"Goodmorning";
NSLog(#"%#", self.dayOutlet.text); // displays (null)
}
That final log does actually appear, so the method is definitely being called. I have discounted the following:
self.dayOutlet.text is not written to elsewhere by any other method in the project
dayOutlet is connected to the label in the storyboard (and the label is not connected to anything else)
The label is not hidden underneath some accidental static label on the storyboard
The cell attributes on the storyboard include its class as CustomCell
No warnings or alerts in Xcode (I have been careful to avoid any circular imports)
The problem was that the controller:didUpdateDay: message was not sent to the correct instance of the cell class.
This occurred because I had not correctly assigned this cell to be the delegate for the view controller. For anyone interested, in my screencast at 3:50, you can see that I have the following in cellForRowAtIndexPath:
RA_FormCell *cell = [tableView dequeueReusableCellWithIdentifier:self.formCellArray[indexPath.row] forIndexPath:indexPath];
self.delegate = cell
However, this means that self.delegate got continually overwritten as the table cells were generated. As a result, my controller:didUpdateDay message was sent to the bottom cell of the table, and not the top one as I required.
The solution was simple - there's no need to have this second delegate at all. Instead, when the cell delegates to the view controller, it should pass self into the message it delegates:
id<CustomCellDelegate> strongDelegate = self.delegate;
if ([strongDelegate respondsToSelector:#selector(customCell:didChangeDay1:)])
[strongDelegate customCell:self didChangeDay1:[sender value]];
Then, in the implementation of this method by the delegate, simply end it by changing the outlet directly:
-(void)customCell:(RA_FormCell *)customCell didChangeDay1:(double)value
// put logic here
customCell.dayOutlet.text = #"No problem!";
In general, there should rarely be a need for a two-way delegate structure. Keep it one way, from A to B, and just remember to have A pass self in any messages it sends to B. That way, B will know the object the message came from, and be able to communicate back to A.
Thanks to Paulw11
I'm really going crazy on this.
But let me explain to you my little project first:
I have an Custom UITableView TDStartTableView.
Also in there I have some methods implemented for rendering the table. No problem there.
Inside of one TableViewCell there is a button.
When that Button is clicked it triggers this method:
- (void)triggerPush {
[self.delegate pushNextView];
}
self.delegate is specified in the .h file of TDStartTableView like this:
#property (nonatomic, weak) id<TDStartTableViewDelegate> delegate;
Also, the reference is set in my UITableViewController:
self.tableView.delegate = self;
So essentially what I'm trying to do is: Create a custom UITableView with Buttons etc. and then listen on the events from a ViewController that is implementing that UITableView and the protocol
So because the protocol forces me to implement pushNextView this method is in my UIViewController:
- (void)pushNextView {
NSLog(#"This works");
}
To this point everything works just fine, no problem there!
But now comes the tricky part.
I create a segue from my UIViewController to a new ViewController. I connect them via a segue and name the segue appropriately. pushToSecondStep.
Now one would think, that when I change the implementation of pushNextView to this
- (void)pushNextView {
[self performSegueWithIdentifier:#"pushToSecondStep" sender:self];
}
it works. But what I get is:
'Receiver (<TDFirstStepTableViewController: 0x8dc97d0>) has no segue with identifier 'pushToSecondStep''
Please help, I'm going crazy :D
The problem was, that I overwrote a constructor of TDStartTableView.
The proper form is that you implement all constructors, so that Objective-C can instantiate them all by itself:
- (id) initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
return self;
}
Also when you implement a custom UITableView Widget you shouldn't use UITableViewController but UIViewController.
Also you don't initialize your custom UITableView yourself, Storyboard already does that for you, so if you want to set special variables for it like numberOfRows then just declare a property and then set it via a setter-method outside and call [tableView reloadData].
Also, thanks https://stackoverflow.com/users/1095089/shubhank for helping me in the chat :)
This may sound silly, but read on...
I want to set the text of a UILabel from outside of a UIViewController that is instantiated by a storyboard. I need to make sure that the label property of the view controller is set when I set its text otherwise the label's text won't be set(because it won't be loaded yet to receive a text value).
Here's my current solution:
// Show pin entry
if (!self.pinViewController) {
// Load pin view controller
self.pinViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"pinScreen"];
self.pinViewController.delegate = self;
if (!self.pinViewController.view) {
// Wait for pin screen to fully load
}
[self.pinViewController setMessageText:#"Set a pin for this device"];
}
Initially I had a while loop that looped until the value of view was not nil, But it seems the very act of checking the view loads it(as mentioned here: http://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006926-CH3-SW37)
I tried using the isViewLoaded method with no success. It just looped forever.
I've gone forward with the above code as my current solution, but it feels wrong.
Is there a better way ensure a UIView has loaded?
I want to propose an alternative way where you don't have to rely on the availability of the view.
If you need to wait for the view to load before you can call other methods on your viewController you break encapsulation, because the viewController that calls your PinViewController has to know about the inner workings of your PinViewController. That's usually not a good idea.
But you could save objects like NSStrings in the PinViewController instance, and when the view of the PinViewController will appear you set its views according to the properties you have set before.
If you need to change the text of an label from outside your viewController you can also create a custom setter that sets the label.text for you.
Your .h
#interface PinViewController : UIViewController
#property (copy, nonatomic) NSString *messageText;
// ...
#end
And your .m
#implementation PinViewController
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.messageLabel.text = self.messageText;
}
// optional, if you want to change the message text from another viewController:
- (void)setMessageText:(NSString *)messageText {
_messageText = messageText;
self.messageLabel.text = messageText;
}
// ...
#end
viewDidLoad should solve this I guess.
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html
I would rather see you change your logic and do it the way that #MatthiasBauch shows in his answer. However, to answer your actual question, you can simply set a view property in order to force it to load:
self.pinViewController.view.hidden = NO;
The problem is simple to explain but difficult for me to resolve. I have a property that is NEVER initialized.
First of all, I'm using the iCarousel custom class in order to display some images for my app. In one of its delegate methods (the one that it uses in order to know which view is going to show at some index), I use this code:
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
if(!view)
{
CustomController* controller = [self.storyboard instantiateViewControllerWithIdentifier: "identifier"];
//BTW, the CustomController is initialized properly. Its instance is not nil after the initialization.
controller.imageView.image = [UIImage imageNamed: "something.png"];
view = controller.view;
}
return view;
}
As you can see, the view that I show in my carousel is a custom view with its own controller. I initialize it using the storyboard method and then I just set the image in my imageView property, which is, obviously, an UIImageView.
Don't get excited and say that I'm not initializing my imageView, because I have a custom getter in my "CustomController" class. Like this:
//interface (.h)
...
#property (nonatomic, strong) UIImageView* imageView;
...
//implementation (.m)
...
#synthesize imageView = _imageView;
...
- (UIImageView*) imageView
{
if(!_imageView)
_imageView = [[UIImageView alloc] init];
return _imageView;
}
...
Believe it or not, even if I put a breakpoint in the "_imageView = [[UIImageVIew alloc] init];"... the program executes that line but the _imageView remains nil. ¿Why?
I don't want to know "How to set my property", so please don't give workarounds for this... what I want to know is "Why my property is never setted and remains nil always", what's am I doing wrong?.
I've also tried to use my imageView as an IBOutlet... but even if I link it to an imageView in the Interface Builder and check its value after the "viewDidLoad", it still remains nil.
P.S: Btw, I'm using ARC (yeah, I know is in the title... xD)
Well, it looks like the answer was what borrrden said, the problem was the LLDB debugger. Actually, my property was initialized but the debugger didn't detect it like that, if I change it to GDB I could see it wasn't nil after all. Furthermore, the reason why I had also issues with my child viewcontroller's outlets was because I didn't use the View Controller Container methods in iOS5 (DidMoveParentViewController and those ones).
Kinda tricky.