I tried some stuff in xcode, and i'm using this code for my MapView.
No known class method for selector 'setRegion:animated:'
I have made three View Controller with with 3 .h and .m files.
What's my mistake?
.m
#import "myPlacesAllTime.h"
#import <MapKit/MapKit.h>
#interface myPlacesAllTime ()
#end
#implementation myPlacesAllTime
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
MKCoordinateRegion startRegion = { {0.0,0.0}, {0.0,0.0} };
startRegion.center.latitude = 35.88905;
startRegion.center .longitude = -17.605591;
startRegion.span.latitudeDelta = 0.1;
startRegion.span.longitudeDelta = 0.1;
[myPlacesAllTime setRegion:startRegion animated: NO];
}
.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface myPlacesAllTime : UIViewController <MKMapViewDelegate>{
__weak IBOutlet MKMapView *myPlacesAllTime;
}
#end
You have chosen the same name myPlacesAllTime for the class and for an
instance variable of that class.
To solve the problem, rename the class, e.g. to MyPlacesController or similar.
Note that the convention is to let
class names start with a capital letter.
I think you problem may be a naming issue. The class you've created is named the same as the instance of MKMapView you have. I would follow convention and name your class with caps, but to solve the current problem try using
[self.myPlacesAllTime setRegion:startRegion animated:NO];
to see if it has a different outcome. You'll have to make your instance a property of the class, as stated in the comments below, which I missed in my original answer.
If you are intending to use setRegion:animated: at class level then make sure you have defined a method like this:
+ (void)setRegion:(OBJ_Type)iType animated:(OBJ_Type)iAnimated {
And f you are intending to use setRegion:animated: at object level then make sure you have defined a method like this:
- (void)setRegion:(OBJ_Type)iType animated:(OBJ_Type)iAnimated {
and in this case you need to call this method like this:
[self setRegion:PARAM animated:PARAM];
Related
I created a new UIViewController class including a xib file in xcode 6.
I set up everything like so
.h file next ViewController
#interface NextViewController : UIViewController
#property (nonatomic,assign) int gameID;
#end
.m file next ViewController
#synthesize gameID;
.m file previous View Controller
NextViewController *nextViewController = [[NextViewController alloc] initWithNibName:#"NextViewController" bundle:nil];
nextViewController.gameID = -1;
[self.navigationController pushViewController:nextViewController animated:YES];
when I ran it through the debugger the gameID is set in the .h file but when I want to access the value in the viewDidLoad method I get 0 for gameID instead of -1
Your code seems perfectly fine & it should work as expect a.k.a should rint "-1" in -(void) viewDidLoad.
Another approach I can think of is to try with overriding -init method like following:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil withGameId:(int)gameIdParam {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.gameID = gameIdParam;
}
return self;
}
Declare this method in .h file & then use this method to create new instance of your NextViewControllerwith passing gameID as a parameter.
Please note that, your code is itself correct. I tried it on Mac & it's working fine.
I think the viewDidLoad is getting hit before you set the GameID. Try setting a breakpoint on viewDidLoad and on nextViewController.gameID = -1; to see which one gets hit first. You can override the setter for gameID to perform logic based off of it if that is the case.
I have a procedure that I'll need in a lot (if not all) of my view controllers. I want to know how I can put it in one place (for code cleanliness and maintenance) and utilize it elsewhere.
There are more ways on how to approach this - depending on what exactly you would like to achieve.
If this methods are tied with UIViewController's life and data you would probably want to subclass UIViewController or make an UIViewController category.
A: Subclassing (you want to add some custom properties, variables, methods or you want to override a method):
MySubclassedViewController.h
#import <UIKit/UIKit.h>
#interface MySubclassedViewController : UIViewController
#property (copy) NSString *myVerySpecialString;
-(void) myVerySpecialMethod;
#end
MySubclassedViewController.m
#import "MySubclassedViewController.h"
#implementation MySubclassedViewController
-(void) initialization
{
self.myVerySpecialString = #"initialized";
}
- (id)initWithCoder:(NSCoder*)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self initialization];
}
return self;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self initialization];
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
[self initialization];
}
return self;
}
-(void) viewDidLoad
{
[super viewDidLoad];
[self myVerySpecialMethod];
}
-(void) myVerySpecialMethod
{
if ([self.myVerySpecialString isEqualToString: #"initialized"])
{
self.backgroundColor = [UIColor yellowColor];
}
}
#end
B: Category (you just want to add some extra method to a class):
UIViewController+SpecialCatrgory.h
#import <UIKit/UIKit.h>
#interface UIViewController (SpecialCategory)
-(void) myVerySpecialMethod;
#end
UIViewController+SpecialCatrgory.m
#import "UIViewController+SpecialCatrgory.h"
#implementation UIViewController (SpecialCategory)
-(void) myVerySpecialMethod
{
self.backgroundColor = [UIColor yellowColor];
}
#end
C: Dedicated helper class
On the other hand if you find yourself using some independent method on more than one place you might
want to consider writing up a helper class and use it as a singleton.
MyHelperClass.h
#interface MyHelperClass : NSObject
+ (instancetype)sharedHelper;
-(NSString *) myVerySpecialMethod;
#end
MyHelperClass.m
#import "MyHelperClass.h"
#implementation MyHelperClass
+ (instancetype)sharedHelper
{
static MyHelperClass *_sharedHelper = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedHelper = [[MAConnectionClient alloc] init];
});
return _sharedHelper;
}
-(NSString *) myVerySpecialMethod
{
return #"a result from your very special method";
}
#end
You use it simply by importing MyHelperClass.h (or putting it in -Prefix.pch), without explicitly creating an instance. For example:
NSString *someString = [[MyHelperClass sharedHelper] myVerySpecialMethod];
There are many ways to achieve this.
Create a base viewcontroller and add your procedure. Subclass this in all your view controller.
Create a common utility class and add your procedure and make it as a class method.
Add your procedure in .pch file.
We have many ways to do it but in general create one global class, import it in YourProjectName-Prefix.pch file.
We can also go for another way i.e create any class method and you can call it anywhere through it's Class Name.
One example, you might have seen many times in your code-
:
In appDelegate.h file, if we make this method and implement it in appDelegate.m file then
+ (NSString *)applicationDocumentDir
{
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
then we can access it from anywhere in the code like :
NSString *strTemp = [AppDelegate applicationDocumentDir];
To know more better way have a look here.
Use of a singleton for creating a basic style helper class
If you're not sure that the method will be used in all Controllers, I'd recommend creating a category for the functionality you're adding. You can find a good intro to categories here.
If you're sure you'll need it in all UIViewControllers, creating a base Controller and subclassing should be the better approach.
All other methods of implementing (Placing a class method in a utility / Adding to *-Prefix.pch) will work, but might not be ideal solutions (assuming the functionality your're adding is only applicable to UIViewController).
Am trying to write a simple custom delegate for displaying multiple selection list (after referring various online tutorials, stackoverflow, Apple doc), but in the class that I want to use the delegate, the line where I set the delegate runs into an infinite loop when I run it.
I have shared the source code here
https://bitbucket.org/ikosmik/uilistviewcontroller/src/ddfcd140b52e6e59d84e58d34d601f8f850145a1/UIList?at=master
UIListViewController (where am declaring the protocols)
https://bitbucket.org/ikosmik/uilistviewcontroller/src/ddfcd140b52e6e59d84e58d34d601f8f850145a1/UIList/UIListViewController.h?at=master
And am trying to use the delegate in a UIViewController called View_Exporter
#import <UIKit/UIKit.h>
#import "UIListViewController.h"
#interface View_Exporter : UIViewController <UIListViewDelegate, UIListViewDataSource>
#property (nonatomic, strong) IBOutlet UIView *viewForList;
#property (nonatomic, strong) UIListViewController *listViewController;
#end
View_Exporter.m
#import "View_Exporter.h"
#implementation View_Exporter
#synthesize arraySelectedList;
#synthesize viewForList;
#synthesize listViewController;
#pragma mark - UIListViewController Methods
-(NSArray *) itemsForList {
NSLog(#"View_Exporter itemsForList");
NSArray *array = [NSArray arrayWithObjects:#"Server", #"Memory", nil];
return array;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.listViewController = [[UIListViewController alloc] initWithNibName:#"UIListViewController" bundle:nil];
self.listViewController.listViewDelegate = self;
//[self.viewForList addSubview:self.listViewController.view];
self.listViewController.listViewDataSource = self;
}
#end
But this line in viewDidLoad seems to loop infinitely when I run the code :
self.listViewController.listViewDelegate = self;
Why is this looping infinitely? Am breaking my head since yesterday on this. not sure where am going wrong. can someone please help?
You've written a custom setter for listViewDelegate, at the end of this method you do this:
self.listViewDelegate = delegate;
This just calls the setter method again. Accessing a property via self. is just a way of calling[self setXX:xxx]. In your accessor method you need to set the instance variable directly, in the normal case this would be just
_delegate = delegate;
(The _delegate instance variable is created for you automatically). You can safely remove all of your synthesize statements, they aren't needed any more.
viewcontroller.m has the following code
- (void)viewDidLoad
{
[super viewDidLoad];
self.array=[[NSArray alloc]initWithObjects:#"hi",#"hello", nil];
NSLog(#"%#",self.array);
view *view1=[[view alloc]init];
[view1 addSubview:self.view];
view1.viewController=self;
}
and there is another UIView class where I am trying to access the array :
the .h file :
#import <UIKit/UIKit.h>
#import "ViewController.h"
#class ViewController;
#interface view : UIView{
ViewController *viewController;
}
#property (nonatomic,retain)ViewController *viewController;
#end
and the .m file :
#import "view.h"
#import "ViewController.h"
#implementation view
#synthesize viewController;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NSLog(#"%#",[viewController array]);
}
return self;
}
I checked in other posts of stackoverflow, and the passing of values was mentioned only between viewcontrollers; or the array was declared in the appdelegate and used in the classes(which I want to avoid).
The NSLog in the last code segment above gives null; so can you please help out in accessing the values of this array.
Thanks in advance..!!
You can achieve using this code in your ViewController
#import "view.h"
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *ary = [NSArray arrayWithObjects:#"7",#"5",#"3",#"2", nil];
view *v=[[view alloc] init];
[v initView:ary];
}
And in your view.h file :
#import <UIKit/UIKit.h>
#interface view : UIView
-(void)initView:(NSArray *)ary;
#end
And in your .m file :
#import "view.h"
#import "ViewController.h"
#implementation view
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
}
return self;
}
-(void)initView:(NSArray *)ary
{
NSLog(#"%#",ary);
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
Log value will display this :
2013-02-20 20:11:52.731 SampleProject[9414:f803] (
7,
5,
3,
2
)
This line
view *view1=[[view alloc]init];
calls the desired initializer initWithFrame: before you set view1.viewController, so what's happening is that
NSLog(#"%#",[viewController array]);
actually calls
NSLog(#"%#",[null array]);
or (note that is pseudocode)
NSLog(#"%#",null);
What you'll want to do is to use view1.viewController after it is assigned. The best practice would be to make a custom constructor taking UIViewController* as a parameter and use it.
First thing you are calling the init method on the view and checking for viewController in the initWithFrame method which is never called. (But maybe you are calling the initWithFrame: from inside your init method with a default frame. :) ). Second, you are setting the viewcontroller property after you have called the init method, so your viewcontroller is still uninitialized in your initWithFrame method.
Third, instead of passing the whole of viewcontroller to your view to access the array (which kind of goes against MVC pattern), you could probably use just create an instance variable in your UIView subclass and pass just the array.
Then you could follow the answer given by Dilip, preferably using the setter method for setting the array. IMO.
I've run into some trouble with loading a sub-classed UIViewController from a nib. My viewDidLoad function is never called.
The super-class has no nib, but the sub-classes each have their own. i.e.
#interface SuperClass : UIViewController {
}
#end
#interface SubClass : SuperClass{
}
#end
#implementation SubClass
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad{
// Never called
}
The view is loaded from a nib as follows:
SubClass *scvc = [[SubClass alloc] initWithNibName:#"SubClass" bundle:nil];
[self.navigationController pushViewController:scvc animated:YES];
[scvc release];
There is a nib file with this name and it has it's file owner's class set properly.
viewDidLoad is not called in the child or super. Any ideas?
You say you are creating views in code (using loadView) in the super class, but trying to use a nib in the sub class?
According to the UIViewController docs (emphasis mine)
If you specify views using a nib file, you must not override loadView but should instead create a nib file in Interface Builder...
It looks like you may have a conflict there. As a test, comment out the loadView method in your superclass and see where that gets you.
I'm assuming SuperClass implements loadView. So when your SubClass is asked to loadView, you get your SuperClass' implementation, which overrides the normal nib loading mechanism.
I would rethink your design here. Your SuperClass' behavior is quite different from what you want your SubClass to do. Maybe that's not the best relationship there.
But, if you want, you should be able to at least make it work by doing this in your SubClass.m:
-(void)loadView {
IMP defaultImp = class_getMethodImplementation([[self superclass] superclass], _cmd);
/* or alternatively...
IMP defaultImp = class_getMethodImplementation([UIViewController class], _cmd);
*/
defaultImp(self, _cmd);
}
This implements a loadView for your subclass that skips over the loadView of your SuperClass and calls the default implementation instead.
IMO, this is ugly and might need to revisited if your class hierarchy expanded. I wouldn't do this in my own app, I would rethink the class hierarchy instead.
Where is this block located
SubClass *scvc = [[SubClass alloc] initWithNibName:#"SubClass" bundle:nil];
[self.navigationController pushViewController:scvc animated:YES];
[scvc release];
Are you sure it is called ?
I made a testproject to test it and the following works:
In your appDelegate.m file i put the following in the application didFinishLaunchingWithOptions method
UINavigationController *navController = [[UINavigationController alloc] init];
self.window.rootViewController = navController;
SubClass *viewController1 = [[[SubClass alloc] initWithNibName:#"SubClass" bundle:nil] autorelease];
[navController pushViewController:viewController1 animated:YES];
SuperClass.h
#import <UIKit/UIKit.h>
#interface SuperClass : UIViewController
#end
SuperClass.m
#import <UIKit/UIKit.h>
#import "SuperClass.h"
#implementation SuperClass
#end
SubClass.h
#import <UIKit/UIKit.h>
#import "SuperClass.h"
#interface SubClass : SuperClass
#end
SubClass.m
#import <UIKit/UIKit.h>
#import "SubClass.h"
#implementation SubClass
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
NSLog(#"Methods %# called", NSStringFromSelector(_cmd));
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
#end
This works for me, make sure you set the right class for your nibFile aswell. Click on the file's owner icon and change the class from UIViewController to SubClass
Try to add:
[super viewDidLoad];