Static library callback - objective-c

I have a static library that is currently sending responses using NSNotificationCenter. But I feel like delegates would be a better solution. The problem is how do I call the delegate methods when I do not know their headers yet. Im not sure how to implement the stuff that is not up to me when the library is in use.
So is there a good of allowing the user to create their own methods and the library calling them when they are needed?

Delegates are often communicated with by you declaring a protocol which specifies the set of callbacks.
#protocol MONImageGeneratorObserver <NSObject>
#required
// called when an image has been generated
- (void)generatedImageWasSavedToURL:(NSURL *)pURL;
- (void)imageGenerationDidComplete;
#end
Then you can tell your client the interface they must implement by specifying the protocol in your APIs:
- (void)setImageGeneratorObserver:(NSObject<MONImageGeneratorObserver>*)pObserver;
Another good way to accomplish this is provide a parameter which is a block. You'll usually want to copy that block when you receive it. Then you don't need to know anything about the client's code.
Your API should be very specific:
that you copy it
on which thread the block will be performed
#interface MONObject : NSObject
+ (void)performAsynchronousLoadWithSuccessfulCallback:(void(^)(void))pSuccess errorCallback:(void(^)(NSError *))pError;
#end
#implementation MONObject
+ (void)performAsynchronousLoadWithSuccessfulCallback:(void(^)(void))pSuccess errorCallback:(void(^)(NSError *))pError
{
if (random()%2) {
// load succeeded!
pSuccess();
}
else {
// load failed = =
NSError * e = ...;
pError(e);
}
}
#end
In both cases, you specify the interface and do not need to see their headers in your implementation. They can call their own methods in the block body or in their definitions of MONImageGeneratorObserver callbacks.

Related

Prevent instantiation of readonly objects from framework

I am currently in the process of creating an objective c framework for iOS to help facilitate the interaction between an API and a developer. As part of this, I return various arrays of readonly objects that a developer can use to display information to the user. However, I would like to ensure that the objects displayed to the user come only from the framework and can not be instantiated by the developer using the framework.
My current implementation uses a custom constructor initializer that takes JSON from the api to instantiate itself. The only way that I am aware of accessing my custom constructor initializer is by putting its definition in the header file which makes it not only accessible to myself, but also the developer. I am aware that I can throw an inconsistency exception when the user tries to use the default constructor initializer, -(id)init;, but I can not stop them from creating their own JSON string and calling my custom constructor initializer.
Am I taking the correct approach to securing my private framework from interference from the developer using it? How else can I get around this to ensure the validity of data in these objects?
Source: Is it possible to make the -init method private in Objective-C?
You are correct that Objective-C doesn't allow for truly private methods by it's very nature, due to its dynamic dispatch system. However, assuming your question is not about true security, rather simply making it difficult to use the framework in an incorrect way, you have a few options.
A simple, common solution would be to put the declarations for methods you don't want to expose publicly in a category in a separate header file. You can still put these methods' implementations in the main implementation file for the class. So, a header with something like this:
// MyClass+Private.h
#interface MyClass (Private)
- (void)aPrivateMethod;
#end
Then, in your own source files where you need to access those private methods, you simply import MyClass+Private.h.
For a framework, you can set each header file to be Public or Private. Private headers will not be copied into the framework bundle, and therefore won't be visible to users of the Framework. You do this by opening the Utilities pane in Xcode (the right-side slide out pane), selecting the header in question, then choosing Private in the second column of the relevant row under "Target Membership".
Based on Andrew Madsen's solution, I ended up using was to have two different header files for each object; One that was public, and one that was private. The public header contains only the information needed by the developer to access the read only properties. Then my private header imports the public header and also contains a category with all the method calls I need to use within the SDK (including the initializer). I then import the private header into my implementation. The structure looks like this:
Public Header MyObject.h
#import <Foundation/Foundation.h>
#interface MyObject : NSObject
#property (nonatomic, retain, readonly) NSString *myValue;
#end
Private Header MyObject+Private.h
#import "MyObject.h"
#interface MyObject (Private)
+(MyObject*)MyObjectFromJSONString:(NSString*)JSONString;
-(id)initWithJSON:JSONString:(NSString*)JSONString
#end
Private Implementation MyObject.m
#import "MyObject+Private.h"
#implementation MyObject
#synthesize myValue = _myValue; //_myValue allows local access to readonly variable
- (id)init {
#throw [NSException exceptionWithName:NSInternalInconsistencyException reason:#"-init is not a valid initializer for the class MyObject" userInfo:nil];
return nil;
}
+(MyObject*)MyObjectFromJSONString:(NSString*)JSONString;
{
return [[MyObject alloc]initWithJSON:JSONString];
}
-(id)initWithJSON:JSONString:(NSString*)JSONString
{
self = [super init];
if(self){
//parse JSON
_myValue = JSONString;
}
return self;
}

Cocoa plugin pattern

I have a plugin architecture for my desktop app. I've implemented it in a fairly standard way using Apple's code loading guide.
I have a single protocol which defines all the methods an instance of the plugin can or should respond to.
The only problem is this protocol defines around 80 methods. Only about 10 of these methods are compulsory and the rest are optional. Some plugins will implement all 80 methods, whereas others will only implement the basic 10.
The usual way for a plugin bundle to tell its host application which class to instantiate is via the NSPrincipalClass key in its Info.plist file. This is a single key so only a single class can be instantiated.
The plugin protocol is a single file and its expected that it will be used by this single class.
My question is: what is the best way of splitting up the functionality inside this single protocol into perhaps multiple protocols, whilst at the same time allowing the plugin writer to have a more flexible implementation?
Currently my existing plugins have the following in their principal class:
- (BOOL)respondsToSelector:(SEL)selector {
return [self forwardingTargetForSelector:selector] ? YES : NO;
}
- (id)forwardingTargetForSelector:(SEL)selector {
id target = nil;
if ([self.instanceOne respondsToSelector:selector]) {
target = self.instanceOne;
} else if ([self.instanceTwo respondsToSelector:selector]) {
target = self.instanceTwo;
} else if ([self.instanceThree respondsToSelector:selector]) {
target = self.instanceThree;
}
return target;
}
But rather than imposing it upon the plugin writer to define an ad hoc system like this, I would like the application's plugin framework to accomodate a more flexible solution.
If you can divide your 80 methods into sensible chunks of functionality, you could split them up into several protocols (FooProtcol, BarProtocol, etc.) and define optional properties that return references to objects that implement them in your primary protocol. For example:
#protocol PluginPrimaryProtocol <NSObject>
#required
/* ... */
#optional
#property (readonly) id<FooProtocol> fooDelegate;
#property (readonly) id<BarProtocol> barDelegate;
/* ... */
#end

iPhone SDK: Accessing methods in other classes

In my iPhone application I have multiple class files, I have my main application's class files, then I have my UIView class files. I have a simple -(void) method declared in my UIView class files, how can I access it from my main applications class files?
A bit more detail: In my application a video is played, when this video finishes playing a notification is sent and actions are preformed, which I have already successfully set up, however when the movie finishes I would like a method declared in another class file to be preformed. If the method was declared in the same class file I would simply use this code: [self mySimpleVoidMethod]; But obviously this doesn't work If the method is declared in a different class file. I believe it is possible to access a method declared in a different class file, but I just haven't got a clue about how to do it. Sorry if I'm using completely incorrect terms to name things. But I am relatively new to programming all together.
You've got a couple of options, depending on your setup. Here are a few:
1) Add a reference to the class with the function (the callee) as a property in the caller's class:
Caller.h
#interface Caller : SomeObject {
Callee *myCallee;
...
}
#property(nonatomic, retain) Callee *myCallee;
Caller.m
#synthesize myCallee;
-(void)someAction {
[myCallee doSomething];
}
Something that sets up Caller after initializing both classes:
caller.myCallee = callee;
2) Use another notification event, like it looks like you already know how to do.
3) Use a protocol if you've got a bunch of different classes that Caller might need to call that all support the same method:
DoesSomething.h
#protocol DoesSomething
-(void)doSomething;
#end
Callee.h
#interface Callee : NSObject<DoesSomething> { // NSObject or whatever you're using...
...
}
-(void)doSomething;
Caller.h
#interface Caller : SomeObject {
id<DoesSomething> *myCallee;
...
}
#property(nonatomic, retain) id<DoesSomething> *myCallee;
... Then as per example 1.
4) Use performSelector to send a message to the class.
Caller.h
#interface Caller : NSObject {
SEL action;
id callee;
}
-(void)setupCallbackFor:(id)target action:(SEL)callback;
Caller.m
-(void)setupCallbackFor:(id)target action:(SEL)callback {
callee = target;
action = callback;
}
-(void)someAction {
if([callee respondsToSelector:action]) {
[callee performSelector:action];
}
I'm sure there are other ways, and there are pros and cons to each of these, but something in there should fit your needs and/or give you enough to scan the documentation to fill in any gaps...
I did a blog post a few weeks ago that outlines one way to do this. It is similar to the previous answers, and includes some sample code you can download and look at. It is based on using table view controllers, but you should be able to adapt the ideas to your application without too much difficulty.
Passing values and messages between views on iPhone
You'll need an instance of the other class, accessible from the code that runs when the movie finishes. Often, this is accomplished by storing an instance of the other class as a field in the class, set either via a "setter", or during construction. You could also use key-value observing, watching a key representing the playstate of the movie; an instance of the other class can register to observe the changes to this key.
Specifically for patterns using UIView, your UIViewController for the view will have access to it (through the view method). If your "main application's class files" have a pointer to the controller - which they probably will, setup via Interface Builder - then that's an easy way to get to a UIView instance.

objective-c delegate

i working with geocoding at the moment. The geocoding service allways works with delegates.
So let's say, I've got a
AskingClass and AnsweringClass(geocoding)
The AskingClass calls a function in the AnsweringClass to return the adress of the current location.
AnsweringClass should handle and capsulate the geocoding stuff. My Problem is, with all these delegates, I do not manage to come back to the orginal function, which the asking class has called. So I cannot give easily the adress back:
AskingClass.Adress= [AnsweringClass giveAdress];
I managed it, doing it with delegates, so the result comes back in a delegate function (somewhere) in the askingClass. But I'm not happy with that. It's seems oversized and complex.
with best regards
Klaus-Dieter
It is unclear why you are using a delegate pattern at all. Why not just use straight up classes?
Something like this (assuming that you are using a PCH file for your header files or otherwise importing 'em as needed):
AnsweringClass.h
#interface AnsweringClass:NSObject
- (MyAnswer *)answerThisDude;
#end
AskingClass.h
#class AnsweringClass; // just in case you including AskingClass.h before AnsweringClass.h
#interface AskingClass : NSObject
// {
// declare the ivar if you need support for 32 bit "classic" ABI
// AnsweringClass *theThingThatAnswers;
// }
#property(retain) AnsweringClass *theThingThatAnswers;
#end
Then you can do this:
AskingClass.m
#implementation AskingClass
#synthesize theThingThatAnswers;
- (void) setUpMyStuff // probably invoked by your designated initializer or app launch handler
{
self.theThingThatAnswers = [AnsweringClass new];
MyAnswer *theFirstAnswer = [self.theThingThatAnswers answerThisDude];
}
// don't forget a -dealloc if you aren't running GC'd
#end
No delegation necessary.

Is it possible to declare a method as private in Objective-C?

Is it possible to declare a method as private in Objective-C?
If you're working in Objective-C 2.0, the best way to create methods that are "hard" for others to call is to put them in a class extension. Assuming you have
#interface MyClass : NSObject {
}
- (id)aPublicMethod;
#end
in a MyClass.h file, you can add to your MyClass.m the following:
#interface MyClass () //note the empty category name
- (id)aPrivateMethod;
#end
#implementation MyClass
- (id)aPublicMethod {...}
- (id)aPrivateMethod {...} //extension method implemented in class implementation block
#end
The advanage of a class extension is that the "extension" methods are implemented in the original class body. Thus, you don't have to worry about which #implementation block a method implementation is in and the compiler will give a warning if the extension method is not implemented in the class' #implementation.
As others have pointed out, the Objective-C runtime will not enforce the privateness of your methods (and its not too hard to find out what those methods are using class dump, even without the source code), but the compiler will generate a warning if someone tries to call them. In general, the ObjC community takes a "I told you not to call this method [by putting it in a private class extension or category or just by documenting that the method is private] and you called it anyways. Whatever mess ensues is your fault. Don't be stupid." attitude to this issue.
No, any object can send any message to any other object. You can, however, put the method in a category that's part of the class's implementation file. That way, you'll get a "Class may not implement this method" warning if you try to call it anywhere else. That's the normal way of making a method "private."
There is nothing that will prevent the method being called (since objective-c is message based anything can be sent any message), but you can declare them outside of the header so they are not visible and the compiler will generate warnings if used.
This works for both class and instance methods.
E.g.
#import "SomeClass.h"
// Interface for hidden methods
#interface SomeClass (hidden)
+(void) hiddenClassMethod;
-(void) hiddenInstanceMethod;
#end
Note: Do NOT declare variables like this or they will become class-variables - e.g. only one variable will be used by all instances.
You can do so by using categories. I've got a fuller description in my answer to this SO question.
As has been said, you can't stop anyone sending a message to a selector, but by using categories you can reduce the visibility of these functions.
Also, you can have more than one category extending a class. So, by using informative category names you can group private functions into related blocks, improving the self-documenting nature of your code.
As others mentioned, you can't have code that's
a method, and
impossible to call from outside a class.
Folks have already pointed out that you can abandon point 2, and get a method that's hard-but-not-impossible to call. Alternatively, why not abandon point 1?
static id myPrivateMethod(MyObject *me, int arg1, id arg2) { ... }
Now the code can only be called from within same file. You don't get any of the magic private-member access you can get with a method, so this is by no means a perfect solution. But there's no better way to achieve privacy.
To implement hidden methods (instance and/or class)
// ===========================
// = File: SomeClass.m
// ===========================
#import "SomeClass.h"
// =================================
// = Interface for hidden methods
// =================================
#interface SomeClass (hidden)
-(void) hiddenInstanceMethod;
#end
// ================================
// = Implementation for SomeClass
// ================================
#implementation SomeClass
-(void) hiddenInstanceMethod
{
printf( "Hidden instance method\n" );
}
-(void) msg
{
printf("Inside msg()...\n");
[self hiddenInstanceMethod];//private method calling
}
#end
http://macdevelopertips.com/objective-c/private-methods.html
reffer this link it will be helpful .