I've looked up about a dozen different pages, both on how to call methods from other views and instances when the method is being skipped, but no answer has come.
I'm going to be thorough here. Two relevant classes:
SpeakersView
and
GetData
GetData is just there because I'm going to need to call that method from half a dozen different classes, best to just write it once.
Here's GetData.h:
#import <UIKit/UIKit.h>
#interface GetData : UIViewController
-(NSArray *)getTableArray:(NSString *)section :(NSString *)entity;
#end
Here's GetData.m:
#interface GetData (){
NSArray *tableData;
NSArray *titleData;
NSArray *splitData;
}
#end
#implementation GetData
- (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.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSArray *)getTableArray:(NSString *)section :(NSString *)entity{
//Code omitted. Shouldn't really have anything to do with why the method is being skipped.
}
#end
So here's how I'm calling the method in SpeakersView.m:
GetData *GD;
menu_List = [GD getTableArray:#"Speakers" :#"John Smith"];
Recommendations? I should mention I've had no problem calling other methods in exactly the same way from different classes.
GetData *GD; doesn't initialize the UIViewController. It's nil at that point, so you cannot call a method on it.
Try:
GetData *GD = [[GetData alloc] init];
Also, why is GetData a UIViewController? Make it an NSObject, you don't need a whole view controller with all of its bulk if you're just using it for that method.
Calling a class "GetData" that inherits an UIViewController shows clearly a huge conception problem. A controller is a class that feed its views with the model (in the MVC pattern). It's not an utility class.
In your example you're also not instantiating the controller.
Related
I have a custom object class (Ship.h and Ship.m), and I am trying to create a new Ship type object with this code:
Ship *PlayerShip = [[Ship alloc] init];
The code is currently in my First view controller.m and under
- (void)viewDidLoad{
but I have tried it in
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
as well.
I create the PlayerShip object just fine with no problems, then I log it with
NSLog(#"Player ship: %#",PlayerShip);
It logs just fine as well.
Then in another part of my code (anywhere other than the place I put it) like for example an NSTimer I try the same NSLog line and it returns
Player Ship: Null
Is the PlayerShip object being deleted for some reason?
I would appreciate any help.
Below is my shipViewController.h
#import <UIKit/UIKit.h>
#import "Ship.h"
#interface ShipViewController : UIViewController{
IBOutlet UILabel *PlayerShipLabel;
IBOutlet UIProgressView *PlayerHullBar;
IBOutlet UIProgressView *PlayerShieldBar;
IBOutlet UILabel *PlayerCreditsLabel;
IBOutlet UIImageView *PlayerShipImage;
IBOutlet UIButton *PlayerRepairBreachButton;
}
#end
Ship *PlayerShip;
And here is ShipViewController.m
#import "ShipViewController.h"
#interface ShipViewController ()
#end
#implementation ShipViewController
- (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.
Ship *PlayerShip = [[Ship alloc] init];
NSLog(#"Player ship: %#",PlayerShip);
}
- (IBAction)ShieldSwitch:(id)sender {
NSLog(#"Ship is %# ",PlayerShip);
}
- (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
Here is my Output from the program when the app first starts:
2014-06-12 19:02:27.503 First Game[5193:60b] Created a new ship!
2014-06-12 19:02:27.504 First Game[5193:60b] Player ship: <Ship: 0x8c30f70>
And here is the output from when I press the button to verify PlayerShip:
2014-06-12 19:02:29.472 First Game[5193:60b] Ship is (null)
There are several problems.
Why do you declare Ship *PlayerShip; in your .h file after the #end statement? That makes it a global variable. Make it an instance variable like the others but putting it in the curly braces of the #interface statement.
In viewDidLoad you create a local variable with the same name as the (soon-to-be) instance variable. Don't declare a new variable. Simply assign the new object to the (soon-to-be) instance variable.
I'm trying to implement simgle AdBanner instance for multiple views in an iOS app. For implementing AdbannerDelegate in a viewController one has to do
bannerview.delegate= self;
where bannerview is an instance of AdBannerView. This delegate method however has to be implemented in every viewController which amounts up to a lot of repeating code. How can I make up a simple class that implements all delegate methods and then I call use them in every viewController.
I think the viewControllers you are using are subclasses of UIViewController.
And you are saying all the viewControllers have the same delegate methods.
So,what i want to do is create new ViewController class (UIDelgateViewController) by SubClassing UIViewController and add all delegate methods there , and have all the other viewControllers subclass UIDelgateViewController.
The code goes like this,
.h file->
#interface UIDelegateViewController : UIViewController<ADBannerViewDelegate>
#property ADBannerView *bannerView;
#end
.m file ->
#import "UIDelegateViewController.h"
#interface UIDelegateViewController ()
#end
#implementation UIDelegateViewController
- (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.
_bannerView = [[ADBannerView alloc] init];
_bannerView.delegate =self;
}
-(void)bannerDelegateMethod{
}
Now your Some viewController ->
#import "UIDelegateViewController.h"
#interface SomeViewController : UIDelegateViewController
#end
#import "SomeViewController.h"
#interface SomeViewController ()
#end
#implementation SomeViewController
- (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.view addSubview:self.bannerView];
self.bannerView.frame = ..../
}
If you want to keep always on the screen the same banner while navigating and changing views, you should consider to use View Controller containtment API
A great example is that remarkable sample code written by Apple, that shows how to keep the same banner instance while moving in a tabbar or navigation controller. It could be also a great start for you project.
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.
Lets say I have a very simple method in my ViewController that returns a number.
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Number: %i",self.returnNumber);
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)returnNumber
{
NSInteger number = 2;
return number;
}
#end
This works just fine, but when I modify the method returnNumber to accept an input parameter like so:
#import "ViewController.h"
#interface ViewController (
)
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Number: %i",self.returnNumber:2);
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)returnNumber:(NSInteger)insertedNumber
{
NSInteger number = insertedNumber;
return number;
}
#end
The compiler says:
Property 'returnNumber' not found on object of type 'ViewController *'
Is it some kind of bug or did I totally fail to learn how Objective-C methods work?
Is it some kind of bug or did I totally fail to learn how Objective-C methods work?
The latter. You're confusing message send and property accessor notation. Property accessor methods can't take any arguments. What you want instead are:
I. [self returnNumber:2]
II. A good Objective-C beginner's guide, with special regards to syntax and properties. Here's Apple's official material on the subject for a starter.
Declare method in .h file.
-(NSInteger)returnNumber:(NSInteger)insertedNumber;
and call the method like this
[self returnNumber:2];
You have to put it in brackets like this
[self returnNumber:2]
That should fix the problem.
NSLog(#"Number: %i",[self returnNumber:2]);
try this for more about Methods and Messaging
[self returnNumber:2] will be the solution. As self defines its own class or viewController and to call a method of the same class we call that method using self.