unrecognized selector sent to instance for Paul Hegarty's CS193P - ibaction

I'm following Paul Hegarty's CS193P course video (lecture #4 # 1:05:40 mark) and ran into problems. Please help debug this 'unrecognized selector sent to instance' error. The view has three objects - see image (https://docs.google.com/file/d/0B453_F6cDmYzMG1OQW93WVptYUU/edit?usp=sharing)
The code
// AttributeViewController.m
// Attribute
#import "AttributeViewController.h"
#interface AttributeViewController ()
#property (weak, nonatomic) IBOutlet UILabel *label; // collection of words
#property (weak, nonatomic) IBOutlet UIStepper *selectedWordStepper; // stepper
#property (weak, nonatomic) IBOutlet UILabel *selectedWordLabel; // selected word from label
#end
#implementation AttributeViewController
- (NSArray *)wordList
{
NSArray *wordList = [[self.label.attributedText string] componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([wordList count]) {
return wordList;
} else {
return #[#""];
}
}
- (NSString *)selectedWord
{
return [self wordList][(int)self.selectedWordStepper.value];
}
- (IBAction)updateSelectedWord {
self.selectedWordStepper.maximumValue = [[self wordList] count]-1;
self.selectedWordLabel.text = [self selectedWord];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self updateSelectedWord];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
The error
2013-03-03 18:03:28.948 Attribute[74205:c07] -[AttributeViewController updateSelectedWord:]: unrecognized selector sent to instance 0x71b93a0
2013-03-03 18:03:28.952 Attribute[74205:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[AttributeViewController updateSelectedWord:]: unrecognized selector sent to instance 0x71b93a0'
*** First throw call stack:
(0x1c91012 0x10cee7e 0x1d1c4bd 0x1c80bbc 0x1c8094e 0x10e2705 0x162c0 0x16258 0xd7021 0xd757f 0xd7056 0x42b195 0x42ae91 0xd6696 0x45cef 0x45f02 0x23d4a 0x15698 0x1becdf9 0x1c14f3f 0x1c1496f 0x1c37734 0x1c36f44 0x1c36e1b 0x1beb7e3 0x1beb668 0x12ffc 0x25cd 0x24f5)
libc++abi.dylib: terminate called throwing an exception
(lldb) gdb

I have really not seen direct calls to IBAction methods before. IBAction methods are connected to actions in your View (buttons, etc.) and are triggered when these buttons, etc.. are clicked.
If updateSelectedWord is an internal method, just replace IBAction with void:
(void)updateSelectedWord
Hope this helps.

Related

Black sceen trying to put a .Xib after Splash

I'm programming a App for iOS 8. I've a problem because i don't want use storyboard, I want to put a .xib file at the first time. Muy problem is that always, after splash be a black screen.
The Class who I want to put after Splash is LoginViewController
At general options, the "Main interface" is white (empty) (if put the name of the class, i've NSException (NSUknownException)).
In the .xib file i'have the files owner connected, and at the right side of the screen i've the name of the class at "Custom Class" (LoginViewController).
My appDelegate.h is: (I try with " #property (strong, nonatomic) LoginViewController *viewController;" too)
#import <UIKit/UIKit.h>
#import "LoginViewController.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) UIViewController *viewController;
#end
My appDelegate.m is: (i try a lot of variants)
#import "AppDelegate.h"
#import "LoginViewController.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.viewController = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
navController.navigationBarHidden = YES;
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
#end
The LoginViewController.h:
#import <UIKit/UIKit.h>
#interface LoginViewController : UIViewController
{
IBOutlet UILabel *labelPrueba;
IBOutlet UIButton *botonPrueba;
IBOutlet UIButton *boton2prueba;
IBOutlet UILabel *label2Prueba;
IBOutlet UILabel *dsfd;
IBOutlet UIButton *dfdf;
}
#end
The LoginViewController.m:
#import "LoginViewController.h"
#interface LoginViewController ()
#end
#implementation LoginViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
label2Prueba.text = #"laaaaaaaaaaaaa";
NSLog(#"Entra en viewDidLoad");
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
Someone can help me please. I'm going crazyyyyy.
Thanks a lot.
The solution was put this windows like init frame:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// That was the solution
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// That was the solution
self.viewController = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
navController.navigationBarHidden = YES;
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
Thanks

iOS 7: Cannot connect to IBOutlets, probably because I'm using UITableViewController

I cannot create any IBOutlets. I'm using a tableviewcontroller instead of a viewcontroller.
When I click on TableViewController, the class is UITableViewController and I can't change that.
Here's my code for ViewController.h:
// ViewController.h
// Tips4
//
// Created by Meghan on 1/20/14.
// Copyright (c) 2014 Meghan. All rights reserved.
//
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
#property (strong, nonatomic) IBOutlet UILabel *sliderDisplay;
#property (strong, nonatomic) IBOutlet UITextField *tempText;
#property (strong, nonatomic) IBOutlet UILabel *billTotal;
#property (nonatomic, strong) IBOutlet UISlider *slider;
- (IBAction)sliderValueChanged:(id)sender;
#property (nonatomic) float answer;
#property (nonatomic) float answerTwo;
#end
Here's my ViewController.m:
// ViewController.m
// Tips4
//
// Created by Meghan on 1/20/14.
// Copyright (c) 2014 Meghan. All rights reserved.
//
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *tipsTableIdentifier = #"TipsTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tipsTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tipsTableIdentifier];
}
return cell;
}
- (IBAction)sliderValueChanged:(id)sender
{
float theText = [_tempText.text floatValue];
_answer = (_slider.value * theText) / 100;
_answerTwo = _answer + theText;
_sliderDisplay.text = [NSString stringWithFormat:#"%1.2f", _answer];
_billTotal.text = [NSString stringWithFormat:#"%1.2f", _answerTwo];
}
- (void)viewDidLoad
{
[super viewDidLoad];
_tempText.keyboardType = UIKeyboardTypeDecimalPad;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
If you’re using a TableViewController, your class must inherit from a UITableViewController. Thats when it will show up in the Identity Inspector, which is where you change your class from UIViewController to your class. After that you should be able to connect IBOutlets.
To do that, just replace your current line
#interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
with
#interface ViewController : UITableViewController
Now, you will need to add the init method that calls the super, to the .m file.
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
I hope this will do it.
Also, sometimes, changes in the code don’t show up in the storyboard Identity Inspector. In that case, you can just quit the Xcode window and open the project again. That does it.
Alternatively, if you use a ViewController, your class can inherit from a UIViewController. Then you add a TableView to your View and add a UITableView instance to the controller file (create an IBOutlet). In this case, your .h file needs to add the UITableViewDelegate and UITableViewDataSource to populate the table and your .m file needs to implement the required methods (Xcode will warn you about this).

Crash in objc_retain in method performed with performSelector

I have this strange crash relating to ARC auto-inserting objc_retains in my code.
I have the following two classes:
#interface MenuItem : NSObject
#property (weak, nonatomic) id target;
#property (unsafe_unretained, nonatomic) SEL action;
#property (strong, nonatomic) id object;
- (instancetype)initWIthTarget:(id)target action:(SEL)action withObject:(id)object;
- (void)performAction;
#end
#implementation MenuItem
- (void)performAction
{
if (self.target && self.action)
{
if (self.object)
{
[self.target performSelector:self.action withObject:self.object];
}
else
{
[self.target performSelector:self.action];
}
}
}
#end
#interface Widget : NSObject
- (void)someMethod:(id)sender;
#end
At some point I instantiate a MenuItem as such:
MenuItem *item = [MenuItem alloc] initWithTarget:widget action:#selector(someMethod:) object:nil];
Then elsewhere I invoke performAction on the menu item:
[item performAction];
In the implementation of someMethod I get a crash:
#implementation Widget
- (void)someMethod:(id)sender
{
// EXEC_BAD_ACCESS crash in objc_retain
}
#end
Why is this happening?
The reason for the crash was because I was using the wrong performSelector.
NSObject defines multiple versions of performSelector. The one I was invoking was:
- (id)performSelector:(SEL)aSelector;
However the method I was invoking took an id parameter. Eg:
- (void)someMethod:(id)sender;
Now ARC being the nice safe memory management system that it is tries to ensure that parameters are properly retained during the execution of a method. So even though my someMethod: was empty ARC was producing code that looked like this:
- (void)someMethod:(id)sender
{
objc_retain(sender);
objc_release(sender);
}
The problem with this however was that I was invoking performSelector: and not supplying a value for the sender parameter. So sender was pointing at random junk on the stack. Therefore when objc_retain() was invoked the app crashed.
If I change:
MenuItem *item = [[MenuItem alloc] initWithTarget:widget
action:#selector(someMethod:)
object:nil];
to
MenuItem *item = [[MenuItem alloc] initWithTarget:widget
action:#selector(someMethod)
object:nil];
and
- (void)someMethod:(id)sender;
to
- (void)someMethod;
Then the crash goes away.
Similarly I can also change
[self.target performSelector:self.action];
to
[self.target performSelector:self.action withObject:nil];
if I want to follow the 'standard' form of target-action methods that take a single parameter. The benefit of the second form of performSelector is that if I'm invoking a method that doesn't take a parameter it will still work fine.

ARC and Popovers and delegates

i am tearing my hair out, I have migrated my old project to arc and I'm getting this error popping up : * Terminating app due to uncaught exception 'NSGenericException', reason: '-[UIPopoverController dealloc] reached while popover is still visible.'
I have read through some threads and I'm confused, some say when using delegates use a weak reference but on the other hand when using popovers use a strong property reference, can someone give me an example of how best to use ARC and delegates with a popover that has a button inside that changes the background colour for example?
From what I've read I keep hearing use an instance variable in my view controller, here it is in my main view controller:
#property (nonatomic, strong) UIPopoverController *currentPopover;
and the is the method implementation in the main view controller file:
- (IBAction)ShowPopTextColor:(id)sender {
if (currentPopover == nil) {
TimerTextColor *timerTextColor = [[TimerTextColor alloc]init];
timerTextColor.delegate =self;
UIPopoverController *pop = [[UIPopoverController alloc]initWithContentViewController:timerTextColor];
[pop setDelegate:self];
[pop setPopoverContentSize:CGSizeMake(320, 240)];
[pop presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
//[pop release];
} else {
[currentPopover dismissPopoverAnimated:YES];
currentPopover = nil;
}
}
here is my popup content header:
#protocol colorChooserDelegate
-(void) colorSelected:(UIColor*)thecolor;
#end
#interface TimerTextColor : UIViewController{
id<colorChooserDelegate> delegate;
IBOutlet UIButton *colorView;
}
- (IBAction)buttonTapped:(id) sender;
#property (nonatomic,strong) id<colorChooserDelegate>delegate;
#property (nonatomic,strong) UIButton *colorView;
#end
What am i doing wrong?
Assign currentPopover.
Call
currentPopover = pop
after popover creation
you shouldn't create a local variable to store the popover controller.
Change this
UIPopoverController *pop = [[UIPopoverController alloc] initWithContentViewController:timerTextColor];
to
self.currentPopover = [[UIPopoverController alloc] initWithContentViewController:timerTextColor];

Semantic issue: Property 'text' not found on object of type 'UISlider'

When I try to run it though, I get an error which says "Semantic issue: Property 'text' not found on object of type 'UISlider'"
What's wrong here?
Here is the code from the header file:
#import <UIKit/UIKit.h>
#interface BIDViewController : UIViewController
#property (strong, nonatomic) IBOutlet UITextField *nameField;
#property (strong, nonatomic) IBOutlet UITextField *numberField;
#property (strong, nonatomic) IBOutlet UISlider *sliderLabel;
- (IBAction)textFieldDoneEditing:(id)sender;
- (IBAction)backgroundTap:(id)sender;
- (IBAction)sliderChanged:(id)sender;
#end
Implementation file:
#import "BIDViewController.h"
#implementation BIDViewController
#synthesize sliderLabel;
#synthesize nameField;
#synthesize numberField;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setNameField:nil];
[self setNumberField:nil];
[self setSliderLabel:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (IBAction)textFieldDoneEditing:(id)sender
{
[sender resignFirstResponder];
}
- (IBAction)backgroundTap:(id)sender
{
[nameField resignFirstResponder];
[numberField resignFirstResponder];
}
- (IBAction)sliderChanged:(id)sender
{
UISlider *slider = (UISlider *)sender;
int progressAsInt = (int)roundf(slider.value);
sliderLabel.text = [NSString stringWithFormat:#"%d",progressAsInt];
}
#end
I suspect your sliderLabel has been declared as an object of class UISlider, when it should be UILabel. Can you verify the sliderLabel's #property declaration in your header file?
I have the same message on NSManagedObject. My solution is set "Always Search User Paths" in "Search Paths" of target's Build Settings to "No"
Hope that could help too.

Resources