0

I have two or even more view controllers (A and B) which uses the same calculation method. I would guess the best way is to put the calculation method in its own class (lets call it C), define a protocol and thats it. If this is right, how do I know how to address the delegate?

If I alloc/init an object of the class C (the one with the calculatormethod) e.g. in class B I have the object pointer in class B - thats ok. But how do I get the object pointer known in class A or even other classes (i.e. how do I tell those controllers which want to use the delegate (i.e the same calculation method), how to address the delegate once it is alloc/init by class B?

Any help is very much appreciated!

Red
  • 1,425
  • 1
  • 10
  • 15
  • If the common code will be purely "functional" -- not accessing any "state" outside of the input parameters -- then it's probably simplest to make it a class method. Can be in some "CommonFunctions" class or some existing "common" class. – Hot Licks Jun 02 '14 at 15:49
  • thx a lot, thats sounds for me as the best idea. I will go with that – Red Jun 03 '14 at 08:18

3 Answers3

0

Use a superclass for A and B (and any number of additional controllers) that contains the calculation method. By using a superclass, you don't have to alloc init another class or use delegates, all the subclasses will have access to the method.

Another approach that would be more general would be to implement a category on UIViewController to add the calculation method. This way, any controller that descends from UIViewController (UITableViewController, UICollectionViewController, etc.) would have access to that method.

After Edit:

I see in your comments that your calculations have nothing to do with the controllers, just some sort of algorithm, so a category or subclass of UIViewController is probably not the best way to go. If you want to do it in another class, any controller that needs to use it, can instantiate an instance of that class, set itself as delegate, and get the result back through the delegate method (that is, if you even need a delegate -- if the calculation is fast, then you can just return a result from the method rather than using a delegate). After your controller gets the result back, the instance should be deallocated. You don't have to worry about which controller set the delegate, since each controller creates its own instance of the calculation class, and sets itself as delegate. I use this kind of structure for apps that need to do downloads from a server from multiple controllers. The download class is instantiated, does its work, sends back the result in a delegate method, and then gets deallocated. It only sticks around for as long as it needs to to do its work.

rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • Yes, works well when both classes A and B actually can have a common superclass, which is probably the case here, but not always. – Stephane Philipakis Jun 01 '14 at 18:06
  • Thx, good idea, except in this special case, my class A is a tableviewcontroller and B a normal one. However, will keep the idea in mind. – Red Jun 01 '14 at 18:10
  • @Red, then a category is probably the easiest approach. I've edited to include that option. – rdelmar Jun 01 '14 at 18:16
  • @Red, I've update my answer based on your comments to Rob's answer. I think the approach you mentioned in your question is on the right track. – rdelmar Jun 02 '14 at 16:54
0

What you are saying is that both classes A and B have a common dependency (could be class C or simply a protocol C). A and B don't need to know anything about how they are instantiated, they just need to know that they will be eventually provided with an instance implementing (protocol) C. Another important thing is that you probably don't want C to be hold with a strong reference by either A or B.

I would look at which class F could have the responsibility to instantiate A and B. The responsibility of this class (which could be described as a Factory) could also be to provide instances of A and B with a C instance.

So what I would do: Define a "factory" class that has methods to build instances of A and B. Each of these methods would also provide with a C instance. This C instance could be a property of the factory class if you want it to be shared (or this factory class could also pick the C instances from a pool of available C instances).

UPDATE: not practical if you are using storyboards to instantiate your controllers. In this case you probably want to go with other given answer or implement your shared computational functions as methods of a singleton class C (see How to pass object between several views in storyboard, iOS Dev for example)

Community
  • 1
  • 1
  • thx, I understand what you are saying, until the point where you provide the C instance. How would that happen, sorry, but I have no clue. – Red Jun 01 '14 at 18:08
  • My answer is not really practical if you are using a storyboard to instantiate your view controllers. I realize that's what you are doing, am I right? – Stephane Philipakis Jun 02 '14 at 15:16
  • yes, thanks anyway, I will use the class - solution. – Red Jun 03 '14 at 20:00
0

I have two or even more view controllers (A and B) which uses the same calculation method.

Unless this is for calculating view layouts, it probably indicates you've have an MVC violation. View Controllers typically should not calculate anything. Their job is to manage user interaction. Data and calculations belong in the model.

If it is a proper view controller calculation (like managing layout), then you're correct that you want a delegate. "Delegation" is what Cocoa tends to call the Strategy pattern. You move your algorithm into another object and that lets you vary the algorithm without varying the rest of the code.

So in one case you need access to some model object, and in the other you need access to some delegate. In either case, the solutions can be similar. I'll call either situation "C" as you have.

One solution, particularly is you're using a storyboard, is to create "C" in the storyboard and wire it with an IBOutlet. You can create any object you like in a storyboard. Just drag out an "Object" and set its class to the appropriate class. Wire it up just like anything else. (This is a technique that is commonly used for multi-view nib files on OS X, and I had remembered translating over to Storyboards, but it doesn't work for sharing objects across scenes, only within scenes; so it's not as useful on iOS.)

Another solution, particularly for the model, is to implement it as a singleton, or to have a separate singleton (a "model controller") that returns it. You should not use the app delegate for this; use a singleton made expressly for this purpose.

You can create "C" in the application delegate and pass it into the root view controller (this is a proper use of the app delegate, because it's part of global program initialization). The view controllers can pass the object as part of their segues. This is my preferred solutions for passing model objects around.

If it really is a layout calculation delegate, this is probably part of some kind of configuration system (assuming it can change). The current configuration can be treated as a piece of the model, and all the above techniques still work.

If it really is just shared algorithms and doesn't vary, don't forget C functions. There is no rule that you must put all code into methods. Functions are ideal for stateless calculation. Categories can be used this way to, but simple functions have fewer complexities.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • thx for the answer. It is just an algorithm, so C function sounds not bad. But, if I use delegates and storyboard, how would it work, when you say: "ust drag out an "Object" and set its class to the appropriate class. Wire it up just like anything else."? I don't know how this would work – Red Jun 01 '14 at 18:56