0

I'm trying to start working on iOS development with Objective-c. I have a lot of experience with Java, so I try to do things in a Java way. Please help me to understand the correct way to code in Objective C.

I have the following interface in Java:

public interface MyInterface {
  void onSuccess(String successString);
  void onError(String errorMessage);
}

I will use it like this:

public static void main(String... args){
    MyInterface interface = new MyInterface() {
        @Override
        public void onSuccess(String successMessage) {
            // things happen here
        }

        @Override
        public void onError(String errorMessage) {

        }
    };
}

How do I convert this code to Objective C? I need to create an interface and pass an instance of this interface to another C method.

I've tried blocks(^), but it is acceptable only when I need to pass an object with only one callback. What is my approach to pass an object with two callback functions to a method?

4
  • 4
    Objective C is a somewhat different beast to Java. It's probably best not to approach it with the intention "to do things in a Java way". This post and this book might help you get started. Commented Jan 26, 2018 at 14:53
  • @AgiHammerthief, thanks for book reference. Can you advise me a way to pass interface reference to C function (blocks works fine, but not provide needed functionality) Commented Jan 26, 2018 at 15:11
  • 1
    Note that methods can use two block one in case of success, and another one in case of error, it's up to you to split it. Commented Jan 26, 2018 at 17:06
  • @Larme I have only one *void argument that i can pass as a handle, so i need to pass two blocks in one object reference Commented Jan 26, 2018 at 17:10

2 Answers 2

1

I have only one *void argument that i can pass as a handle, so i need to pass two blocks in one object reference

One way is to define a class with two instance variables of block type, one each for the success and error cases; an initialiser which takes values (blocks) and sets those instance variables; and two instance methods, one each for success and failure cases, which simply invoke the block referenced by the corresponding instance variable.

If you need the interface as other classes will implement it directly just make your new class conform to it as well.

Another way is to define your class with two block-valued properties, and use property references to obtain the blocks rather than methods to invoke them.

The tricky part comes when you pass your class instance as a void * and later cast it back to use the methods/properties. If you are using ARC you need to use a bridging cast in both directions and ensure your object stays alive until needed. You can achieve this by using a cast at the call site which transfers ownership of the object away from ARC, thus preventing ARC from releasing it; and a cast at the use site which transfers ownership back to ARC, so that after the appropriate method/property has been called ARC will clean up the object. You'll need to read up on bridging casts to do this; they are no more complicated to write than ordinary casts but you do need to understand the semantics.

Of course at this point, especially after manual memory management with bridging casts, you might decide to switch to a more Objective-C oriented model from your Java one. However the above is a standard technique for dealing with C functions which follow the void * context pointer model, and there is nothing wrong per se in using it when required.

HTH

Sign up to request clarification or add additional context in comments.

Comments

1

Your code is basically an example of delegation in Objective-C. You build it in two (or three, depends on how you want to count it) in Objective-C:

First, you create a protocol. Usually the delegating instance is passed as argument. This is for convenience reasons in some situation. So let's imagine a class Delegator.

@protocol MyDelegate
- (void)delegator(Delegator*)delegator didFinishWithSuccess:(NSString*)message;
- (void)delegator(Delegator*)delegator didFinishWithError:(NSString*)message;
@end

In Objective-C such a protocol is and only is a contract without any content. You add the content by creating a class that adopts the protocol (hence the contract):

@interface MyDelegate : NSObject < MyDelegate >
@end // You do not need to redeclare the methods.

@implementation MyDelegate
- (void)delegator(Delegator*)delegator didFinishWithSuccess:(NSString*)message
{
  …
}
- (void)delegator(Delegator*)delegator didFinishWithError:(NSString*)message
{
  …
}
@end

Then you can simply create an instance and pass it as delegate:

…
MyDelegate delegate = [MyDelegate new]; 
[delegator doSomethingWithDelegate:delegate];

The delegator stores its delegate and send appropriate messages to the delegate.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.