Overridden properties from superclass - iphone

I have a superclass of UIViewController - MasterViewController which declares a property called itemsViewController. This declares a method called from the MasterViewController, and is wired up via a storyboard in IB.
I have a subclass of MasterViewController which redeclares this property as a specific iPad version, but I can't access the redeclared property from the parent class.
MasterViewController
#interface MasterViewController : UIViewController {
}
#property (nonatomic, strong) IBOutlet ItemsViewController *itemsViewController;
#end
#implementation MasterViewController
#synthesize itemsViewController;
-(void)viewDidLoad {
// I can access itemsViewController in viewDidLoad.
}
#end
MasterViewController_iPad
#interface MasterViewController_iPad : MasterViewController {
IBOutlet ItemsViewController_iPad *_itemsViewController;
}
#property (nonatomic, strong) IBOutlet ItemsViewController_iPad *itemsViewController;
#end
#implementation MasterViewController_iPad
#synthesize itemsViewController = _itemsViewController;
-(void)viewDidLoad {
[super viewDidLoad];
// when I call super viewDidLoad, itemsViewController is nil, as though the property hasn't been overriden
// _itemsViewController is not nil in viewDidLoad.
}
#end
Am I misunderstanding the way property inheritance works in Objective-C?

You can't change the type signature of a method when you override a superclass method.
MasterViewController has these methods:
(void)setItemsViewController:(ItemsViewController *)foo
(ItemsViewController *)itemsViewController
But you're trying to give MasterViewController_iPad these methods:
(void)setItemsViewController:(ItemsViewController_iPad *)foo
(ItemsViewController_iPad *)itemsViewController
Which you can't do: you can't overload the same method name but have different types for the arguments.
If ItemsViewController_iPad is a subclass of ItemsViewController, a quick solution would be to keep the same signature as in MasterViewController but simply use an ItemsViewController_iPad when you set the property.

You can use category if you'd like to override property. Here is example:
I have PDFFileChooserViewController with PDFFileModel and PDFFilesDataSource and some logic related to this properties.
#class PDFFileModel, PDFFilesDataSource;
#interface PDFFileChooserViewController : UIViewController
#property (nonatomic, strong) PDFFileModel* selectedModel;
#property (nonatomic, strong) PDFFilesDataSource*dataSource;
#end
Then I'd like to add specific ViewController for choosing files from Dropbox but my model have some additional fields for example dropboxPath and my DropboxDataSource gets files using another way. So I decided to create category and override this properties:
#import "PDFFileChooserViewController.h"
#class DropboxFileModel,DropboxDataSource;
#interface DropboxViewController : PDFFileChooserViewController
#end
#interface DropboxViewController (ModelCategory)
#property(nonatomic, strong) DropboxFileModel* selectedModel;
#property(nonatomic, strong) DropboxDataSource* dataSource;
#end
Notice that this category will be visible inside DropboxViewController only where I can manipulate with that properties but another classes see only super class interface

Related

Local declaration of "speed view" hides instance variable

So I have been searching in a few hours for why my iPhone app hates me. This is the error I get:
Warning: local declaration of 'speedView' hides instance variable.
Here is my .m file
#implementation MainViewController
#synthesize speedCount;
#synthesize speedView;
#synthesize popoverController;
- (void)setspeedView:(UILabel *)speedView
{
[speedView setText: [NSString stringWithFormat:#"%d",speedCount]];
speedCount = 0;
speedCount++;
}
.h file
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MainViewController : UIViewController <LoginDelegate,WEPopoverParentView,PopoverControllerDelegate,MainMenuDelegate,MKMapViewDelegate,UIActionSheetDelegate,UIAccelerometerDelegate, CLLocationManagerDelegate>
{
AppDelegate *appDelegate;
IBOutlet MKMapView *userMap;
IBOutlet UILabel *speedView;
CLLocationManager *locationManager;
}
#property (strong, nonatomic) IBOutlet UILabel *speedView;
#property(nonatomic) int speedCount;
I really don't understand why it says that I am hiding the instance variable.
You have a ivar (an instance variable) called speedView.
In your method
- (void)setspeedView:(UILabel *)speedView
speedView is a local variable whose name clashes with the ivar.
If you are using a modern version of the compiler just remove the #synthesize directive.
It will be automatically added by the compiler in this form
#synthesize speedView = _speedView
which will create the ivar _speedView, whose name doesn't clash anymore with the local variable.
Also note that declaring both the instance variable and the property is redundant. The ivar will be automatically created by the (implicit) #synthesize directive.
Here's a "modern" version of your class:
.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MainViewController : UIViewController <LoginDelegate,WEPopoverParentView,PopoverControllerDelegate,MainMenuDelegate,MKMapViewDelegate,UIActionSheetDelegate,UIAccelerometerDelegate, CLLocationManagerDelegate>
#property (strong, nonatomic) IBOutlet UILabel *speedView;
#property (strong, nonatomic) CLLocationManager *locationManager;
#property (strong, nonatomic) IBOutlet MKMapView *userMap;
#property (strong, nonatomic) AppDelegate *appDelegate;
#property (nonatomic) int speedCount;
.m
#implementation MainViewController
- (void)setspeedView:(UILabel *)speedView {
[speedView setText:[NSString stringWithFormat:#"%d", self.speedCount]];
self.speedCount = 0;
self.speedCount++;
}
Please note:
properties are nice: use them whenever you can
#synthesize is implicit
the implicit version of #sythesize declares a _ivar for the property ivar
always access variables through the getters/setters, i.e. self.ivar, a part from init methods. If you need to access the var directly use _ivar or self->_ivar
As a final remark, this looks a bit weird
self.speedCount = 0;
self.speedCount++;
and it could be replaced with
self.speedCount = 1;
Are you sure it's what you mean? Also, as noted in the comments by others, you are not using the method parameter speedView. That smells bad and you may want to double check your implementation.

UIViewController obj updated in mycustomview controller implementation how to get it in a subclass

i created a myCustomviewcontroller and made all other .m files as subclasses to it.
and myCustomviewcontroller contains an UIViewController obj and property defined as:
#interface MyCustomViewController : UIViewController{
IBOutlet UINavigationController *navigationController;
UIViewController *topView;
}
#property(nonatomic, retain) IBOutlet UINavigationController *navigationController;
#property(nonatomic, retain) IBOutlet UIViewController *topView;
#end
in the implementation the topview is initialized or given a view controller as in
#implementation MyCustomViewController
//some method
topView = appDelegate.navigationController.topViewController;
#end
and there is another class demo.h which uses MyCustomViewController
#interface demo : MyCustomViewController{
}
and in the implementation of demo.m i want to get the topview value.
not just the instance of topview but the value which is assigned to topview in the implementation of MyCustomViewController.m is this possible if so please help me
thanks.
By the rule of inheritance you can use the instance variable of base class or super class.
so i will prefer you whenever you use inheritance you initialise the property in derived class not in super class so in your case you initialise
super.topView = appDelegate.navigationController.topViewController;
in demo not in MyCustomViewController.

property not found of object of type 'segmentControl' iphone

I have defined segmentControl buttons.
#property(nonatomic, strong) SegmentControl *option;
SegmentControl *result = [[SegmentControl alloc] initWithFrame:frame items:#[#"Bad", #"Good"]];
result:self.option.selectedSegmentIndex
why am I getting this error: property 'selectedSegmentIndex' not found on object of type 'segmentControl',
#class SegmentControl;
#protocol SegmentControlDelegate <NSObject>
#optional
- (void)segmentControl:(SegmentControl *)segmentControl didSelectSegment:(UIButton *)segment;
#end
#interface SegmentControl : UIView
#property(nonatomic, assign) BOOL staySelected;
#property(nonatomic, weak) id<SegmentControlDelegate> delegate;
- (id)initWithFrame:(CGRect)frame items:(NSArray *)items;
#end
Your class SegmentControl needs to be a subclass of UISegmentControl (not UIView).

Passing a value from UIViewController to UIView

I have the following UIViewController class:
FILE: ResultsDataViewController.h
#interface ResultsDataViewController : UIViewController
#property (nonatomic, strong) NSString* name;
#end
FILE : ResultsDataViewController.m
#import "ResultsDataViewController.h"
#interface ResultsDataViewController ()
#end
#implementation ResultsDataViewController
#synthesize data;
Then I have my UIView with class name Plot.h/m
Plot.h:
#interface PlotGraph : UIView <CPTBarPlotDataSource, CPTBarPlotDelegate>
#property (nonatomic, strong) NSString* receivedName;
#end
Plot.m:
#import "Plot.h"
#interface Plot()
#end
#implementation PlotGraph
#synthesize receivedName;
...
=====
Question:
HOW do I pass the value of name from my UIViewController and assign it to the variable receivedName in my UIView?
The UIView Plot is a view in my UIViewController DataViewController
(Note: #synthesize data; in your question is probably a typo. I'll assume you meant #synthesize name;. Also, #interface Plot() should probably be #interface PlotGraph().)
First, you need to have a reference to a PlotGraph object either as something you create in code or something that you load into an IBOutlet variable from your xib file or storyboard. Once you have that, either where you create it or in viewDidLoad:, it's simply something like:
plotView.receivedName = self.name;

How to use delegate methods to pass objects between two view controllers?

I'm using the Utility Application project to Xcode 4.2, then I am adding two text fields for each view: main view and the flipside view.
Now I wish to assign the value of the flipside text field to mainview text field.
MainViewController.h
#import "FlipsideViewController.h"
#interface MainViewController : UIViewController <FlipsideViewControllerDelegate> {
UITextField *nameField;
}
#property(nonatomic, retain) IBOutlet UITextField *nameField;
- (IBAction)showInfo:(id)sender;
#end
FlipsideViewController.h
#class FlipsideViewController;
#protocol FlipsideViewControllerDelegate
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller;
#end
#interface FlipsideViewController : UIViewController {
UITextField *changeText;
}
#property (nonatomic, retain) IBOutlet UITextField *changeText;
#property (assign, nonatomic) IBOutlet id <FlipsideViewControllerDelegate> delegate;
- (IBAction)done:(id)sender;
#end
FlipsideViewController.m
#import "FlipsideViewController.h"
#implementation FlipsideViewController
#synthesize delegate = _delegate;
#synthesize changeText;
- (IBAction)done:(id)sender
{
[self.delegate flipsideViewControllerDidFinish:self];
}
When the done action starts, i want the changetext value be assigned to nameField text.
How do I do this?
In MainViewController.m, implement the flipSideViewControllerDelegate method as:
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller
{
self.nameField.text=controller.changeText.text;
}
So when the done: method is called, this delegate method is also called with your flipSideViewController object as the argument, through which changeText can be accessed.
EDIT to answer question in comment:
In your protocol FlipSideViewControllerDelegate, add this method:
- (void)flipsideViewControllerDidSelect:(NSIndexPath*)indexPath
Then it is similar to the other delegate method implementation in MainViewController.m
, which is how the protocol works really. If your MainViewController conforms to the protocol, it can implement methods of that protocol. By default all the methods declared in the protocol are optional, but you have the option to specify if the method is optional or required by using
#optional
//list of methods
#required
//list of methods
Bear in mind that if your a method is declared as required in the protocol, any class conforming to that protocol must implement it. Anyway, in your MainViewController.m:
- (void)flipsideViewControllerDidSelect:(NSIndexPath*)indexPath
{
int anInt=indexPath.row;
self.nameField.text=[NSString stringWithFormat:#"%d",anInt];
}