In an Objective-C class I have a #private ivar that uses an enum of the form:
typedef NS_ENUM(NSInteger, PlayerStateType) {
PlayerStateOff,
PlayerStatePlaying,
PlayerStatePaused
};
However, I include this definition in the header file of that class (since it's used in it). This effectively makes the type public, which isn't what I intended. How can I make this enum type private?
Adding my comment as an answer.
You can add this in your .m class so that while importing it is not shared with other classes. You can just add it below your import statements. If the params of this type are used only in this .m class, you can declare that also in this .m file.
Your .m class will look like,
typedef NS_ENUM(NSInteger, PlayerStateType) {
PlayerStateOff,
PlayerStatePlaying,
PlayerStatePaused
};
#interface ViewController () //Use an extension like this in .m class
#property (nonatomic) PlayerStateType param;
#end
Define it in .m file & declare your privare ivar in controller category in .m file. To know about controller category take a look at Difference between #interface definition in .h and .m file.
Related
I have been trying with no success the following structure:
ClassA.swift
class ClassA:NSObject{
var varA = ""
}
then I have a ClassB.h and ClassB.m (Objective c) and I am not able to define "Project-Swift.h" in the .h file so i import it into the .m
#interface ClassB()
#property ClassA *myClassA;
#end
and
#synthesize myClassA = theAClass;
The problem comes when I try
class ClassC:NSObject{
let theClassAFromC = ClassB.myAClass
}
I get an error message Value of type 'ClassB' has no member 'theClassA'
Add your objc header to bridging header
In your objc header use #class notation for your swift class, e.g. #class ClassA;, instead of import "Project-Swift.h" file. You can import that one in your objc implementation file.
Don't forget that you cannot access non-static property of objc class the way you're declaring. Instead, initialize your ClassB object in your swift class and access it's property when needed. For instantiating the ClassA object you can use dependency injection in ClassB
As part of the convenience, use #objc declaration for your Swift classes accesible to objc runtime
try to search with keyword "Bridging-Header" and then add
#import "ClassB.h"
That does not work in my case.
adding ClassB.h in my Bridge File makes properties from .h Visible But not the the properties in my .m file. If i add Class.m In my header file then Module-Swift.h is not found
Suppose I have the following
FileName : DBManager.h
#import <Foundation/Foundation.h>
#interface DBManager : NSObject
//Notice no method is declared here
#end
Now its implementation file looks like this
FileName: DBManager.m
#import "DBManager.h"
#interface DBManager()
+ (DBManager*) SomeMethod;
#end
#implementation DBManager
+ (DBManager*) SomeMethod
{
....
return SomePtr;
}
#end
Now in some other class method if I do the following
[DBManager SomeMethod] ; //Error No known class method for selector 'SomeMethod'
However if SomeMethod is declared inside the .h file inside of category then this works fine. I wanted to know if this was a limitation of categories that the methods are not visible to other classes ?
First, #interface DBManager() is not a category, it's a class extension. There's no identifier between the parentheses.
Second, the issue isn't visibility based on whether the method is declared in a class, category, or class extension, it's whether it was declared in the same translation unit.
A translation unit is a source file after the preprocessor has included/imported the header files (or whatever other files have been included/imported).
The error is telling you that the declaration of +SomeMethod was not declared in the translation unit. If it were, there'd be no error, regardless of whether it were declared in the class interface, a category, or a class extension.
It follows that if you declare the interface of a category in a header file and include the header file in a source file, you can use the methods declared by that category in that source file.
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 !!!
I've noticed a variety of #interface declarations for Objective-c classes. I'd like to understand why developers declare #interface in the following ways:
// in the .h file
#interface MyClass : NSObject
// ...
#end
// in the .m file (what's the purpose of the parens?)
#interface MyClass ()
// more property declarations which seem like they can go in the .h file
#end
// again in the .m file (what's the purpose of private?)
#interface MyClass (Private)
// some method declarations
#end
This is just a normal class interface, inheriting from NSObject, where you declare ivars, properties and methods
// in the .h file
#interface MyClass : NSObject
// ...
#end
The following two are categories, which allow you to add methods to a class. It is not a subclass however (do not declare a method with the same name, as you won't be able to access the original one). If you have a named category of the interface (like #interface MyClass (Private)), then the implementation should be provided in #implementation MyClass (Private), in the case of unnamed categories (also called extensions), the implementation can be provided as usual. Note that extensions also allow you to add ivars to the class while (named) categories do not.
// in the .m file (what's the purpose of the parens?)
#interface MyClass ()
// more property declarations which seem like they can go in the .h file
#end
// again in the .m file (what's the purpose of private?)
#interface MyClass (Private)
// some method declarations
#end
It is used to declared private methods.
This response explain this in details: What are best practices that you use when writing Objective-C and Cocoa?
What ever goes in the .m file is private. the parens are for categories so you can segment your code into categories to make it more readable. because the code is in .m and private, they called the category Private.
Normally we use
#interface interface_name : parent_class <delegates>
{
......
}
#end
method in .h file and in .m file we synthesis the properties of variables declared in .h file.
But in some code, this #interface.....#end method is kept in the .m file also. What does it mean? What is the difference between them?
Also give some words about getters and setters for the interface file that is defined in .m file...
It's common to put an additional #interface that defines a category containing private methods:
Person.h:
#interface Person
{
NSString *_name;
}
#property(readwrite, copy) NSString *name;
-(NSString*)makeSmallTalkWith:(Person*)person;
#end
Person.m:
#interface Person () //Not specifying a name for the category makes compiler checks that these methods are implemented.
-(void)startThinkOfWhatToHaveForDinner;
#end
#implementation Person
#synthesize name = _name;
-(NSString*)makeSmallTalkWith:(Person*)person
{
[self startThinkOfWhatToHaveForDinner];
return #"How's your day?";
}
-(void)startThinkOfWhatToHaveForDinner
{
}
#end
The 'private category' (the proper name for a nameless category is not 'private category', it's 'class extension') .m prevents the compiler from warning that the methods are defined. However, because the #interface in the .m file is a category you can't define ivars in it.
Update 6th Aug '12: Objective-C has evolved since this answer was written:
ivars can be declared in a class extension (and always could be - the answer was incorrect)
#synthesize is not required
ivars can now be declared in braces at the top of #implementation:
that is,
#implementation {
id _ivarInImplmentation;
}
//methods
#end
The concept is that you can make your project much cleaner if you
limit the .h to the public interfaces of your class, and then put
private implementation details in this class extension.
when you declare variable methods or properties in ABC.h file , It
means these variables properties and methods can be access outside the
class
#interface Jain:NSObject
{
NSString *_name;
}
#property(readwrite, copy) NSString *name;
-(NSString*)makeSmallTalkWith:(Person*)jain;
#end
#Interface allows you to declare private ivars, properties and
methods. So anything you declare here cannot be accessed from outside
this class. In general, you want to declare all ivars, properties and
methods by default as private
Simply say when you declare variable methods or properties in ABC.m
file , It means these variables properties and methods can not be
access outside the class
#interface Jain()
{
NSString *_name;
}
#property(readwrite, copy) NSString *name;
-(NSString*)makeSmallTalkWith:(Person*)jain;
#end
you can even create other classes in .m file,
for instance other small classes which inherit from the class declared in .h file but having some slight different behaviour.
You could use this in a factory pattern