This question already has answers here:
What is the empty #interface declaration in .m files used for?
(2 answers)
Closed 8 years ago.
info: iOS5, xcode4.3.2, iphone5
Create tab view controller application from xcode template wizard.
Following code gets generated (some truncated by me for this post).
=== SUFirstViewController.h
#import <UIKit/UIKit.h>
#interface SUFirstViewController : UIViewController
#end
=== SUFirstViewController.m
#import "SUFirstViewController.h"
#interface SUFirstViewController ()
#end
#implementation SUFirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
#end
===
My question is regarding this code snippet:
#interface SUFirstViewController ()
#end
Why is this particular code snippet generated in the SUFirstViewController.m ?
Can I remove it ?
How do I use it ?
As Matthias said, is for things you want to keep private or hidden to clients of the class :)
This part of the code is called class extension (others call them anonymous categories because they don't have a name in the parenthesis) and you could used them to write something like this:
#interface SUFirstViewController ()
#property (nonatomic, strong) IBOutlet UITextView *textview;
#property (nonatomic) float privateProperty;
- (IBAction)someAction:(id)sender;
- (float)resultOfDoingSomething;
#end
Interface Builder is pretty smart and you will be able to hock your outlets/actions if you write them here, in fact Apple recommends to have your IBOutlets/IBActions declared in this place because most of the time you don't need to expose them.
You can also have any other private property, and method like the ones I wrote.
Hope it helps.
It is generated for the case, you want do declare private things (methods, members, protocols, etc.) If you do not, you can delete it safely.
That's an Objective-C Class Extension. It's where you typically declare your private methods and instance variables. For example:
#interface MyClass()
{
int _privateInstanceVariable;
}
#property (nonatomic, retain) NSString* privateProperty;
-(void)privateMethod;
#end
#implementation MyClass
#synthesize privateProperty;
// etc...
You can remove it if it's not used.
Related
I'm getting an "incomplete implementation" error in my .m file, but I cannot figure it out how to fix it. I`ll post .h and .m files if you can give me tips on how to fix that. Thanks.
Apparently, I need to put more details, or I cannot post the question because the post contains mostly code, so this are just some dummy lines.
.h File
#import <UIKit/UIKit.h>
#interface BlogViewController : UIViewController <UIPickerViewDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate>
- (IBAction)selectPicturePressed:(id)sender;
- (IBAction)blogPost:(id)sender;
#property (weak, nonatomic) IBOutlet UITextView *commentTextField;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (nonatomic, strong) NSString *username;
#end
.m File
#import "BlogViewController.h"
#import <Parse/Parse.h>
#import "SWRevealViewController.h"
#import "PhotoViewController.h"
#interface BlogViewController ()
-(void)showErrorView:(NSString *)errorMsg;
#end
#implementation BlogViewController **//Incomplete Implementation**
#synthesize imageView = _imageView;
#synthesize username = _username;
#synthesize commentTextField = _commentTextField;
IBActions are just regular functions with syntactic sugar for connecting them to interface builder therefore you have to implement them in the .m file
.m file:
- (IBAction)selectPicturePressed:(id)sender {
// code here
}
- (IBAction)blogPost:(id)sender {
// and here
}
On the line that's giving you the Incomplete Implementation error, you can get more details about what you're missing.
You don't paste all your .m so it's anyone's guess what you're missing, however, your .h declares 2 methods and 3 protocols that you must implement.
Your .m file must have method bodies for these two methods:
- (IBAction)selectPicturePressed:(id)sender;
- (IBAction)blogPost:(id)sender;
Likely, you already have these in here, particularly if these were generated by Ctrl+Dragging from interface builder.
But you must also include, at a minimum, all the required methods from the protocols you declared.
UIPickerViewDelegate protocol official documentation
UINavigationControllerDelegate protocol official documentation
UIImagePickerControllerDelegate protocol official documentation.
(I'm not completely familiar with these protocols and don't know for sure that they actually have any #required methods.)
Your .m also has a private interface, which declares a method you must implement in the implementation.
-(void)showErrorView:(NSString *)errorMsg;
You declared this method in a private interface, so be sure to implement this method as well.
Regardless of what you're missing, Xcode will absolutely tell you if you just click on the error/warning. Xcode will give you the names of the methods its expecting to find in your implementation but cannot.
I now know there is no protected method in Objective-C and here is my problem.
I have two viewControllers with many functions and properties that are shared. My vision was to have a BaseViewController holding the shared methods and properties, and from it two classes will inherit and override the needed functionality while using the same variables,
I don't wish to convert the shared functions to public by placing them in the .h file
To help clarify my question I'm adding code :)
#interface BaseViewController ()
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *uiButtons;
- (void)setBtns:(NSArray *)p_btns; //tried with & without this line
#end
#implementation BaseViewController
- (void)setBtns:(NSArray *)p_btns {
uiButtons = p_btns;
//do something generic with the buttons (set font, image etc.)
}
#end
#interface DerivedViewController ()
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *buttonsConnectedToTheActualView;
#end
#implementation DerivedViewController
- (void) setBtns:(NSArray *)p_btns {
[super setBtns:p_btns];
//do something specific with the buttons (decide if they face up or down according to this class logic)
}
#end
The call to [super setBtns:p_btns]; raises an error:
DerivedGameViewController.m:No visible #interface for 'BaseViewController' declares the selector 'setBtns:'
How can I achieve this? Can someone post a snippet or point to my mistake (in code or concept).
Just create a second header with the protected methods declared in a category. Name and document the header appropriately.
UIGestureRecognizer.h and UIGestureRecognizerSubclass.h may server you as an example.
Take this simple class hierarchy:
Tree.h:
#interface Tree : NSObject
#property (nonatomic, assign) id<TreeDelegate> delegate;
#end
Tree.m:
#implementation Tree
#synthesize delegate;
#end
Aspen.h:
#interface Aspen : Tree
- (void)grow:(id<TreeDelegate>)delegate;
#end
Aspen.m:
#implementation Aspen
- (void) grow:(id<TreeDelegate>)d {
self.delegate = d;
}
#end
When I try to do self.delegate = d;, I'm getting the following error:
-[Aspen setDelegate:]: unrecognized selector sent to instance 0x586da00
I was expecting the Tree parent class's delegate property to be visible to the subclass as-is, but it doesn't seem to be since the error indicates the parent class's synthesized setter isn't visible.
What am I missing? Do I have to redeclare the property at the subclass level? I tried adding #dynamic at the top of the implementation of Aspen but that didn't work either. Such a simple concept here, but I've lost an hour searching around trying to find a solution. Out of ideas at this point.
--EDIT--
The above code is just a very stripped-down example to demonstrate the issue I'm seeing.
I just tried your code, supplemented by the protocol, an object implementing it, the necessary import and a main function and on my system it works like a charm:
#import <Foundation/Foundation.h>
#protocol TreeDelegate <NSObject>
#end
#interface MyDelegate : NSObject <TreeDelegate>
#end
#implementation MyDelegate
#end
#interface Tree : NSObject
#property (nonatomic, assign) id<TreeDelegate> delegate;
#end
#interface Aspen : Tree
- (void)grow:(id<TreeDelegate>)delegate;
#end
#implementation Tree
#synthesize delegate;
#end
#implementation Aspen
- (void) grow:(id<TreeDelegate>)d {
self.delegate = d;
}
#end
int main(int argc, char ** argv) {
MyDelegate * d = [[MyDelegate alloc] init];
Aspen * a = [[Aspen alloc] init];
[a grow:d];
return 0;
}
I was finally able to figure this out. My actual code leverages a 3rd party static library that defines the classes Tree and Aspen in my example. I had built a new version of the static library that exposed the Tree delegate given in my example, however I did not properly re-link the library after adding it to my project and as a result the old version was still being accessed at runtime.
Lessons learned: be diligent with steps to import a 3rd party library, and when simple fundamental programming concepts (such as in my example text) aren't working, take a step back and make sure you've dotted i's and crossed t's.
This should be an easy question - but I'm having a hard time figuring it out. I'm trying to create a property on an object so that during prepareForSegue I can tell the object what it's delegate is. I know I could do this with protocols but I figured for this case a direct approach would be simplest. Unfortunately, the following code results in a compiler error:
#import <UIKit/UIKit.h>
#import "PlanningViewController.h"
#interface DepartmentViewController : UITableViewController
#property (nonatomic, weak) PlanningViewController *planningDelegate;
#end
When I type the property declaration, Xcode recognizes PlanningViewController and even displays the text for me to just tab through. The compiler, though, complains with:
Unknown type name 'PlanningViewController': did you mean 'UISplitViewController'?
What am I doing wrong?
PlanningViewController.h looks like this:
#import <UIKit/UIKit.h>
#import "DepartmentViewController.h"
#interface PlanningViewController : UITableViewController
// Table cell connections
- (IBAction)addItemPressed:(id)sender;
#end
Remove this line from your PlanningViewController.h header file:
#import "DepartmentViewController.h"
You have something of a loop in your header files.
Better still, make DepartmentViewController.h look like this (there is no need to include PlanningViewController.h in your header file):
#import <UIKit/UIKit.h>
#class PlanningViewController;
#interface DepartmentViewController : UITableViewController
#property (nonatomic, weak) PlanningViewController *planningDelegate;
#end
I think you've kind of missed one of the main points of the delegate patter which is to decouple you objects. The best way of declaring this delegate would be:
#import <UIKit/UIKit.h>
#protocol DepartmentViewControllerDelegate; // forward declaration of protocol
#interface DepartmentViewController : UITableViewController
#property (nonatomic, weak) id <DepartmentViewControllerDelegate> delegate;
#end
#protocol DepartmentViewControllerDelegate
- (void)departmentViewController:(DepartmentViewController *)controller
isProcessingPeople:(NSArray *)people
#end
In your department view controller, you would then write something like this:
if ([self.delegate respondsToSelector:#selector(departmentViewController:isProcessingPeople:)]) {
[self.delegate departmentViewController:self isProcessingPeople:people];
}
And in your planning view controller, you would implement this method:
- (void)departmentViewController:(DepartmentViewController *)controller
isProcessingPeople:(NSArray *)people {
// do necessary work here
}
The example here is just an example of one message you can send to the delegate. You can add whatever you need, but this makes it so there is no coupling between your controllers. The planning view controller knows everything it needs to about the department controller, but the department controller doesn't need to know anything about the planning controller.
If you want to stick with what you have currently, just recognize that it's not really the delegate pattern, and you should probably rename your property.
this is a follow-up question to my last one here: iOS: Initialise object at start of application for all controllers to use .
I have set my application up as follows (ignore the DB Prefix):
DBFactoryClass // Built a DataManaging Object for later use in the app
DBDataModel // Is created by the factory, holds all data & access methods
DBViewControllerA // Will show some of the data that DBDataModel holds
moreViewControllers that will need access to the same DBDataModel Object
i will go step by step through the application, and then post the problem in the end
AppDelegate.h
#import "DBFactoryClass.h"
AppDelegate.m
- (BOOL)...didFinishLaunching...
{
DBFactoryClass *FACTORY = [[DBFactoryClass alloc ]init ];
return YES;
}
DBFactoryClass.h
#import <Foundation/Foundation.h>
#import "DBDataModel.h"
#interface DBFactoryClass : NSObject
#property (strong) DBDataModel *DATAMODEL;
#end
DBFactoryClass.m
#import "DBFactoryClass.h"
#implementation DBFactoryClass
#synthesize DATAMODEL;
-(id)init{
self = [super init];
[self setDATAMODEL:[[DBDataModel alloc]init ]];
return self;
}
#end
ViewControllerA.h
#import <UIKit/UIKit.h>
#import "DBDataModel.h"
#class DBDataModel;
#interface todayViewController : UIViewController
#property (strong)DBDataModel *DATAMODEL;
#property (weak, nonatomic) IBOutlet UILabel *testLabel;
#end
ViewControllerA.m
#import "todayViewController.h"
#implementation todayViewController
#synthesize testLabel;
#synthesize DATAMODEL;
- (void)viewDidLoad
{
todaySpentLabel.text = [[DATAMODEL test]stringValue]; // read testdata
}
#end
DBDataModel.h
#import <Foundation/Foundation.h>
#interface DBDataModel : NSObject
#property (nonatomic, retain) NSNumber* test;
#end
DBDataModel.m
#import "DBDataModel.h"
#implementation DBDataModel
#synthesize test;
-(id)init{
test = [[NSNumber alloc]initWithInt:4]; // only a testvalue
return self;
}
#end
the app builds fine, and starts up but the label stays blank. so either the object does not exist (but i guess this would result in an error message), or something else is wrong with my setup. any thoughts?
Two notes:
Your have a shotgun approach to asking questions: everytime you hit a stumbling block, you ask a question and if the answer does not work immediately, you ask another one. You have to spend some energy in between the questions debugging and poking into the code on your own, otherwise you will depend on the external help forever.
Use the common coding style please. CAPS are reserved for macros.
Now to the code:
- (BOOL) …didFinishLaunching…
{
DBFactoryClass *factory = [[DBFactoryClass alloc] init];
return YES;
}
This simply creates an instance of the DBFactoryClass and then throws it away. In other words, it’s essentially a no-op. Judging by the comments in the previous answer you create the controllers using the Storyboard feature. How are they supposed to receive the reference to the data model? The reference isn’t going to show up by magic, you have to assign it somewhere.
I’m not familiar with the Storyboard feature. The way I would do it is to create the view controllers using separate XIB files, then you can create the controller instances in the Factory class and pass them the needed reference to the model. In the end the application delegate would create the factory, ask it to assemble the main controller and then set it as the root view controller for the window. Just like in my sample project. It’s possible that there’s a way to make it work with storyboards, but as I said, I am not familiar with them.