0

Note: This question doesn't have anything to do with the language used, i.e, Swift/ Objective-C

I can't seem to get my head around how such a problem can be solved. How an asynchronous method which processes data continuously ,return back these processed values to a function?

Example Class structure of -> ClassName

  1. A method named -(void)infoCallBack , this is the method you have to call to get returns continuously.
  2. Inside -(void)infoCallBack -> an asynchronous method [self startRecording]is there, which does audio recording asynchronously using AudioQueues by using a callback method void AudioInputCallback(..param..).
  3. Finally Inside void AudioInputCallback(..param..) -> a method -(void) processAudio is there, which continuously processes data and gives us an integer number.

How to call a method like [ClassName infoCallBack] in such a way that we keep getting all these processed integers continuously?


Edit : I have searched SO, and came across completion handler blocks : although completion handlers only return a value once after completionHandler() is called. Moreover, another problem in this method was how to pass around this completionHandler to multiple methods in the className Structure as shown.

I came across delegates, it said that when distinct values are being returned continuously and state of something changes, then we should call a delegate. But I was stuck at how I would return values after I call the function infoCallBack from ClassName, i.e, [ClassName infoCallBack] which continuously can feed the person calling this function with the values being processed.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Shivansh Jagga
  • 1,541
  • 1
  • 15
  • 24

2 Answers2

1

Actually I don't completely understand your question but I will give you the answer in my understanding

In my opinion, you can use block to handle process update.

typedef void (^ProcessHandlerBlock) (NSInteger i);

- (void)infoCallBackWithProcessHandlerBlock:(ProcessHandlerBlock)block {
  [self startRecordingWithProcessHandlerBlock:(ProcessHandlerBlock)block];
}

- (void)startRecordingWithProcessHandlerBlock:(ProcessHandlerBlock)block {
  [self audioInputCallbackWithParam1:@"1" param2:@"2" processHandlerBlock:(ProcessHandlerBlock)block];
}

- (void)audioInputCallbackWithParam1:(id)param1 param2:(id)param2 processHandlerBlock:(ProcessHandlerBlock)block {
  [self processAudioWithProcessHandlerBlock:(ProcessHandlerBlock)block];
}

- (void)processAudioWithProcessHandlerBlock:(ProcessHandlerBlock)block {
  // Assume this is your process method callback
  [NSTimer scheduledTimerWithTimeInterval:1.f repeats:YES block:^(NSTimer * _Nonnull timer) {
    // After receive integer, pass it to block.
    block(1);
  }];
}

When you want to use them, call

[self infoCallBackWithProcessHandlerBlock:^(NSInteger i) {
  NSLog(@"%l", i); // Do whatever you want here
}];

Inside the completion block of infoCallBackWithProcessHandlerBlock method, you can use result integer to do what you want.

trungduc
  • 11,926
  • 4
  • 31
  • 55
  • I upvoted your answer, although it doesn't give a complete insight, but thank you. I'll explain in a better manner . My asynchronous function does recording and keeps processing the recording and continuously computes values. As soon as it computes a value I want it to return this value. Now , it can't be done with a completion handler because it just doesn't compute one value and returns it and stops there. It keeps computing and returning many values. – Shivansh Jagga Nov 19 '17 at 11:35
  • @ShivanshJagga i have updated my answer, you can check again – trungduc Nov 19 '17 at 14:05
  • Hi I will give the correct answer in a while. I finally got it using delegate. However, I'll still look forwardif there is a completionHandler solution. I'll post it and edit out my question after a few hours. – Shivansh Jagga Nov 19 '17 at 14:12
  • @ShivanshJagga you should check it. I tried and `block` called each second. I am very eager to see an answer with `delegate` ;) – trungduc Nov 19 '17 at 14:16
1

I can't seem to get my head around how such a problem can be solved.

From the rest of what you've written I suspect you can get your head around this, you probably just need a rest. You've found the answer already without realising...

I have searched SO, and came across completion handler blocks : although completion handlers only return a value once after completionHandler() is called.

The phrase "completion handler block" might be written as "a block used as a completion handler" - a block is just a block, you can call it as many times as needed, store it in variables, etc. While a completion handler is typically only called once a, say, result reporter might be called multiple times.

Moreover, another problem in this method was how to pass around this completionHandler to multiple methods in the className Structure as shown.

A block is a kind of object and like other objects your class instance might need to use in many methods it doesn't need to be passed around but can be stored in an instance variable. For ease of use first declare your a shorthand for the block type, say:

typedef void (^SampleHandler)(int i);

then declare a suitable instance variable:

@implementation ClassName
{
   SampleHandler mySampleHandler;
}

now use this like any other instance variable - initialise it (mySampleHandler = ...;), use it to call the block (mySampleHandler(42);`)

I came across delegates, it said that when distinct values are being returned continuously and state of something changes, then we should call a delegate. But I was stuck at how...

Blocks and delegates are often used for similar purposes, you can use either to solve your problem in essentially the same way - store the block/delegate reference in an instance variable, call the block/delegate method to return a value. You just have to decide which suits your use case best:

  • A block is a function. A block is created inline, usually at the call site, and can reference (and sometimes modify) variables in the environment where it is created. Like any function it is (usually) a single-operation thing - pass argument(s), produce a side-effect/return a result.

    • A delegate is an object. Like any other object it requires an interface/implementation. Like any object it can have multiple methods, so its a multi-operation thing.

In your case - returning a value - a block is probably the best option, but you need to decide.

HTH

CRD
  • 52,522
  • 5
  • 70
  • 86
  • I wish I could up vote you multiple times. You were right, I needed rest. and I did get the right answer which I'll be posting soon enough. :) Also, I'll be grateful if you could help with this, people upvoted, so I'm guessing it's a good question : https://stackoverflow.com/questions/47278081/ios-header-file-notation-error-for-keeping-directory-structure-in-frameworks – Shivansh Jagga Nov 20 '17 at 12:51