My Car.m implementation file is as follows. Here I have 1 private method engineStarting.
Here I have used class extension concept to introduce
private method and I have also used Car+Maintainance as a category.
#import "Car.h"
//private methods
#interface Car()
-(BOOL) engineStarting;
#end
#implementation Car
#synthesize model=_model;
-(void)drive{
NSLog(#"%# is driving",_model);
}
-(void)stop{
NSLog(#"%# has stopped now",_model);
}
-(void)turnleft{
NSLog(#"%# is turning left",_model);
}
-(void)turnright{
NSLog(#"%# is turning right",_model);
}
-(BOOL) engineStarting{
return true;
}
My main.m file looks like
#import <Foundation/Foundation.h>
#import "Car.h"
#import "Car+Maintanance.h"
int main(int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
NSLog(#"Hello, World!");
Car *car=[[Car alloc]init];
car.model=#"maruti";
//using car its own methods
// i am getting error in this line(no visible #interface......)
[car engineStarting];
[car drive];
[car stop];
[car turnleft];
[car turnright];
//using maintainanace
if([car neddOilChange]){
[car changeOil];
}
}
return 0;
}
As you said you've created private method -(BOOL) engineStarting which means you can access it just within car class.
If you want that method to be visible in your main.m file move the declaration to car.h file it will make it public.
You say that you want to keep -engineStarting privately, but use it outside the implementation? That's contradictory, because private means: "Unvisible outside the implementation."
Probably you are messed up with the terms. And you are right in a way: There is no black and white private/public pair, but a greyscale: Something can be visible to an implementation only (usually called private), to an implementation and subclass implementations (usually called protected), to an implementation and subclass implementations and friend classes (in a framework, usually called package) and public at all. Beside this you can have the desire to make a method public only to some subsystems (modules) and so on. So it is very complex.
What you can do for it, is to create a separate category and import the header of that category file to the area, where it should be visible.
//Car_PublicInFrameworkAddition.h
#interface Car(PublicInFrameworkAddition)
-(BOOL) engineStarting;
#end
//Car_PublicInFrameworkAddition.m
#implementation Car(PublicInFrameworkAddition)
-(BOOL) engineStarting
{
…
}
#end
Somewhere.m
// Somewhere should see the addition
#import "Car_PublicInFrameworkAddition.h"
Related
I have the next code where I am getting a pointer to instance method:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#interface TestClass : NSObject
#end
#implementation TestClass
- (void)someMethod { // This is instance method, it's okay
NSLog(#"Hello from some method!");
}
#end
int main(int argc, const char * argv[]) {
typedef void (*MethodWithoutParams)();
MethodWithoutParams someMethodImplementation =
class_getMethodImplementation([TestClass class], #selector(someMethod));
someMethodImplementation();
return 0;
}
It works pretty good. But if I'd like to get a pointer to class method, it doesn't work:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#interface TestClass : NSObject
#end
#implementation TestClass
+ (void)someMethod { // This is class method, it doesn't work
NSLog(#"Hello from some method!");
}
#end
int main(int argc, const char * argv[]) {
typedef void (*MethodWithoutParams)();
MethodWithoutParams someMethodImplementation =
class_getMethodImplementation([TestClass class], #selector(someMethod));
someMethodImplementation();
return 0;
}
It doesn't work because it can not look up the method implementation.
I am sure it must work, because it works if I am getting the implementation in such way:
MethodWithoutParams someMethodImplementation =
[TestClass methodForSelector:#selector(someMethod)];
So I looked into NSObject implementation and see the next code:
+ (IMP)methodForSelector:(SEL)sel {
if (!sel) [self doesNotRecognizeSelector:sel];
return object_getMethodImplementation((id)self, sel);
}
- (IMP)methodForSelector:(SEL)sel {
if (!sel) [self doesNotRecognizeSelector:sel];
return object_getMethodImplementation(self, sel);
}
Also object_getMethodImplementation() function has the next implementation:
IMP object_getMethodImplementation(id obj, SEL name)
{
Class cls = (obj ? obj->getIsa() : nil);
return class_getMethodImplementation(cls, name);
}
So the implementation is same for both class method lookup and instance method lookup.
But it doesn't work and I have no idea why. I guess that any type of methods (both class and instance) gonna be located in the dispatch table, and I can get the pointer to any of this methods. But as you see I can't do it.
You need to query the class's metaclass. A class method is an instance method on its metaclass.
Class meta = objc_getMetaClass("TestClass");
SEL sel = #selector(someMethod);
typedef void (*MyMethodImplementation)(Class, SEL);
MyMethodImplementation someMethodImplementation = (MyMethodImplementation)class_getMethodImplementation(meta, sel);
someMethodImplementation([TestClass class], sel);
Note, a method (instance or class) is never "without parameters". It must always be called with at least the receiver (instance or class) and the selector.
I have absolutely no idea about Objective-C runtime. But here is my rant:
object_getMethodImplementation for class methods:
// returns a class method implementation, can't find instance methods
class_getMethodImplementation([TestClass class]->getIsa(),
#selector(classMethod));
which is equivalent to
class_getMethodImplementation(objc_getMetaClass("TestClass"),
#selector(classMethod));
object_getMethodImplementation for instance methods:
// returns an instance method implementation, can't find class methods
class_getMethodImplementation((<TestClass instance>)->getIsa(),
#selector(someMethod));
which is equivalent to:
class_getMethodImplementation([TestClass class],
#selector(someMethod))
So it seems that <TestClass instance>->getIsa() returns a pointer that is equal to what [TestClass class] returns. And I guess now you know what's the difference between a self in a class method and a self in an instance method.
So you should use meta class as #KenThomases suggests.
I am trying to define an instance variable which is a block
i have 2 classes as follows
#interface ClassA:NSObject
typedef void (^ABlock)(void);
#end
#import "ClassA.h"
#interface ClassB :NSObject
-(void)someMethodWithABlock:(ABlock)block;
#end
in class B the "ABlock" type is not recognized unless it is written right above the "someMethodWithABlock"
How can I fix it?
you want this?
typedef void (^blockA)(void);
#import <Foundation/Foundation.h>
#interface ClassA : NSObject
{
blockA classAblockA;
}
#end
#interface ClassB : NSObject
{
blockA classBblockA;
}
#end
hope this will help you
You want to pass a block as an argument of a method
so instead of writing this
- (void) someMethodWithABlock:(void (^)(void)) blockA;
you want to use typedef to make it more presentable
typedef void (^ABlock)(void);
now you can use it as
- (void) someMethodWithABlock:(ABlock) blockA;
Now You want to use above typedef to someWhere else for it you need to import this
.h file where you want to use this typedef(If you are already done it , you must have problem in your global file where you are importing it).
I am attempting to create an abstract class and inherit some of its properties in a subclass. If I leave the properties in the abstract class' header file, all of the properties are accessible. The problem is that the instance of the subclass can also access those properties, which is not always desirable in my case.
For instance, I have a delegate in my abstract class that sends down button presses to its sub class. I realize that this may not be the best way of structuring inheritance, so other suggestions are welcome. However, I would still like to know how my subclass can inherit some properties from its superclass without making all of those properties available in its instance. Thanks in advance!
Here is some example code below:
#interface AbstractClass : UIView
#property (nonatomic, strong) id<ButtonDelegate>buttonDelegate;
#end
…
#protocol ButtonDelegate
#required
- (void) buttonWasPressed;
#end
…
#interface SubClass() <ButtonDelegate>
- (id)init {
self = [super init];
if (self) {
self.buttonDelegate = self;
}
return self;
}
-(void) buttonWasPressed {
[self doSomething];
}
…
#implementation ViewController
- (void)viewDidLoad {
SubClass *subClass = [[SubClass alloc] init];
subClass.buttonDelegate = self; // THIS IS NOT DESIRABLE
}
Do like UIGestureRecognizer does.
All public properties and methods goes into UIGestureRecognizer.h
All protected properties and methods goes into UIGestureRecognizerSubclass.h.
Only import this in the *.m-files. Never include it in any public header.
All private properties and methods goes into *.m-files. Use the #interface ClassName ()
Example https://gist.github.com/hfossli/8041396
how to my subclass can inherit some properties from its superclass
without making all of those properties available in its instance
What is the problem with this?
#import <Foundation/Foundation.h>
#interface Animal : NSObject
{
#protected
NSString *name; // default access. Only visible to subclasses.
}
#end
#implementation Animal
-(NSString*)description {
return name;
}
#end
#interface Cow : Animal
#end
#implementation Cow
-(id)init {
self=[super init];
if (self){
name = #"cow";
}
return self;
}
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
Cow *cow = [Cow new];
NSLog(#"%#", cow); // prints the name through internal access
// error accessing from the outside: NSLog(#"%#", cow.name);
Animal *animal = [Animal new];
// error accessing from the outside: NSLog(#"%#", animal.name);
}
}
Maybe I misunderstood the question, you say
Creating properties only visible to subclass in Objective-C
and then
The problem is that the instance of the subclass can also access those
properties
Which one is it?
Create an empty category on top of your implementation file (.m):
#interface AbstractClass()
#property (nonatomic, strong) id<ButtonDelegate>buttonDelegate;
#end
In that way, your subclass will inherit and can access that property, but not other external classes because it's not in the header.
I don't think there is any way to achieve this using property declaration.
Either a property be visible for all (declared in .h file) or it will be invisible for all (declared in .m file using category)
I guess one way is declaring public/protected variable in .h file class declaration:
#interface AbstractClass : UIView {
...
id<ButtonDelegate>buttonDelegate;
...
}
#end
I am not sure about this, but give a try.
I see one approach that can fit your problem, however, it is pretty rude. Use Antonio's suggestion and create the private category with the property. As you've mentioned, it's scope is limited to the .m file. So you can put your subclasses into that file. This will be hard to read the code if subclasses are huge, but this is the only way for you as far as I understand.
EDIT: well, I have another solution. Copy
#property (nonatomic, strong) id<ButtonDelegate>buttonDelegate;
to all your subclasses. This will give you a warning about the absence of the property's #synthesize, but should work. I'd prefer this, if subclasses wont be changed or added often.
Let me describe how it would work.
We add a property into the Abstract class, and it is hidden for all (even for subclasses):
// .m file
#interface Abstract ()
#property (nonatomic, strong) id<ButtonDelegate> buttonDelegate;
#end
#implementation Abstract
#synthsize buttonDelegate;
#end;
But due to runtime features of Objective-C we still can call for that property, and there will not be any runtime error, only compiler warning.
To get rid of that warning and to add an ability to autocomplete, we add property without #synthsize into all subclasses:
#interface MySubclass : Abstract
#property (nonatomic, strong) id<ButtonDelegate> buttonDelegate;
#end
This will tell the compiler that there is such a property somewhere. There will be also one warning about the absence of #synthesize, but Xcode will still could autocomplete if you write something like
MySubclass *subclass = ...
subclass.butto...
It can not be done. There is no private or protected in objective-c. Stuff declared in the .m file "private" interface is only visible to that class and not in any subclass. Also you can always use your "private" properties/methods from outside if you want, although it would be bad practice to do so.
I found similar questions on this site but not one that addresses the problem in a clear and basic way.
I have my ReadViewController.h and ReadViewController.m files along with my ChooseViewController.h and ChooseViewController.m files.
They both need to access the getProperties method which is currently in the ReadViewController.m file.
- (void) getProperties {
NSLog(#"Start getProperties");
//SOME CODE
NSLog(#"End getProperties");
}
Now ideally this will be in a third file called GeneralModel.m
Please give me a basic example of what code needs to be in the controller files for them to be able to call this method.
If this method Going to be used in many places in Application then in this case you should treat it as Global method and try to put this method in separate class may be type of NSObject Class.
#interface Utility :NSobject
- (void) getProperties
#end
#implementation Utility
- (void) getProperties {
NSLog(#"Start getProperties");
//SOME CODE
NSLog(#"End getProperties");
}
#end
Here Whenever you need that methods you just need to create the Object of Utility Class can access it easily wherever it needed.like
in ReadViewController just make object and access in this way
Utility * obje = [Utility alloc]init];
[obje getProperties ];
And One thing if you just talking about the App architecture ,Suppose you following the MVC in that Case you should keep your model(NSObject Type)Class for Making some DB call, Request call to server. Keep View Classes code Like UIView separately and put the Code inside Controller class only which needed to control the Logic of App.
Here is the Link which explain The MVC Architecture.
I hope it clears to you.
The solution I've implemented looks like this. I'll accept iOS-Developer's answer though since it set me on the right track.
//*********************
//ReadViewController.h
#import <UIKit/UIKit.h>
#import "GeneralModel.h"
#interface ReadViewController : UIViewController {
GeneralModel *generalModel;
}
#end
//*********************
//*********************
//ReadViewController.m
#import "ReadViewController.h"
#interface ReadViewController ()
#end
#implementation ReadViewController
NSArray *allProperties;
- (void) getProperties {
generalModel = [[GeneralModel alloc] init];
allProperties = [generalModel getProperties];
NSLog(#"ALLPROPERTIES: %#", allProperties);
[generalModel release];
}
//**********************
//**********************
//GeneralModel.h
#import <Foundation/Foundation.h>
#import "sqlite3.h"
#interface GeneralModel : NSObject {
}
-(NSArray *) getProperties;
#end
//**********************
//**********************
//GeneralModel.m
#import "GeneralModel.h"
#implementation GeneralModel
- (NSArray *) getProperties {
NSLog(#"Start getProperties");
NSArray *someProperties;
//Some nice code goes here for getting a lot of nice properties from somewhere else.
return someProperties
NSLog(#"End getProperties");
}
//***********************
If this method Going to be used in many places in Application then in this case you should treat it as Global method and try to put this method in separate class may be type of NSObject Class.
#interface Utility :NSobject
- (void) getProperties
#end
#implementation Utility
- (void) getProperties {
NSLog(#"Start getProperties");
//SOME CODE
NSLog(#"End getProperties");
}
#end
Here Whenever you need that methods you just need to create the Object of Utility Class can access it easily wherever it needed.like
in ReadViewController just make object and access in this way
Utility * obje = [Utility alloc]init];
[obje getProperties ];
game.h file
#interface ViewController : UIViewController
{
UIImageView * player;
}
#end
game.m
-(void)InitPlayer
{
player.tag = 0;
}
player.m
I want InitPlayer in this file instead but keep declaration in game.h file.
- (void)InitPlayer
{
player.tag = 0; // access UIImageView *player;
}
Is this possible to do?
Thanks
just use this to declare -InitPlayer part of your class' public interface:
#interface ViewController : UIViewController
{
#private
UIImageView * player;
}
- (void)InitPlayer;
#end
then you keep your implementation of -InitPlayer in ViewController.m, where it must reside. You cannot place the method's implementation inside an #interface block.
if you are coming from other languages, then you should know that dispatch in objc is dynamic -- placing a definition in the header (if it were possible) would not result in an inlined/optimization.
In response to the clarified question:
Ok, then just do this:
Player.h
#interface Player : NSObject
- (void)prepareUIImageView:(UIImageView *)pImageView; // << could actually be a class method in this case
#end
Player.m
#implementation Player
- (void)prepareUIImageView:(UIImageView *)pImageView
{
pImageView.tag = 0;
}
#end
then you can tell the Player to initialize the view from the ViewController, assuming it has no controller itself.
(note: objc methods names typically begin with a lowercase character. as well, it's usually a good idea to hide this initialization stuff from your clients)