Is there any way to add a second parameter in a custom UIView class in the drawRect method?
I am currently using a UIView to draw a text string but the text itself is set in the drawRect method. Is there any way to pass in the text variable in something like
- (void) drawRect:(CGRect)rect(NSString *)text
and if not are there any alternative work arounds?
Thanks
You would generally have a custom #property for your UIView subclass:
#property (nonatomic, copy) NSString *text;
You might even have a custom setter that calls setNeedsDisplay, such that when you set the text property, the view's drawRect will get called, e.g.:
- (void)setText:(NSString *)text
{
_text = [text copy];
[self setNeedsDisplay];
}
Your drawRect could then reference self.text when it needs to reference that NSString.
Related
I am using custom delegation with my UITextField in a custom UITableViewCell. Basically I have UITextFields on my UITableView, and in Edit mode, I want to be able to edit the content inside the UITextField.
My issue is that when I go into Edit mode and try to type something in the text field, I am only able to type one character and it doubles. In this example, I tried to type "p" and it only lets me type "p" and it changes to "pp".
Here's my code. As an FYI I am pretty new to iOS/programming/custom delegation/custom UITableViewCells.
UITableViewCell subclass .h:
#protocol MenuTableViewCellDelegate <NSObject>
- (void)updatedFoodItem:(NSString *)foodItem fromCell:(id)sender;
#end
#interface MenuTableViewCell : UITableViewCell <UITextFieldDelegate>
#property (nonatomic, weak) id <MenuTableViewCellDelegate> delegate;
#property (weak, nonatomic) IBOutlet UITextField *foodTextField;
#property (weak, nonatomic) IBOutlet UITextField *priceTextField;
#end
UITableViewCell .m:
- (void)awakeFromNib {
self.foodTextField.delegate = self;
}
// Delegate method for tableview cell - food item text field is within cell.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
[self.delegate updatedFoodItem:string fromCell:self];
return YES;
}
In my ViewController.m:
- (void)updatedFoodItem:(NSString *)foodItem fromCell:(MenuTableViewCell *)cell
{
NSIndexPath *p = [self.menuTableView indexPathForCell:cell];
id item = self.menuItemsArray[p.row];
cell.foodTextField.text = foodItem;
}
By the way I realize that the above probably isn't updating my data yet, I haven't figured it out yet so any advice would be great.
The problem is that you're calling your updatedFoodItem: method and then returning YES in your shouldChangeCharactersInRange: function. Essentially what's happening is:
1 - shouldChangeCharactersInRange: is called
2 - This function calls updatedFoodItem:
3 - The updatedFoodItem: function sets the cell's text field to the original text passed in
4 - The shouldChangeCharactersInRange: method returns YES, appending the same text that was just set in the updatedFoodItem: function to the cell's label
I'm not sure exactly what you're trying to do (maybe you're trying to save the food item into your self.menuItemsArray?), but you should either not set the cell's text in the updatedFoodItem: function, or you should return NO in your shouldChangeCharactersInRange: function.
I am trying to show a label for some seconds when i press a button. But the hide function is not working properly.
-(void) hide_label:(NSString *)value{
[value setHidden:YES];
}
Get the error: No Visible #interface for 'NSString' declares the selector 'setHidden:'.
In your example, value is an NSString, not the UILabel. NSString's have no setHidden: method, as the error message suggests.
Instead, you will want to pass in the label itself and then call setHidden:.
So, change the method to:
- (void) hide_label:(UILabel *)label {
[label setHidden:YES];
}
And change all parts of the code that call this method to pass in the UILabel.
NSString is not a subclass of UILabel and does not respond to setHidden: you must call that on the UILabel property itself.
How do you declare your UILabel? It should be something similar to the following if you connect via a nib:
#property (nonatomic, weak) IBOutlet UILabel *label;
or if its created programatically:
#property (nonatomic, strong) UILabel *label;
You can then call setHidden on the label, as it is a property you can use dot syntax:
label.hidden = YES;
You can check its state by using its accessor:
if ([label isHidden]) {
//... do something
}
It might be worth you reading some tutorials on iOS development, Look Here on raywenderlich.com
How Can I copy UITextField string to UITextView?
I want to do it when UIButton;
[myUIButton addTarget:self action:#selector(touchButton) forControlEvents:UIControlEventTouchUpInside];
UITextField* textField (initialized, omit code here)
[self.view addSubview:textField];
//save string to the property
self.textFieldString = textField.text;
//textFieldString is #property NSString* textFieldString; at the header.
UITextView* textView (initialized, omit code here)
[self.textView setEditable:false];
[self.view addSubview:self.textView];
//here i want to implement UITextField string -> UITextView display
-(void)submitButtonClicked {
//....
//Problem i am having here is that, I can not see instance variable other than #property variable. How should I pass UITextField .text to UITextView?
}
Prepare the identifier to each UI
[textField setTag:100];
[self.view addSubview:textField];
[textView setTag:200];
[self.view addSubview:textView];
Identify the each UI element and Manage
-(void)submitButtonClicked {
//Problem i am having here is that,
// I can not see instance variable other than #property variable.
// How should I pass UITextField .text to UITextView?
UITextField *myTextField=(UITextField*)[self.view viewWithTag:100];
UITextView *myTextView=(UITextView*)[self.view viewWithTag:200];
myTextView.text=myTextField.text;
}
If you are creating UITextView programatically then create a property variable and synthesize the same. You can access the same using the synthesized name and in UIButton action method get the text and set it to UITextView.
In .m file you can declare UITextView as
#interface classname () {
UITextView *textView
}
or in .h file
#property (nonatomic, strong) UITextView *textView;
As you have described the problem 'Problem i am having here is that, I can not see instance variable other than #property variable. How should I pass UITextField .text to UITextView?'
In your button's action use:
textView.text=textField.text;
Declare your variables between #interface and #end and initialize them in the viewDidLoad. This way you'll be able to use them in your button's action.
#interface ViewController ()
{
UITextView *textView;
UITextField *textField;
}
#implementation ViewController
-(void) viewDidLoad
{
// Do the following
// Initialize both textView and textField
// Set their frames
// Add both of them as a subview to your view
}
#end
Now you'll be able to access both of them in your button's action.
Hope this helps.
Edit:
I'm drawing a line using drawRect: function which resides in a custom class in a view which I created in the MainStoryboard.storyboard file. The view does point to the custom class (draw2D) in the interface builder.
All code i have regarding draw in my main file(viewController) is now:
(header file)
#class draw2D;
#property (weak, nonatomic) IBOutlet draw2D *draw;
(m file)
#import "draw2D.h"
[draw.listOfFreqToDraw addObject: closestChar];
[draw setNeedsDisplay];
The problem I seem to have now is that it only runs the drawRect method in draw2D class once and never calls it again (therefor listOfFreqToDraw isn't even called after the first run)
You can always change a variable in draw2D
Set this up in the draw2D.h
#property (nonatomic, strong) NSMutableArray * listOfFreqToDraw;
in draw2D.m
- (void)drawRect:(CGRect)rect {
for (UIBezierPath *path in self. listOfFreqToDraw) {
[path stroke];
}
}
and in your main class
[draw.listOfFreqToDraw addObject: closestChar];
[draw setNeedsDisplay];
I am subclassing UITextField to to display some data. I want to use the same datasource - delegate pattern like UITableView.
#interface MySubClass : UITextField <UITextFieldDelegate>
#property (nonatomic, unsafe_unretained) id<MyDataSource> myDatasource;
#property (nonatomic, unsafe_unretained) id<MyDelegate> myDelegate;
-(void) loadStuff;
#end
#implementation MySubClass
-(id) initWithFrame:(CGRect)frame {
...
self.delegate = self; // For the UITextField
...
}
-(void) layoutSubviews {
[self doStuff];
}
-(void) loadStuff {
Data * data = [self.myDatasource ...];
NSString * string = // do stuff to the data for display
self.text = string; //Calls layoutSubviews again, infinite loop.
}
#end
I thought about using layoutSubviews to fetch data from the datasource, and display it.The problem with that is, setting the text to the data I just processed, triggers a call to layoutSubviews again. So you have an infinite loop.
In fact changing the view in anyway seems to trigger a call to layoutSubviews.
Is it possible to duplicate what UITableView does with its datasource?