I have a view controller class with the following code:
-(void) awakeFromNib{
RootModel *rm = [RootModel sharedModel];
for(NSString *title in rm.rLevels) {
[self addNewButtonWithTitle:title];
}
}
// add a new button with the given title to the bottom of the list
- (void)addNewButtonWithTitle:(NSString *)title
{
// create a new button
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
}
the statement
[self addNewButtonWithTitle:title];
generates a warning:
method addNewButtonWithTitle not found.
Con't figure it out.
Thanks
You have 3 options to get rid of the warning:
Declare the method in the #interface block.
If you do not want to expose the method in your interface:
Declare the method in a class extension.
Implement the method above the first call to it.
Have you added method in .h file ?
You need to declare that method in your header file and if not then the method definition should be above the place where you call it.
So in your header file of whereever you have written #interface add the line :
- (void)addNewButtonWithTitle:(NSString *)title
Related
I'm new in iphone development.now, I'm facing one warning in my project.while,setting the delegate of UITextfield in ios 6 I'm getting the warning that
"**incompatible pointer types sending 'class' to parameter of type '<uitextfielddelegate>'**"
+(UITextField*)tableLabelForText:(NSString *)txt frame:(CGRect)frm isEditable:(BOOL)isEditable
{
UITextField *txtField = [[UITextField alloc] initWithFrame:frm];
[txtField setEnabled:isEditable];
[txtField setText:txt];
[txtField setTextColor:[UIColor blackColor]];
[txtField setDelegate:self];
return txtField;
}
You are trying to assign the delegate in a class method which has no idea of the initialised object. Hence the warning. What you need to do is setDelegate to the initialised object.
[txtField setDelegate:<MyObject>];
Or you can as one of the answers suggests change the class methods to instance method.
-(UITextField*)tableLabelForText:(NSString *)txt frame:(CGRect)frm isEditable:(BOOL)isEditable
You are using a Class level method "+" to return a text field instance, change it to Instance Level Method "-". i.e:
-(UITextField*)tableLabelForText:(NSString *)txt frame:(CGRect)frm isEditable:(BOOL)isEditable
If I am not wrong , you are setting Delegate for an NSObject class ,
as NSObject class does not have any views , so UITextFieldDelegate does not confirms to the class. Instead use UIView
#interface ClassName : UIView <UITextFieldDelegate>
So please forgive me as I am very new to stackoverflow and to ios programming in general.
I am attempting to change the text of a button i have, replacing current text with a date string (dateStringForInput) I am passing in from another class. The button is called myTodayButton and is declared in my .h file for my class inputMilesViewController...
#property (strong, nonatomic) IBOutlet UIButton *myTodayButton;
Below is the code from my .m.
+(void) changeButtonText:(NSString*) dateStringForInput{
NSLog(#"we got to changebuttontext");
[_myTodayButton setTitle:dateStringForInput forState:UIControlStateNormal];
}
I am getting the following error "Instance variable "_myTodayButton" accessed in class method.
I understand that this is written in a class method rather than an instance method but i cant figure out how to get this change to happen. the button which prompts this call to changeButtonText is in the other class which is creating dateStringForInput.
Try like this...
For (+) instance.
+ (void) changeButtonText: Only have access to the self object.
--Step 1: Remove follwing line from header file
#property (strong, nonatomic) IBOutlet UIButton *myTodayButton;
--Step 2:
Add UIButton *myTodayButton in your class file globally..
That means declare before #implementation
Eg: In .m File
#import "Controller.h"
UIButton *myTodayButton // Add like this before #implementation
#implementation Controller
For (-) instance
- (void) changeButtonText: Only have access to the instance methods
Class methods do not have access to instance variables, that's why you're getting the error you're seeing.
You need to change the method to an instance method:
- (void)changeButtonText:(NSString *)dateStringForInput;
Then you will need to pass or obtain a reference to the instance of the class containing the method to the class calling the method.
I hope that makes sense... Add a comment if you need any clarification!
change method to an instance method instead of a class method ("-" instead of "+") create an instance of the class and then simply call it like so:
MyClass *classInstance = [[MyClass alloc] init];
[classInstance changeButtonText:#"stringText"];
Also its recommended to have weak properties for IBOutlets.
#property (nonatomic, weak) IBOutlet UIButton *myButton;
[EDIT]
Regarding your second issue with segues. Firstly do you really need a different view controller for simply displaying a UIDatePicker? I normally display them in the same UIViewController using an actionSheet, its a little work to get just right but solves this problem. I can post the code if you like?
Anyway if you want to keep your current setup I would do the following:
In the ViewController that contains the button create a new public NSString property in the .h file.
#property (nonatomic, strong) NSString *dateString;
In the View Controller that contains the date picker, after the user has selected the date override the perpareForSegue method. In here get the destination view controller (which is the one with the button and new string property created in point one above) and set the dateString.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
MyViewController *todayViewController = (MyViewController*)[segue destinationViewController];
[todayViewController setDateString:#"valueYouRequire"];
}
In the ViewController with the button set the button's title in the viewDidLoad to be the dateString.
(void)viewDidLoad
{
[super viewDidLoad];
if (self.dateString) [self.myTodayButton setTitle:self.dateString forState:UIControlStateNormal];
}
[EDIT]
If you want to go down the actionSheet route then add this method to the ViewController with the button and play around with the frame sizes to fit your needs. The method below creates a date picker, adds it to an actionSheet and displays the actionSheet.
- (IBAction) datePressed:(id)sender {
if (!_actionSheet) {
_actionSheetFrame = CGRectMake(0, self.view.frame.size.height - 373, 320, 403);
_actionSheetBtnFrameOk = CGRectMake(20, 330, 280, 50);
_actionSheetBtnFreameCancel = CGRectMake(20, 275, 280, 50);
_pickerFrame = CGRectMake(0, 50, 320, 216);
_actionSheet = [[UIActionSheet alloc] initWithTitle:#"Select Date" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"OK", nil];
_datePicker = [[UIDatePicker alloc] init];
[_datePicker setDatePickerMode:UIDatePickerModeDate];
[_actionSheet addSubview:_datePicker];
}
[_datePicker setMaximumDate:[NSDate date]];
[_actionSheet showInView:self.view.superview];
[[[_actionSheet subviews] objectAtIndex:kActionBtnIndexOk] setFrame:_actionSheetBtnFrameOk];
[[[_actionSheet subviews] objectAtIndex:kActionBtnIndexCancel] setFrame:_actionSheetBtnFreameCancel];
[_actionSheet setFrame:_actionSheetFrame];
[_datePicker setFrame:_pickerFrame];
}
You will also have to implement the UIActionSheetDelegate method to set the button's text once the user has selected his desired date.
#pragma mark - UIActionSheet Delegate Methods
- (void) actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
[self.myTodayButton setTitle:self.dateStringFromSelectedDate forState:UIControlStateNormal];
}
}
is there a way to pass a boolean to the addClicked method beside using button.tag for the code below?
[cellview.buttonAdd addTarget:self action:#selector(addClicked:) forControlEvents:UIControlEventTouchUpInside];
-(void) addClicked:(id)sender {
}
THanks in advance.
if you want to add a integer property , you can use tag.
if you want to add a nonInteger property , you must use a category with Associative References,the inheritting UIButton can not post property at all.
you can see this :
Subclass UIButton to add a property
Try something like this:
-(void) addClicked:(id)sender
{
UIButton * button = (UIButton*)sender;
NSLog(#"Button Tag: %i", button.tag);
}
Not sure what you mean by pass Boolean.
Short answer: You cannot pass extra information into the method directly.
Why would you want to do that anyway though? What does the button "know" that it would need to communicate, other than the fact that it was clicked?
The way this should be done is via an instance variable in the class that implements the click handler.
If you really must maintain state inside the button itself, subclass it:
#interface CustomButton : UIButton
#property (nonatomic, assign) BOOL myBoolValue;
#end
/* ... */
- (void)addClicked:(id)sender
{
CustomButton *button = (CustomButton *)sender;
if (button.myBoolValue) {
// Whatever you want to do.
}
}
I'm trying to sub class the uibutton class and add some extra metheds to it.
If I ceate a class as follows
cTest *mTest=[cTest buttonWithType:UIButtonTypeRoundedRect];
and call any methed, one i created or allready there, example [cTest setTitle:#"test" forState: UIControlStateNormal]; crashes.
my cTest class:
#import <Foundation/Foundation.h>
#interface cTest : UIButton {
int i;
}
-(void) aTest;
#end
code to test the class:
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
// this works fine
UIButton *mBut=[UIButton buttonWithType:UIButtonTypeRoundedRect];
[mBut setTitle:#"test" forState: UIControlStateNormal];
// this does NOT
cTest *mTest=[cTest buttonWithType:UIButtonTypeRoundedRect];
[cTest setTitle:#"test" forState: UIControlStateNormal];
[mTest aTest]; // crashes here does not call my function
}
Ted
UIButton buttonWithType: simply returns a UIButton* object, not a cTest* object.
You wil have to provide a class method (factory method)
+ (cTest*) cTestWithType:
That one does not call [super buttonWithType:...] neither.
Instead of that you will have to create a new cTest object with alloc (and retain or autorelease, what ever serves your purpose best) and initialize it by setting the buttonType property.
... or just do the same without providing a factory method.
+buttonWithType: is not guaranteed to return an instance of the class it's called on. If you specify UIButtonTypeRoundedRect, a private subclass of UIButton will be returned: UIRoundedRectButton.
To get an instance of your subclass, either override +buttonWithType:, or call a different initializer, like -initWithFrame:, or -init.
It you want to add method to the UIButton, then the Objective-C: Categories may help.
#interface UIButton (Extend)
-(void) aTest;
#end
Reference at: http://macdevelopertips.com/objective-c/objective-c-categories.html
Is there any way to insert an NSLocalizedString in interface builder.
For example set a label text to a localized string instead of a static string?
I really hate to create a property for every single item that requires a localized string.
This post might have some tips for you:
http://blog.wilshipley.com/2009/10/pimp-my-code-part-17-lost-in.html
Even if this post is old, for those interested in automatically localizing your IB files, check this out: https://github.com/angelolloqui/AGi18n
DISCLAIMER: I am the developer of the library
You can take advanced of the User Defined Runtime Attributes:
http://cupobjc.blogspot.com.es/2014/04/interfaz-builder-localization.html
First define a new category for UILabel:
#import "UILabel+Localized.h"
#implementation UILabel (Localized)
-(void) setTextLocalized:(NSString *)aText{
[self setText:NSLocalizedString(aText, nil)];
}
#end
Then in the interface builder, User Defined Runtime Attributes :
textLocalized String your string to localized
To avoid creating a bunch of categories, create just one that categorize the NSObject and then check for the isKindOfClass as suggested. See the code below:
#import "NSObject+Localized.h"
#implementation NSObject (Localized)
///
/// This method is used to translate strings in .xib files.
/// Using the "User Defined Runtime Attributes" set an entry like:
/// Key Path: textLocalized
/// Type: String
/// Value: {THE TRANSLATION KEY}
///
-(void) setTextLocalized:(NSString *)key
{
if ([self isKindOfClass:[UILabel class]])
{
UILabel *label = (UILabel *)self;
[label setText:NSLocalizedString(key, nil)];
}
else if ([self isKindOfClass:[UIButton class]])
{
UIButton *button = (UIButton *)self;
[button setTitle:NSLocalizedString(key, nil) forState:UIControlStateNormal];
}
else if ([self isKindOfClass:[UIBarButtonItem class]])
{
UIBarButtonItem *button = (UIBarButtonItem *)self;
[button setTitle:NSLocalizedString(key, nil)];
}
}
#end
NSLocalizedString is not the recommended way to localize Interface Builder files. Check out ibtool:
http://www.bdunagan.com/2009/03/15/ibtool-localization-made-easy/
I have done same thing as #OAK mentioned. Here is full code.
Interface Builder Localization HowTo