I am new to xcode iOS programming and I really need your help with the error of unrecognised selector sent to instance. Below is my implementation
//.h file
#interface AppAccountController : UIViewController <UIAlertViewDelegate>{
IBOutlet UITextField *txtName;
IBOutlet UITextField *txtEmail;
IBOutlet UIDatePicker *dateOB;
IBOutlet UITextField *txtPwd;
IBOutlet UITextField *txtRePwd;
}
- (IBAction)btnSave:(id)sender;
#end
//.m file
#interface AppAccountController ()
#property (strong, nonatomic) IBOutlet UITextField *txtName;
#property (strong, nonatomic) IBOutlet UITextField *txtEmail;
#property (strong, nonatomic) IBOutlet UIDatePicker *dateOB;
#property (strong, nonatomic) IBOutlet UITextField *txtPwd;
#property (strong, nonatomic) IBOutlet UITextField *txtRePwd;
#property (strong, nonatomic) IBOutlet UIButton *btnSave;
#end
#implementation AppAccountController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (IBAction)btnSave:(id)sender {
// Create strings to store the text info
NSString *name = [txtName text];
NSString *email = [txtEmail text];
NSDate *dob = [dateOB date];
NSString *passwd = [txtPwd text];
NSString *repasswd = [txtRePwd text];
if ([txtName.text isEqualToString:#""])
{
[txtName becomeFirstResponder];
UIAlertView* finalCheck = [[UIAlertView alloc]
initWithTitle:#"Attention"
message:#"Name Field is empty. Please enter a name"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil] ;
[finalCheck show];
finalCheck.tag = 1;
}
else if ([txtEmail.text isEqualToString:#""])
{
[txtEmail becomeFirstResponder];
UIAlertView* finalCheck = [[UIAlertView alloc]
initWithTitle:#"Attention"
message:#"Email Field is empty. Please enter an Email"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil] ;
[finalCheck show];
finalCheck.tag = 2;
}
else if ([txtPwd.text isEqualToString:#""])
{
[txtPwd becomeFirstResponder];
UIAlertView* finalCheck = [[UIAlertView alloc]
initWithTitle:#"Attention"
message:#"Password Field is empty. Please enter a Password"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil] ;
[finalCheck show];
finalCheck.tag = 3;
}
else if ([txtRePwd.text isEqualToString:#""])
{
[txtRePwd becomeFirstResponder];
UIAlertView* finalCheck = [[UIAlertView alloc]
initWithTitle:#"Attention"
message:#"Confirm Password Field is empty. Please enter to confirm Password"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil] ;
[finalCheck show];
finalCheck.tag = 4;
}
else if (![passwd isEqualToString:repasswd])
{
[txtPwd becomeFirstResponder];
UIAlertView* finalCheck = [[UIAlertView alloc]
initWithTitle:#"Attention"
message:#"Passwords do not match. Please enter to confirm Password"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil] ;
[finalCheck show];
finalCheck.tag = 5;
}
else{
// Store the data
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:name forKey:#"name"];
[defaults setObject:email forKey:#"email"];
[defaults setObject:passwd forKey:#"passwd"];
[defaults setObject:dob forKey:#"dob"];
[defaults synchronize];
NSLog(#"Data saved");
[self performSegueWithIdentifier:#"saveLoad" sender:self];
}
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if(alertView.tag == 1) {
[txtName becomeFirstResponder];
NSLog(#"Name AlertView is clicked");
}
else if(alertView.tag == 2) {
[txtEmail becomeFirstResponder];
NSLog(#"Email AlertView is clicked");
}
else if(alertView.tag == 3) {
[txtPwd becomeFirstResponder];
NSLog(#"Password AlertView is clicked");
}
else if(alertView.tag == 4) {
[txtRePwd becomeFirstResponder];
NSLog(#"Re-Password AlertView is clicked");
}
else if(alertView.tag == 5) {
[txtRePwd becomeFirstResponder];
NSLog(#"Re-Password AlertView is clicked");
}
}
#end
Whenever I press the btnSave button or after moving on to another UI element (one element gaining focus after another one losses it), I get unrecognised selector sent to instance.
UPDATE
2014-12-18 18:06:23.794 XPB[964:35743] -[AppAccountController btnSave:forEvent:]: unrecognized selector sent to instance 0x7fd949d923f0
2014-12-18 18:06:23.834 XPB[964:35743] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[AppAccountController btnSave:forEvent:]: unrecognized selector sent to instance 0x7fd949d923f0'
*** First throw call stack:
(
0 CoreFoundation 0x000000010bd2df35 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010a182bb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010bd3504d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x000000010bc8d27c ___forwarding___ + 988
4 CoreFoundation 0x000000010bc8ce18 _CF_forwarding_prep_0 + 120
5 UIKit 0x00000001087e98be -[UIApplication sendAction:to:from:forEvent:] + 75
6 UIKit 0x00000001088f0410 -[UIControl _sendActionsForEvents:withEvent:] + 467
7 UIKit 0x00000001088ef7df -[UIControl touchesEnded:withEvent:] + 522
8 UIKit 0x000000010882f308 -[UIWindow _sendTouchesForEvent:] + 735
9 UIKit 0x000000010882fc33 -[UIWindow sendEvent:] + 683
10 UIKit 0x00000001087fc9b1 -[UIApplication sendEvent:] + 246
11 UIKit 0x0000000108809a7d _UIApplicationHandleEventFromQueueEvent + 17370
12 UIKit 0x00000001087e5103 _UIApplicationHandleEventQueue + 1961
13 CoreFoundation 0x000000010bc63551 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
14 CoreFoundation 0x000000010bc5941d __CFRunLoopDoSources0 + 269
15 CoreFoundation 0x000000010bc58a54 __CFRunLoopRun + 868
16 CoreFoundation 0x000000010bc58486 CFRunLoopRunSpecific + 470
17 GraphicsServices 0x000000010c64e9f0 GSEventRunModal + 161
18 UIKit 0x00000001087e8420 UIApplicationMain + 1282
19 XPB 0x00000001083965b3 main + 115
20 libdyld.dylib 0x000000010ce4b145 start + 1
21 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
The problem is that btnSave: and btnSave:forEvent: are two different things.
Your AppAccountController has a btnSave: method, so it can be sent the btnSave: message. But it has no btnSave:forEvent: method. Unfortunately, that's the selector you specified to be used whenever the button is pressed. The button is trying to send btnSave:forEvent: to your AppAccountController, and AppAccountController doesn't know what to do with that. So it crashes.
The easiest solution is to fix the button so that it sends btnSave: and not btnSave:forEvent:. (You will almost never need the two-parameter variant of an action method in any case.)
Related
I've been working on a app that displays the current location of the user in a UILabel using the core location framework in Xcode When a button is clicked the app calls the CLLocationManager that gets the users latitude and longitude. I also included reverse geocoding to present the coordinates in a human readable form. I have this code here.
Header file
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController <CLLocationManagerDelegate>
#property (strong, nonatomic) IBOutlet UILabel *latitudeLabel;
#property (strong, nonatomic) IBOutlet UILabel *longitudeLabel;
#property (strong, nonatomic) IBOutlet UILabel *addressLabel;
- (IBAction)getCurrentLocation:(id)sender;
#end
Implementation file
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController {
CLLocationManager *locationManager;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
locationManager = [[CLLocationManager alloc] init];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)getCurrentLocation:(id)sender {
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:#"Error" message:#"Failed to Get Your Location" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
_longitudeLabel.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
_latitudeLabel.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
}
}
#end
I got this output
Message from debugger: Terminated due to signal 15
I am using the below code for UIAlertController in my project.
if([[[UIDevice currentDevice] systemVersion]floatValue] >= 8.0){
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:#"Input Error"
message:#"Please enter a valid email."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* okAction = [UIAlertAction
actionWithTitle:#"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:okAction];
[self presentViewController:alert animated:YES completion:nil];
}
else
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Input Error"
message:#"Please enter a valid email"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil];
[alertView show];
}
I am getting the below waring message:
Warning: Attempt to present <UIAlertController: 0x7f8da58df1f0> on <MBComplaintsViewController: 0x7f8da36454d0> which is already presenting (null)
Kindly guide me how to properly use UIAlertController using Objective C.
Thanks,
Abin Koshy Cheriyan
Yes as per #Alexander you should not be dismissing the alert controller like this explicitly.
As per an apple engineer a new window gets added each time an UIAlertController is displayed so when we go for dismissing it the window is still there though the alert controller disappears.
So there are two ways to handle this -
Way 1 - No explicit dismiss
Do not explicitly dismiss the UIAlertController, let it be done by the user
Way 2 - Use your own window
Simply create a category on UIAertController
Here is the sample code -
.h
#import <UIKit/UIKit.h>
#interface UIAlertController (MyAdditions)
#property(nonatomic,strong) UIWindow *alertWindow;
-(void)show;
#end
In .m
#import "UIAlertController+MyAdditions.h"
#import <objc/runtime.h>
#implementation UIAlertController (MyAdditions)
#dynamic alertWindow;
- (void)setAlertWindow:(UIWindow *)alertWindow {
objc_setAssociatedObject(self, #selector(alertWindow), alertWindow, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIWindow *)alertWindow {
return objc_getAssociatedObject(self, #selector(alertWindow));
}
- (void)show {
self.alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.alertWindow.rootViewController = [[UIViewController alloc] init];
// window level = topmost + 1
UIWindow *topWindow = [UIApplication sharedApplication].windows.lastObject;
self.alertWindow.windowLevel = topWindow.windowLevel + 1;
[self.alertWindow makeKeyAndVisible];
[self.alertWindow.rootViewController presentViewController:self animated:YES completion:nil];
}
-(void)hide {
self.alertWindow.hidden = YES;
self.alertWindow = nil;
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
// just to ensure the window gets desroyed
self.alertWindow.hidden = YES;
self.alertWindow = nil;
}
To show the alert controller
UIAlertCntroller *alert = ## initialisation##;
// will show the alert
[alert show];
//to dismiss
[alert hide];
[alert dismissViewControllerAnimated:YES completion:nil];
Even you can checkout one of my sample implementation here
I don't know about your problem, but you shouldn't do that
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
It will be anyway dismissed on any of your actions.
EDIT: figured out that the NSNumber was a bad type to bind to. Using NSString instead solved the problem
I have a ToDo entity which has a to-one relationship ("title") with the ToDoTitle entity, and the relationship in reverse("todos") is to-many . i.e. a todo can have one title, but a title can have multiple todos.
Now I want to add a separate NSNumber on top of my NSManagedObject for count of the "incomplete todos" i.e. they have a todo.todoStatus == FALSE.
It looks like this:
#interface ToDoTitle : NSManagedObject
#property (nonatomic, strong) NSNumber * displayOrder;
#property (nonatomic, strong) NSString * title;
#property (nonatomic, strong) NSSet *todo; // this is saved in Core Data model
#property (nonatomic, strong) NSNumber *incompleteCount; // this isn't in the Core Data model
I can tweak the incompleteCount getter to return the correct count of items, and this works:
- (NSNumber *) incompleteCount {
[self willAccessValueForKey:#"incompleteCount"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"todoStatus == FALSE"];
NSSet *incomplete = [[self primitiveValueForKey:#"todo"] filteredSetUsingPredicate: predicate];
[self didAccessValueForKey:#"incompleteCount"];
return #([incomplete count]);
}
Now what I really use this for is for Cocoa Bindings, to display this number on a button. The binding works from the NSButton to a NSTableViewCell with the model key path = "objectValue.managedObject.incompleteCount.stringValue"
This also works fine, and displays the correct data initially. I also implement this in TodoTitle to keep track of changes to the 'todo' set:
+ (NSSet*) keyPathsForValuesAffectingIncompleteCount {
return [[NSSet alloc] initWithObjects: #"todo", nil];
}
so now when I add or delete ToDo objects, the count for each title gets updated correctly as well.
What I can't figure out how to update this incompleteCount when I update one of the todo object's todoStatus. I need to do something like this in the ToDo managed object:
- (void) setTodoStatus:(NSNumber *)todoStatus {
[self willChangeValueForKey:#"todoStatus"];
[self setPrimitiveValue:todoStatus forKey:#"todoStatus"];
if (todoStatus.boolValue == YES) {
self.todotitle.incompleteCount = #(self.todotitle.incompleteCount.integerValue - 1);
}
[self didChangeValueForKey:#"todoStatus"];
}
I get this error:
2014-08-03 22:27:26.632 CJ[9487:303] Cannot update for observer
for the key path
"incompleteCount.stringValue" from , most
likely because the value for the key "incompleteCount" has changed
without an appropriate KVO notification being sent. Check the
KVO-compliance of the ToDoTitle class.
with this stack trace:
2014-08-03 22:27:26.634 Contacts Journal[9487:303] (
0 CoreFoundation 0x00007fff8b5c525c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff8f25be75 objc_exception_throw + 43
2 CoreFoundation 0x00007fff8b5c510c +[NSException raise:format:] + 204
3 Foundation 0x00007fff92c134b0 -[NSKeyValueNestedProperty object:withObservance:didChangeValueForKeyOrKeys:recurse:forwardingValues:] + 1003
4 Foundation 0x00007fff92ba6fd9 NSKeyValueDidChange + 166
5 Foundation 0x00007fff92babbe6 -[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:] + 118
6 CoreData 0x00007fff88542b01 -[NSManagedObject didChangeValueForKey:] + 113
7 CJ 0x00000001000d664e -[ToDo setTodoStatus:] + 318
8 CJ 0x00000001000ff2a9 -[ToDo(ToDo_Category) updateStatusToComplete] + 345
I'm just not sure to update the incompleteTodos object in a KVO-compliant way. I've tried various things, like wrapping the call inside willChangeValueForKey: and didChangeValueForKey: but doesn't seem to help:
- (void) setTodoStatus:(NSNumber *)todoStatus {
[self willChangeValueForKey:#"todoStatus"];
[self setPrimitiveValue:todoStatus forKey:#"todoStatus"];
if (todoStatus.boolValue == YES) {
[self.todotitle willChangeValueForKey:#"incompleteCount"];
self.todotitle.incompleteCount = #(self.todotitle.incompleteCount.integerValue - 1);
[self.todotitle didChangeValueForKey:#"incompleteCount"];
}
[self didChangeValueForKey:#"todoStatus"];
}
I'm not sure what I'm doing wrong here. I've also tried adding a custom setter in TodoTitle, with and without the willChange/didChange calls:
- (void) setIncompleteCount:(NSNumber *)incompleteCount_ {
incompleteCount = incompleteCount_;
}
but still get the same problem.
Any idea what's wrong here?
Well, it turns out that if I change incompleteCount type to an NSString instead of an NSNumber, and turn the integer into a string, it works fine! Must be some problem with NSNumber's stringValue not updating with the binding? I don't know. Wasted half a day on this!
I am attempting to code an iPhone/iPad screen that outputs a value based on what is entered in a text field and what is selected in a 2-component picker. I have the basics done, right up to the point of having the entered/selected data appear, but short of performing the calculation. I have searched every resource I can find and have made use of all the relevant code I found, as you will see below.
Specifically, I want to allow the user to enter a dollar amount in one text field, select what pay frequency (hourly, monthly, etc) it is, select what pay frequency they would like to convert it to, and see the results in the other text field when they tap a button. Another button would clear the fields, so they can convert another amount. More specifically, if they wanted to see what their weekly wage of $310 was semimonthly, they would enter "310" in the first field, select "Weekly" in the first picker component, select "SemiMonthly" in the other component, and tap the Calculate button. The other field would then show $671.67 (310 * 52 / 24 = 671.67).
Just in case it is relevant, the View Controller this takes place on is tied to a Navigation Controller as one of 5 screens attached to one of 6 screens attached to the main View Controller (it takes a couple of taps to get to this screen).
So far, I can enter numbers into the two text fields and I can spin the 2 picker components and make their selections appear in labels, but that's where I'm stuck. I can find no examples of how to implement it.
Here is my ViewController.h code:
#interface PayFrequencyViewController : UIViewController
<UIPickerViewDelegate, UIPickerViewDataSource>
{
UIPickerView *payPicker;
NSArray *fromArray;
NSArray *toArray;
NSArray *fromValues;
NSArray *toValues;
UILabel *resultText;
UITextField *inputText;
}
#property (strong, nonatomic) IBOutlet UIPickerView *payPicker;
#property (strong, nonatomic) NSArray *fromArray;
#property (strong, nonatomic) NSArray *toArray;
#property (strong, nonatomic) NSArray *fromValues;
#property (strong, nonatomic) NSArray *toValues;
#property (strong, nonatomic) IBOutlet UILabel *resultText;
#property (strong, nonatomic) IBOutlet UITextField *inputText;
- (IBAction)Convert:(id)sender;
- (IBAction)Clear:(id)sender;
#end
And here is my ViewController.m code:
#interface PayFrequencyViewController ()
#end
#implementation PayFrequencyViewController
#synthesize payPicker;
#synthesize toArray;
#synthesize fromArray;
#synthesize toValues;
#synthesize fromValues;
#synthesize resultText;
#synthesize inputText;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
self.fromArray = [[NSArray alloc] initWithObjects:
#"Annual", #"Monthly", #"48/Year", #"SemiMonthly", #"BiWeekly", #"Weekly", #"Hourly", nil];
self.fromValues = [[NSArray alloc] initWithObjects:
[NSNumber numberWithFloat:1.0],
[NSNumber numberWithFloat:12.0],
[NSNumber numberWithFloat:48.0],
[NSNumber numberWithFloat:24.0],
[NSNumber numberWithFloat:26.0],
[NSNumber numberWithFloat:52.0],
[NSNumber numberWithFloat:2080.0], nil];
self.toArray = [[NSArray alloc] initWithObjects:
#"Annual", #"Monthly", #"48/Year", #"SemiMonthly", #"BiWeekly", #"Weekly", #"Hourly", nil];
self.toValues = [[NSArray alloc] initWithObjects:
[NSNumber numberWithFloat:1.0],
[NSNumber numberWithFloat:12.0],
[NSNumber numberWithFloat:48.0],
[NSNumber numberWithFloat:24.0],
[NSNumber numberWithFloat:26.0],
[NSNumber numberWithFloat:52.0],
[NSNumber numberWithFloat:2080.0], nil];
[super viewDidLoad];
inputText.keyboardType = UIKeyboardTypeDecimalPad;
// Do any additional setup after loading the view.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.toArray = nil;
self.fromArray = nil;
self.resultText = nil;
self.inputText = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 2;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
if (component == 0) {
return [fromArray count];
}
return [toArray count];
}
- (NSString *)pickerView:(UIPickerView *)pickerView
titleForRow:(NSInteger)row
forComponent:(NSInteger)component
{
if (component == 0) {
return [fromArray objectAtIndex:row];
}
return [toArray objectAtIndex:row];
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row
inComponent:(NSInteger)component {
//- (IBAction)Convert:(id)sender {
// float valuein = [[fromValues text] floatValue];
// float valueout = [[toValues text] floatValue];
// [resultText setText:[NSString stringWithFormat:#"%6.2f", result]];
// [inputText resignFirstResponder];
float valuein = [[fromValues objectAtIndex:row] floatValue];
float valueout = [[toValues objectAtIndex:row] floatValue];
float input = [inputText.text floatValue];
float result = input * valuein / valueout;
NSString *resultString = [[NSString alloc] initWithFormat: #"$ %#", [toArray objectAtIndex:row]];
}
- (IBAction)Clear:(id)sender {
inputText.text = #"";
resultText.text = #"";
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[inputText resignFirstResponder];
}
#end
My apologies for the lengthy post and the improperly formatted code. I hope someone can tell me what code is unnecessary and what is required to complete this task.
I wrote code like:
+ (CGFloat)tableView:(UITableView*)tableView rowHeightForObject:(id)item {
CustomTTTableSubtitleItem* captionedItem = item;
CGFloat maxWidth = tableView.width - kHPadding*2;
CGSize titleSize = [captionedItem.title sizeWithFont:TTSTYLEVAR(myTitleFont) constrainedToSize:CGSizeMake(maxWidth, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];
}
Got this exception:
2011-07-24 03:10:18.762 xinyou[15941:b303] -[TTDefaultStyleSheet
myTitleFont]: unrecognized selector sent to instance 0x5b5e120
2011-07-24 03:10:18.765 xinyou[15941:b303] * Terminating app due to
uncaught exception 'NSInvalidArgumentException', reason:
'-[TTDefaultStyleSheet myTitleFont]: unrecognized selector sent to
instance 0x5b5e120'
* Call stack at first throw: ( 0 CoreFoundation
0x0119a5a9 exceptionPreprocess + 185 1 libobjc.A.dylib
0x012ee313 objc_exception_throw + 44 2 CoreFoundation
0x0119c0bb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187 3
CoreFoundation 0x0110b966 __forwarding + 966
4 CoreFoundation 0x0110b522
_CF_forwarding_prep_0 + 50 5 xinyou
0x000081f9 +[CustomTTTableSubtitleItemCell
tableView:rowHeightForObject:] + 186 6 xinyou
0x000a6c92 -[TTTableViewVarHeightDelegate
tableView:heightForRowAtIndexPath:] + 156 7 UIKit
0x0064a6d5 -[UISectionRowData
In this exception you can see [TTDefaultStyleSheet myTitleFont]: unrecognized selector sent to instance 0x5b5e120 but actually myTitleFont defined in XYDefaultStyleSheet and I've imported XYDefaultStyleSheet.h in my class. XYDefaultStyleSheet.h and XYDefaultStyleSheet.m are like:
XYDefaultStyleSheet.h
#import "Three20/Three20.h"
#interface XYDefaultStyleSheet : TTDefaultStyleSheet
#property(nonatomic,readonly) UIColor* myHeadingColor;
#property(nonatomic,readonly) UIColor* mySubtextColor;
#property(nonatomic,readonly) UIColor* myTitleColor;
#property(nonatomic,readonly) UIFont* myTitleFont;
#property(nonatomic,readonly) UIFont* myHeadingFont;
#property(nonatomic,readonly) UIFont* mySubtextFont;
#end
XYDefaultStyleSheet.m
#import "XYDefaultStyleSheet.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
#implementation XYDefaultStyleSheet
///////////////////////////////////////////////////////////////////////////////////////////////////
// styles
///////////////////////////////////////////////////////////////////////////////////////////////////
// public colors
- (UIColor*)myTitleColor {
return [UIColor blackColor];
}
- (UIColor*)myHeadingColor {
return RGBCOLOR(80, 110, 140);
}
- (UIColor*)mySubtextColor {
return [UIColor grayColor];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// public fonts
- (UIFont*)myTitleFont {
return [UIFont boldSystemFontOfSize:16];
}
- (UIFont*)myHeadingFont {
return [UIFont boldSystemFontOfSize:13];
}
- (UIFont*)mySubtextFont {
return [UIFont systemFontOfSize:12];
}
#end
why always tell [TTDefaultStyleSheet myTitleFont] ... if the problem is really myTitleFont, it should be [XYDefaultStyleSheet myTitleFont], why TTDefaultStyleSheet?
got it! Init my style sheet in AppDelegate.
This is an answer to #Jason Zhao's answer about initialising within the AppDelegate.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
[TTStyleSheet setGlobalStyleSheet:[[[CustomDefaultStyleSheet alloc]
init] autorelease]];
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
}
Original code is from here, which has a lot of useful information about using TTStyleSheet's:
Three20 Stylesheets iPhone Tutorial