Accessing interface method defined in .m file - objective-c

MyClass.h file
#import <Foundation/Foundation.h>
#interface MyClass : NSObject
{
// This is the Place of Instance Variable
}
- (void)thePublicMethod;
#end
MyClass.m file
#import "MyClass.h"
#interface MyClass()
- (void)thePrivateMethod;
#end
#implementation MyClass
-(void)thePublicMethod {
NSLog(#"Public Method Called");
}
- (void)thePrivateMethod {
NSLog(#"Private Method Called");
}
#end
The main.m file
#import <Foundation/Foundation.h>
#import "MyClass.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
MyClass *myObj = [[MyClass alloc] init];
[myObj thePublicMethod];
// [myObj thePrivateMethod];
}
return 0;
}
since “Private” methods can be created by defining them in a class’s implementation file while omitting them from its interface file.
i want to access thePrivateMethod from main.m and also can i call thePrivateMethod() from thePublicMethod() is it possible and how ?

If you want to access an internal method from somewhere other than the class's implementation, then you need to truly declare it as a private method.
Move that class extension to its own header file, say MyClass_Private.h. Then #import that header into both main.m and MyClass.m.
I.e. move this:
#interface MyClass()
- (void)thePrivateMethod;
#end
Into a file called MyClass_Private.h and then #import "MyClass_Private.h" in both your MyClass.m and main.m files.
Internal means only used in the innards of this framework or class.
Private means may be used by this framework or the class, but may be exposed to clients that are more intimately tied to the class than through Public API. Typically reserved for framework authors on large scale systems (like the OS).
Public means may be used anywhere by any client of the class.

No matter how or where or IF you declare a method, at all.. If it exists.. calling it is as simple as
[myInstance performSelector:NSSelectorFromString(#"yourSuperSecretMethod:")
withObject:myKillerObject];
If the method got compiled.. It will get called. There is no "hiding" it. Even if not declared, the runtime "gives up" this information to any interested party. #see class-dump, if interested in learning more.

Related

Objective C: Making Object in .h Files

I am using Xcode 5.x and I want to make an object of another class in my second class's .h file. So a myclass1 object in myclass2.h. Here is a replica of my MyClass2.h (The name is different and the bulk code is gone):
#import <Foundation/Foundation.h>
#import "MyClass1.h"
#class MyClass1 ;
MyClass1 * object1 ;
#interface MyClass2 : NSObject{
}
#end
However, I cannot type: MyClass1 *object = [MyClass1 new] ; because it is not a compile time constant. I understand the error, but where do I put the [MyClass1 new]? Without it, the object is created, but when I use it in MyClass2.m, I cannot access the methods of MyClass1. Will I have to make the object in main.m? I am making an iOS app (if that helps).
The header file (.h) is really primarily used to declare instance variables, properties, and expose functions, you don't want to be running any code there.
Your header should look something like:
#import <Foundation/Foundation.h>
#import "MyClass1.h"
#interface MyClass2 : NSObject {
MyClass1 *instanceOfMyClass1;
}
#end
And in your implementation file (.m) you can then do this in whatever function (init/viewDidLoad/whatever) you'd like:
instanceOfMyClass1 = [MyClass1 new];

Understanding private instance variable

I'm having a hard time understanding private instance variables through example. After reading about private instance variables, I went to Xcode and tried to verify how they work.
In the book I'm reading, it states that if you declare an instance variable in the implementation file of a superclass, the instance variable will be private and inaccessible to subclasses.
I tried proving it doing the following without any luck.
/** SuperClass interface file**/
#import <Foundation/Foundation.h>
#interface ClassA : NSObject
-(void) setX;
-(void) printX;
#end
/**SuperClass implementation file **/
#import "ClassA.h"
#implementation ClassA
{
int x;
}
-(void) setX
{
x = 100;
}
-(void) printX
{
NSLog(#" x is equal to %i", x);
}
#end
/** interface file of subclass **/
#import "ClassA.h"
#interface ClassB : ClassA
#end
/**Main file **/
#import "ClassA.h"
#import "ClassB.h"
int main(int argc, const char * argv[])
{
#autoreleasepool
{
ClassA * a;
a = [[ClassA alloc] init];
ClassB * b;
b = [[ClassB alloc] init];
[b setX];
[b printX];
}
return 0;
}
The program prints the following:
x is equal to 100
isn't "x" a private instance variable and inaccessible by object "b", because "x" is declared in the implementation file of superClass "a" while "b" is a subclass?
The books says "instance variables that are to be accessed directly by a subclass must be declared in the interface section and not in the implementation section...Instance variables declared or synthesized in the implementation section are private instance variables and are not directly accessible by subclasses."
Really confused by this.
The methods setX and printX are public and visible and thus can be called on the instance of ClassB. Since they are public they can also be called by the ClassB, like this.
#implementation ClassB
- (void)fig {
[self setX];
}
#end
What can't be done is for ClassB to directly access the value x. Like this:
#implementation ClassB
- (void)foo {
NSLog(#"x is now %i", x);
}
#end
ClassB does not have direct access to x, but it has indirect access to x through the superclass methods. This indirect access is an object oriented programming concept known as encapsulation.
Ivars have #protected attribute by default, means subclasses can access them. To declare ivar as private, use #private attribute before ivar declaration:
#interface ClassA : NSObject
{
#private
int x;
}
If you declare your ivars in #implementation section, the only way for them to be visible to subclasses is to import .m file in your subclass, but your can't use them because they're private.
Or don't use ivars at all, since Objective-C properties now create ivars automatically. If you need a private property, you can declare it via anonymous category in .m file like this:
#interface MyClass ()
#property (nonatomic) NSInteger x;
#end
UPDATE:
I think I understand what's confusing you. Public and protected ivars are inherited by subclasses and can be accessed directly as instance variables of subclass, no need to use accessor methods from a subclass.

How to simulate protected properties and methods in objective-c [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Protected methods in objective-c
The way to declare private properties is simple.
You declare that in extension that's declared in .m files.
Say I want to declare protected properties and access it from the class and subclass.
This is what I tried:
//
// BGGoogleMap+protected.h
//
//
#import "BGGoogleMap.h"
#interface BGGoogleMap ()
#property (strong,nonatomic) NSString * protectedHello;
#end
That one is compile. Then I added:
#import "BGGoogleMap+protected.h"
#implementation BGGoogleMap ()
-(NSString *) protectedHello
{
return _
}
#end
Problem starts. I can't implement class extension outside the original .m files it seems. Xcode will demand something inside that bracket.
If I do
#import "BGGoogleMap+protected.h"
#implementation BGGoogleMap (protected)
-(NSString *) protectedHello
{
return _
}
#end
I cannot access the ivar of _protectedHello declared in BGGoogleMap+protected.h
Of course I can use regular category rather than extension, but that means I can't have protected properties.
So what should I do?
The Objective-C Programming Language says this:
Class extensions are like anonymous categories, except that the methods they declare must be implemented in the main #implementation block for the corresponding class.
So you could just implement your class extension's methods in the class's main #implementation. That is the simplest solution.
A more complicated solution is to declare your “protected” messages and properties in a category, and declare any instance variables for that category in a class extension. Here's the category:
BGGoogleMap+protected.h
#import "BGGoogleMap.h"
#interface BGGoogleMap (protected)
#property (nonatomic) NSString * protectedHello;
#end
Since a category cannot add an instance variable to hold protectedHello, we need a class extension also:
`BGGoogleMap_protectedInstanceVariables.h'
#import "BGGoogleMap.h"
#interface BGGoogleMap () {
NSString *_protectedHello;
}
#end
We need to include the class extension in the main #implementation file so that the compiler will emit the instance variable in the .o file:
BGGoogleMap.m
#import "BGGoogleMap.h"
#import "BGGoogleMap_protectedInstanceVariables.h"
#implementation BGGoogleMap
...
And we need to include the class extension in the category #implementation file so that the category methods can access the instance variables. Since we declared the protectedHello property in a category, the compiler will not synthesize the setter and getter method. We have to write them by hand:
BGGoogleMap+protected.m
#import "BGGoogleMap+protected.h"
#implementation BGGoogleMap (protected)
- (void)setProtectedHello:(NSString *)newValue {
_protectedHello = newValue; // assuming ARC
}
- (NSString *)protectedHello {
return _protectedHello;
}
#end
Subclasses should import BGGoogleMap+protected.h to be able to use the protectedHello property. They should not import BGGoogleMap_protectedInstanceVariables.h because the instance variables should be treated as private to the base class. If you ship a static library without source code, and you want users of the library to be able to subclass BGGoogleMap, ship the BGGoogleMap.h and BGGoogleMap+protected.h headers, but don't ship the BGGoogleMap_protectedInstanceVariables.h header.
I wish I could tell you otherwise but you just can't. See this question for more information: Protected methods in Objective-C.
I am not sure, what you want to do? Something Hacking or Cracking of Data Abstraction out of OOPS concept?
Extensions are used to add properties. You have successfully added private property as in
#import "BGGoogleMap.h"
#interface BGGoogleMap ()
#property (strong,nonatomic) NSString * protectedHello;
#end
What are you doing in this ?
#import "BGGoogleMap+protected.h"
#implementation BGGoogleMap ()
-(NSString *) protectedHello
{
return _
}
#end
You have extended a class, now you are again implementing same class !!! Twice!!! And category only comes with .h file. I guess you are creating yourself a .m file, that not acceptable.
Private properties cant be accessed outside the class, it can be accessed only from the base class or subclass. That is what the error is.
I can't implement class extension outside the original .m files it seems.
Yes this is abstraction and data hiding of Objective-c !!!

iOS - how do I create a "utility" class that all my controllers can call

I am new to iOS and obective-c so I am not too sure how to best accomplish this seemingly simple task.
What I want is to make a class that looks like this in pseudocode:
class UtilityClass
{
// Have a method that I can pass parameters to
String doCalculation ( String art1 , String arg2 )
{
return arg1 + arg2;
}
}
My uncertainty is:
1) xCode seems to be inclined to lay out my file structure in a relatively flat way. So should I make a utils directory and have this file be under utils/fileName ? Usually I am kind of used to having at least some src directory, but so far I have not been prompted by anything to create one.
2) How do I import and call this class/function from my controllers?
Thanks,
Alex
Just create a new group called Utilities, and then create your class inside it. Like,
utils.h
utils.m
Later in your ViewController's header file just add.
#import "utils.h"
if this utils class is used by many controllers in very fat project then, find a file called, Should be inside supporting files group.
YourAppName-Prefix.pch
In that file you have a code block like this,
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#endif
Just edit this block and add your utils.h reference here, In this way your entire project can create utils object without explicitly importing into their own header.
Edit like this.,
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "utils.h"
#endif
First of all create a new File in Xcode and uncheck xib file. Name the Project as you like . and extend it from NSObject .
for creating static method you have to replace function starting - to + like
interface. class
#interface Utility : NSObject
+ (int)getNumber;
+ (void)setNumber:(int)number;
#end
.m class
#import "Utility.h"
#implementation Utility
static int number = 1;
+ (int)getNumber {
return number;
}
+ (void)setNumber:(int)newNumber {
number = newNumber;
}
+ (id)alloc {
[NSException raise:#"Cannot be instantiated!" format:#"Static class 'ClassName' cannot be instantiated!"];
return nil;
}
#end
call it in any other ViewController like
NSLog(#"number = %d", [Utility getNumber]);
[Utility setNumber:3];
NSLog(#"number = %d", [Utility getNumber]);
for details..
Where you store the files is up to you, just make sure XCode knows where to find them. The class itself should be made like any other Objective C class, just make it inherit from NSObject instead of one of the graphical classes:
// MyClass.h
#interface MyClass : NSObject {
int instanceVar;
}
#property (nonatomic, assign) int property;
#end
// MyClass.m
#import "MyClass.h"
#implementation MyClass
#synthesize property;
-(id) init {
...
}
-(int) function {
...
}
#end
To use the class in another file, just import the header like any other class
#import "MyClass.h"

how to make a single method in a class to private in Objective-c?

how to make a single method in a class to private in Objective-c?
There's no concept of private methods in Objective-C. What you can do, however, is obmitting the method in the header file and adding a category in a private file.
Usually this is down like this:
#interface MyObject : NSObject {
// ivars
}
// public methods
#end
// usually in a seperate file
#interface MyObject ()
// private methods
#end
An empty name for a category means that it's a class extension, this tells the compiler that the method is required in the main implementation block.
You can't strictly speaking create private methods in Objective-C; but you can create a category in the file containg the implementation (MyClass.m), hiding it from the header file (MyClass.h).
//MyClass.h
#import <Foundation/Foundation.h>
#interface MyClass : NSObject {
}
#end
Implementation file:
//MyClass.m
#interface MyClass ()
- (void)myPrivateMethod;
#end
#implementation MyClass
- (void)myPrivateMethod {
return;
}
#end
Objective-C doesn't support private methods natively by design.
However, you can achieve private method control by using "class extensions" (anonymous categories).
The basic idea is to declare a class extension with your private methods inside the implementation file for your class (not its header), but outside of your #implementation block. You can then implement the methods and no outside class will be able to see them. Like this:
#interface MyClass ()
- (void)myPrivateMethod;
#end
#implementation MyClass
- (void)myPrivateMethod
{
//implementation goes here
}
-(void)someOtherMethod
{
[self myPrivateMethod];
}
#end
Using a class extension forces you to implement the methods in the main #implementation block and requires that they are implemented (much like as if they were declared in the main #interface block in the header).
Unfortunately, due to Objective-C's dynamic nature, this won't actually prevent those methods from being called by other classes. They will get a warning telling them that the class may not respond to the message, but at runtime it will work. The only thing this gives you is the ability to hide the methods from other programmers.
You can't. Only instance variables can be marked as private.
Though there are ways to do something equivalent to private methods.
The general idea is that you don't declare the private method in your header but in your implementation file.
Therefore, if you'd want to have a public (myPublicMethod) and private (myPrivateMethod) method, you're header could look like this:
#interface MyClass {
}
- (void)myPublicMethod;
#end
And then you have three options for your implementation file:
1.
Don't declare the method in any #interface section and just make sure it's implemented before it's being used in the #implementation section.
#implementation MyClass
- (void)myPrivateMethod { }
- (void)myPublicMethod {
[self myPrivateMethod];
}
#end
2.
Use an anonymous category in your implementation file to declare the private methods and implement them in the main #implementation block.
#interface MyClass ()
- (void)myPrivateMethod;
#end
#implementation MyClass
- (void)myPrivateMethod { }
- (void)myPublicMethod {
[self myPrivateMethod];
}
#end
3.
Use a regular category in your implementation file and implement the private methods in a separate #implementation block.
#interface MyClass (PrivateMethods)
- (void)myPrivateMethod;
#end
#implementation MyClass (PrivateMethods)
- (void)myPrivateMethod { }
#end
#implementation MyClass
- (void)myPublicMethod {
[self myPrivateMethod];
}
#end