1

Just to calm my curiosity,

Lets say, I am creating a project/framework in Objective-C for iOS with XCode and I want to add a method which will further visible to a particular project and hidden to other projects.

If this does not give you a idea of my thoughts, Lets say I am creating a XCode project which is further divided as three different projects(say A, B, C). When I start actual implementation, I want all of the class methods from project A visible to project B but wants to hide them from project C.

Is there a way to implement something like this in iOS Objective-C/Swift?

Pankaj Gaikar
  • 2,357
  • 1
  • 23
  • 29
  • i developed custom frameworks in both language(Objective-c , Swift). and this is fact that we can't make different scope(public,private,protected) for an unique method. – Abhimanyu Daspan Jan 27 '17 at 13:44
  • 1
    I guess you can use extensions e.g. something like here http://stackoverflow.com/questions/19095716/hiding-properties-from-public-framework-headers-but-leaving-available-internall – Mindaugas Jan 27 '17 at 13:50
  • 1
    Yes, extension will work for you. – Anoop Nyati Jan 30 '17 at 07:35

3 Answers3

1

I developed custom frameworks in both languages(Objective-c , Swift). and this is fact that we can't make different scope(public,private,protected) for an unique method "(public func a(){})". so whatever scope we are giving any particular method inside framework it will remain same for all (A,B,C) projects those want to use it.

Abhimanyu Daspan
  • 1,095
  • 16
  • 20
  • 1
    Which I always thought was a bit odd. I always believed that visibility should not be part of the *language* but the environment. And that you should be able to generate any "header" you want, not just a single one. I seem to recall Dylan did that, so you could have a internal-use-only header and a public header for the same code. – Maury Markowitz Jan 27 '17 at 18:26
1

As mentioned by Mindaugas in one of the comment, you can use class extension for this purpose.

Class extensions are often used to extend the public interface with additional private methods or properties for use within the implementation of the class itself.

For example .h contains

@interface Person : NSObject
@property(nonatomic, copy) NSString *firstName;
@property(nonatomic, copy) NSString *lastName;

- (void)setDateOfBirth:(NSDate *)date;
@end

.m will have

@interface Person()
@property(nonatomic, strong) NSDate *dateOfBirth;

- (void)calculateMyAge;
@end

@implementation Person
- (void)setDateOfBirth:(NSDate *)date
{
    self.dateOfBirth = date;
    //Some more code goes here
}

- (void)calculateMyAge
{
    //Do something with self.dateOfBirth here
}

@end

Here we made @property dateOfBirth and a method calculateMyAge private to the interface Person and implemented it under @implementation block.

@interface Person()

is nothing but class extension (or nameless category or anonymous category).

Now coming back to original question, you want to make it public to your framework and private for outside world.

Let's say you want Person class to have a method that will return full name (first and last name appended). However you want for internal purpose of your framework.

You can create a separate header file for this.

Person+InternalHeader.h

which will have declaration for the method

@interface Person()
- (NSString *)fullName;
@end

You can import

#import "Person+InternalHeader.h"

into your Person.m file and under @implementation block you can implement body for the method.

@implementation Person
//other code
- (NSString *)fullName
{
    return [self.firstName stringByAppendingFormat:@" %@",self.lastName];
}
@end

You can always import Person+InternalHeader.h into your other classes and make use of fullName method.

Why extension and not category?

Extensions enable you to override the property or add new property to the existing parent class. Also you can always override the default behaviour of method defined in extension, in child class. With category, it simply adds the method to your existing object.

For example, lets there is class Doctor which inherits from class Person.

@interface Doctor : Person

Now you want the fullName method to return "Dr." prepended. You can simply override the fullName behaviour in your Doctor.m file.

@implementation Doctor
- (NSString *)fullName
{
    NSString *fullName = [super fullName];
    return [@"Dr. " stringByAppendingString:fullName];
}
@end
Anoop Nyati
  • 339
  • 2
  • 11
0

Depending on what you mean by project, you can selectively import headers to affect the visibility of methods.

If Project A has a class that implements a class method:

@implementation Antelope

+ (void)leap
{
    // Jump into the air
}

@end

Then you can put the declaration of that method into a category in its own header:

// Antelope+Leaping.h

#import "Antelope.h"

@interface Antelope (Leaping)

+ (void)leap;

@end

And the compiler will only allow you to write [Antelope leap] in files that import that specific header. Project A doesn't have any control over this, of course: it's up to Projects B and C to do the imports.

The method will still be a member of the class, and it's possible to work around the compiler, but the method won't be "visible" where the declaration is not present.

jscs
  • 63,694
  • 13
  • 151
  • 195
  • we are creating Antelope class in to Project A so here we stuck on project base approach but the question was related to "framework based method scope for for n number of projects (A,B,C..n) with access scope " i think which is not possible. – Abhimanyu Daspan Jan 28 '17 at 05:30