I have a weird problem. I get this error:
-[FourSquareCheckInViewController tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x7aecc0
2012-09-14 19:18:39.039 [5869:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[FourSquareCheckInViewController tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x7aecc0'
*** First throw call stack:
(0x3545e88f 0x37805259 0x35461a9b 0x35460a83 0x353bb650 0x32ee3693 0x32ee49ed 0x32ee493f 0x32ee451b 0x32ef17df 0x32ef16af 0x32e95f37 0x353bd1fb 0x3228daa5 0x3228d6bd 0x32291843 0x3229157f 0x322894b9 0x35432b1b 0x35430d57 0x354310b1 0x353b44a5 0x353b436d 0x37050439 0x32ec0cd5 0xb7ebb 0xb7e60)
terminate called throwing an exception(lldb)
Ok so I have made sure that the ViewController is set as the dataSource and the Delegate. I have added the UITableViewDelegate and UITableViewDataSource to the <> thingies.
I have set tableView.delegate = self and tableView.dataSource = self in my viewDidLoad method.
Here is my implementation of the viewDidLoad and viewDidAppear methods:
- (void)viewWillAppear:(BOOL)animated{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer; // 1km
[locationManager startUpdatingLocation];
locationLat = [locationManager location].coordinate.latitude;
locationLng = [locationManager location].coordinate.longitude;
[locationManager stopUpdatingLocation];
// 1
CLLocationCoordinate2D zoomLocation;
zoomLocation.latitude = locationLat;
zoomLocation.longitude= locationLng;
// 2
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, 0.5*METERS_PER_MILE, 0.5*METERS_PER_MILE);
// 3
MKCoordinateRegion adjustedRegion = [_mapView regionThatFits:viewRegion];
// 4
[_mapView setRegion:adjustedRegion animated:YES];
}
- (void)viewDidLoad
{
[super viewDidLoad];
_tableView.delegate = self;
_tableView.dataSource = self;
// Do any additional setup after loading the view.
// 1
MKCoordinateRegion mapRegion = [_mapView region];
CLLocationCoordinate2D centerLocation = mapRegion.center;
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer; // 1km
[locationManager startUpdatingLocation];
locationLat = [locationManager location].coordinate.latitude;
locationLng = [locationManager location].coordinate.longitude;
[locationManager stopUpdatingLocation];
}
Here is my method body for numberOfRowsInSection:
- (NSInteger)numberOfRowsInSection:(NSInteger)section{
return 5;
}
Here is my header file for the view controller:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#define METERS_PER_MILE 1609.344
#interface FourSquareCheckInViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, CLLocationManagerDelegate, MKMapViewDelegate>{
}
#property (weak, nonatomic) IBOutlet MKMapView *_mapView;
- (NSInteger)numberOfRowsInSection:(NSInteger)section;
#property (weak, nonatomic) IBOutlet UITableView *_tableView;
#end
Here is a screenshot showing how my tableView is hooked up:
Read what the error message is telling you!
You have implemented numberOfRowsInSection:. So what? That's the wrong method. It is irrelevant. It will never be called.
The method you need to implement is called tableView:numberOfRowsInSection:. That's completely different.
If you click on the view it should show the above connections in INSPECTOR.
If you haven't got the ViewController hooked up as well you will get the error:
'NSInvalidArgumentException', reason: '-[UIView
tableView:numberOfRowsInSection:]: unrecognized selector sent to
instance
How I stopped the error is you
press on the ViewController to select it
look for Referencing Outlets in the Connection inspector to the right
drag from the circle of the New Referencing Outlet to the view
when you release the mouse, a tiny popup will show - select datasource
repeat step 3, and this time select delegate
When done, it should look like the image below!
This stopped the above error for me.
I hope this helps someone.
Check if you have UITableViewDelegate, UITableViewDataSource defined in your class file:
class ClassName: UIViewController, UITableViewDelegate, UITableViewDataSource
{
}
You'll also see this error if, although you've hooked everything up properly in the view controller, you have forgotten to assign your custom view controller class in your storyboard:
I think it's important that I show this answer. It seems silly, probably it is, but I lost a good while until I saw the error.
It happened to me creating a new view and copying part of the code.
I created the new view:
class THIRD: UIViewController {
[...]
}
And I started copying the code:
func numberOfSections(in tableView: UITableView) -> Int {
...
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
...
}
Etc.
And then, the message error:
[Fonts.THIRD tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x10204b200
I reviewed the Storyboard again and again. And I checked the code again and again. And I lost a good time.
Finally I realized!!!
I forgot to declare:
class THIRD: UIViewController, UITableViewDelegate, UITableViewDataSource {
Perhaps the error may be, do not declare the UITableViewDelegate and UITableViewDataSource protocols
Keep it in mind, do not forget it!
It is very simple, I had got a similar problem. I am implementing my TableView without Storyboard in my ViewController which has subclassed UIViewController with two protocols: <UITableViewDataSource, UITableViewDelegate>
But if you look to the UITableViewDataSource there are two methods witch are #required and these you need to implement in your code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
All other methods in UITableViewDelegate are #optional hence you don't need to implement them.
You'll also see this error if, although you've hooked everything up properly in the view controller, you have forgotten to extend UITableViewDelegate,UITableViewDataSource.
- (NSInteger)numberOfRowsInSection:(NSInteger)section;
You are not implementing UITableViewDataSource method. Remove the declaration and it won't crash anymore. Or alternatively provide a method body for it.
Another cause of this error I found (even when conforming to UITableViewDataSource!) was when setting a tableView.tableHeaderView before setting the tableView.dataSource.
// Header config
self.tableView.tableHeaderView = header; // CRASH!! Triggers table view update and thus calls unknown selector.
self.tableView.dataSource = self;
Really simple fix is to set the data source first before setting the tableHeaderView (or tableFooterView):
self.tableView.dataSource = self;
// Header config
self.tableView.tableHeaderView = header; // Runtime can now find selector even though it is already defined.
If you have set up everything correctly and you still get this error. You will need to assign a controller to your custom class
Related
Using Xcode 7
Swift 2
I have been researching inheriting Objective C base class in a Swift UIViewController. I have added my Bridging header file correctly and it is correctly part of my project build settings:
In my SCS-Bridging-Header.h file I have the following code:
#import "UIViewControllerPlus.h"
And then I am trying to inherit the Objective C class UIViewControllerPlus in a Swift class:
import UIKit
class TestBasicTabBarSegueViewController: UIViewControllerPlus {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
This builds and runs, but when I Segue to the Swift TestBasicTabBarSegueViewController a property of the Objective C base class or super class is not accessible:
#ifndef UIViewControllerPlus_h
#define UIViewControllerPlus_h
#import <UIKit/UIKit.h>
#import "MMTabBarController.h"
#interface UIViewControllerPlus : UIViewController
#property MMTabBarController* mt;
#end
#endif /* UIViewControllerPlus_h */
It is the property mt which is of type MMTabBarController.
You can see in the following custom Segue that destinationController.mt is not accessible and causes the app to crash when attempting to set:
#import "MMNavigationSegue.h"
#import "MMTabBarController.h"
#import "UIViewControllerPlus.h"
#implementation MMNavigationSegue
- (void) perform
{
MMTabBarController *tabBarController = (MMTabBarController *) self.sourceViewController;
UIViewControllerPlus *destinationController = (UIViewControllerPlus *) self.destinationViewController;
destinationController.mt = tabBarController; //HERE APP CRASHES
for (UIView *view in tabBarController.placeholderView.subviews)
{
[view removeFromSuperview];
}
// Add view to placeholder view
tabBarController.currentViewController = destinationController;
[tabBarController.placeholderView addSubview: destinationController.view];
// Set autoresizing
[tabBarController.placeholderView setTranslatesAutoresizingMaskIntoConstraints:NO];
UIView *childview = destinationController.view;
[childview setTranslatesAutoresizingMaskIntoConstraints: NO];
// fill horizontal
[tabBarController.placeholderView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat: #"H:|[childview]|" options: 0 metrics: nil views: NSDictionaryOfVariableBindings(childview)]];
// fill vertical
[tabBarController.placeholderView addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat: #"V:|-0-[childview]-0-|" options: 0 metrics: nil views: NSDictionaryOfVariableBindings(childview)]];
[tabBarController.placeholderView layoutIfNeeded];
// notify did move
[destinationController didMoveToParentViewController: tabBarController];
}
#end
Note, the above code works if the destination UIViewController Segued to is an Objective C code UIViewController implementation that inherits from the Objective C class UIViewControllerPlus.
But on the next line the app crashes:
Error:
2016-06-14 21:16:39.795 SCS[49747:17004544] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIViewController setMt:]: unrecognized selector sent to instance 0x7d967080'
The destinationController is not casting to type UIViewControllerPlus it is instead casting to type UIViewController, even though it defined as a UIViewControllerPlus. This only happens if it is a Swift file/class inheriting the Objective C UIViewControllerPlus class but the cast works if it is Objective C subclass inheriting Objective C base class UIViewControllerPlus:
**Is inheriting an Objective C base class in Swift possible? I have read various conflicting statements online about this?
Is there something I might be missing in my Objective C project references/configuration?**
-[UIViewController setMt:]: means the view controller being instantiated is a regular view controller - not one of your subclassed "plus" type.
You probably forgot to assign the correct class to the view controller in the storyboard.
I have a frustrating problem. I can't wrap my head around the "delegate thing".
My problem is that i can't set a Viewcontroller as the delegate.
-(IBAction)adminRegisterVC:(id)sender{
AdminSignUpViewController *adminSignUpVC = [[AdminSignUpViewController alloc] init];
[adminSignUpVC setDelegate:self]; // Gets an error message. See what error below.
[self.navigationController pushViewController:adminSignUpVC animated:YES];
}
it doesnt work with: adminSignUpVC.delegate = self; either.
error:
No visible #interface for 'AdminSignUpViewcontroller' declares the selector 'setDelegate:'
Is there something i should add to this:
#interface AdminSignUpViewController : UIViewController
I really need some help here!
I created a singleton in ios7 like this:
SharedData.h
#interface SharedData : NSObject
{
}
+ (id)sharedInstance;
#property (strong, nonatomic) NSMutableArray *list;
#end
SharedData.m
#import "SharedData.h"
#implementation SharedData
#synthesize list;
// Get the shared instance thread safe
+ (SharedData *)sharedInstance {
static dispatch_once_t once = 0;
static SharedData *sharedInstance = nil;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (id)init {
self = [super init];
if (self) {
//initialize
list = [[NSMutableArray alloc] init];
}
return self;
}
#end
I always use this code to access this class:
SharedData *sharedData = [SharedData sharedInstance];
The problem is now when I switch the view in my viewDidLoad method the list is empty but in my viewDidAppear method everything is fine. Any ideas?
EDIT:
This is the code how I change the views:
SharedData *sharedData = [SharedData sharedInstance];
//clear feed and add new feed
[sharedData.list removeAllObjects];
[sharedData.list addObjectsFromArray:newList];
//show new gui
[self.navigationController performSegueWithIdentifier:#"goToMain" sender:self];
NOTE: I push from a normal ViewController to a TabBarController -> NavigationController -> TableViewController to display the list.
I guess you have the confusion between these two viewcontroller methods:
-(void)viewDidLoad{
//
}
&
-(void) viewDidAppear{
//
}
viewDidAppear is the method which is called each time your view changes but viewDidLoad is the method which is not necessarily called each time your view changes.
ViewDidLoad method is called when view loads for the first time, after that it doesn't get called until the views are removed/released.
P.S: I suggest you to put the breakpoint in your viewDidLoad and viewDidAppear method and feel it. Your answer lies there.
Hope this helps you alot.
Good Luck.
The problem was i created a segue which went from the button to the next view. Because of this the viewDidLoad gets earlier called than the list assigned. I just changed the segue to go from view to view.
How are you changing from one viewController to the other? Wich classes are the parents of your destination ViewController?,
If you are modifying properties of the view in the prepareForSegue method... you are forcing the view to load.
For example, you are setting the list of your singleton in prepareForSegue, but before setting the list you are modifying a property of your destination viewController. (doing something like destVC.view = XXX or destVC.viewControllers = XX if you are subclassing a UITabBarViewController...) Then you are triggering the viewDidLoad method , and it's executing before you have set the list to the correct value.
Or maybe you are seguing in two different places to the destinationViewController. And when the viewDidLoad happens, you still have not updated the list on the singleton.
Here is the transcription of the chat with the poster of the question: https://chat.stackoverflow.com/transcript/55218
Following my previous post about UIViewControllers designated initializer initWithCoder I have another question about the argument aDecoder passed into the protocol method.
Here is the code in question:
#implementation WhereamiViewController
- (id)initWithCoder:(NSCoder *)aDecoder //we're overiding the superclasses (UIViewController) inititalizer
{
self = [super initWithCoder:aDecoder];
if (self){
//create location manager object
locationManager = [[CLLocationManager alloc] init];
//there will be a warning from this line of code
[locationManager setDelegate:self];
//and we want it to be as accurate as possible
//regardless of how much time/power it takes
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
//tell our manager to start looking for its location immediately
[locationManager startUpdatingLocation];
}
return self;
}
I was curious about aDecoder so renamed it to see if my code would still work and it did. What I want to know is what exactly is being passed into initWithCoder as an argument? It seems like nothing is in my code. Is the argument just part of the method and has to be shown even if nothings being passed into it? Other times I have created designated initializers I've done it like this:
self = [super init]
init is NSObjects designated initializer right?
This is the only part of the code I don't understand. I see I'm calling my superclasses initializer and then implementing it with additional custom code / making it selfs (whereamiviewcontroller) value.
I did set a marker and look in the logs to see if anything would catch my eye but had no luck with that.
Thanks in advance
Regards
You can see the -initWithCoder: method in action when you try to initialise your view controller instance from nib or storyboard. In this case Cocoa Touch will decode the controller elements from the xml using UINibDecoder instance by -initWithCoder: initialiser.
I think setting the delegate for the KalViewController correctly - copying both the Holiday & NativeCal demo - but I must not be because I'm getting the following error when I click upon a date cell:
-[UINavigationButton didSelectDate:]: unrecognized selector sent to instance
When I set breakpoints on All Exceptions I see that it's raising an exception in KalGridView.m in this function:
- (void)setSelectedTile:(KalTileView *)tile
{
if (selectedTile != tile) {
selectedTile.selected = NO;
selectedTile = [tile retain];
tile.selected = YES;
[delegate didSelectDate:tile.date]; // exception raised here
}
}
And here's the code where I set the delegate (pretty much copied from the demo code):
- (void) viewDidLoad
{
KalViewController *calendar = [[KalViewController alloc] init];
calendar.delegate = self;
[[self.view viewWithTag:1] addSubview:calendar.view];
....}
The error makes sense because I'm setting the delegate to my own ViewController which doesn't implement didSelectDate. On the other hand, neither does the Holiday and NativeCal classes which are set at the KalViewController's delegate, both of which are of type
NSObject <UIApplicationDelegate, UITableViewDelegate>
Thanks a pile.. I'm more than a touch stuck.
This is one of those rare instances where the delegate should probably be retained because it's being released and replaced. Override -setDelegate: and retain your delegate.