1

I apologize if my terminology isn't correct - I've been learning Objective C for just a few days, so I'm still a little unfamiliar.

I have a ViewController that has a progress bar (UIProgressView) hooked up with an IBOutlet using Xcode's storyboard "quick drag" functionality. The ViewController instantiates an object of a custom class I have written. It passes a message to a selector of that object that does a lengthy bit of work which takes about 15-20 seconds. I want to be able to update the progress bar as the job progresses, but I can't work out how to access the calling class's UIProgressView to do this. I don't need to use a timer, as the object's method runs a long loop which I know the limits of, and can update the progress bar based on current position in the loop.

I'm sure it's a pretty fundamental concept in objective C programming, but a prod towards the right direction or documentation would really help me out.

Neeku
  • 3,646
  • 8
  • 33
  • 43
Nande
  • 637
  • 1
  • 7
  • 18
  • it's not an objC problem, so it's problem in your app's architecture. Read some books about OOP. – tikhop Aug 14 '12 at 13:47
  • Do you have a suggestion about why this is the wrong way to do it, or what would be a better way? It would help me to understand a lot more than just saying "read books". – Nande Aug 14 '12 at 14:15
  • ViewController should update UIProgressView. Some controller/manager do your long work and update the model. Model dispatch changes to ViewController and then ViewController update UIProgressView. – tikhop Aug 14 '12 at 14:21
  • read this http://en.wikipedia.org/wiki/Design_Patterns book (or similar), and you can build great app architecture. – tikhop Aug 14 '12 at 14:24
  • for sure you can use delegate anywhere, but your code will be look like spaghetti – tikhop Aug 14 '12 at 14:25

2 Answers2

1

Use the delegate pattern.

Create a protocol for your ProgressBar updates:

@protocol MyProgressBarDelegate

- (void) onUpdateProgress:(NSInteger)progress;

@end

Your ViewController implements the delegate and contains this onUpdateProgress method.

Your custom class has a delegate variable which you set in its initializer, its set to the ViewController instance.

id <MyProgressBarDelegate> delegate;

Update your CustomClass designated initializer to pass delegate:(id)delegate as a parameter.

- (void) initWithDelegate:(id<MyProgressBarDelegate>)delegate
{
    self.delegate = delegate;
}

When initializing your CustomClass, [[CustomClass alloc] initWithDelegate:self];

OR make delegate a settable @property, and update via [mCustomClass setDelegate:self];

Then you can call the onUpdateProgress method from your custom class.

if (delegate != nil)     
 [delegate onUpdateProgress:int];
CSmith
  • 13,318
  • 3
  • 39
  • 42
  • Thanks that's a really clear explanation. To complicate things further, will this work if I do: dispatch_async(dispatch_get_global_queue....), ^{ block that creates and calls methods in other object to do the loop } ? I tried doing this and putting it on the queue given its execution time, but I the delegate method never seemed to get called. – Nande Aug 14 '12 at 14:08
  • before worrying about threading/GCD, make sure to hook up your delegate properly. Create an empty onUpdateProgress method, set the delegate, and call [delegate onUpdateProgress:0] from your custom class. Trace in debugger. Once hooked up, you can do whatever you need via GCD (except updating your ProgressBar which you must do on UI thread), delegate is just a pointer. – CSmith Aug 14 '12 at 14:18
  • Ok. I seem to have having trouble hooking it up at all. I put the protocol in the calling viewcontroller.h file, the method definition in the viewcontroller.m file, and the delegate variable with the instances variables of the custom class. There are no build errors or warnings, but when I run the code and do [delegate methodName] nothing happens at all - I checked the logs and delegate is NIL, so somehow it's not working. Am I putting everything in the right place? – Nande Aug 14 '12 at 14:46
  • updated answer ... you need to set delegate to the ViewController instance (self). Modify your designated initializer to pass this value or create a public settable property. – CSmith Aug 14 '12 at 15:04
0

You can assign the view controller as a delegate of the custom class and make the custom class report its progress to the viewcontroller. First, define a protocol for the delegate of the custom class, then make your view controller conform to that protocol, and assign the delegate once you create the instance of your custom class.

J2theC
  • 4,412
  • 1
  • 12
  • 14