Joseph Toronto
Joseph Toronto

Reputation: 1892

Possible to pass object out of IF statement scope?

Here's my code. The compiler is complaining about unused variables within the scope, and use of an undeclared variable out of scope. I understand that. The object would need to be declared before the IF statement so it's accessible from both sides. But here's the twist.

I can't pre-declare the object because what class the object will be from is dependent on the result of the IF statement. Here's the excerpt of code that I'm stuck on.

if (!([self.defaults valueForKey:@"unofficialAPIOn"])) {

        MALInterfaceController *interface = [[MALInterfaceController alloc]init];

    }
    else{

        MALControllerUnofficial *interface = [[MALControllerUnofficial alloc]init];

    }

    [interface verifyAuth:self.usernameField.text forPassword:self.passwordField.text];

Both MALInterfaceController and MALControllerUnofficial are basically the same class that have the same methods, etc but are tailored to two different API's. How can I pass the *interface object upwards?

Upvotes: 0

Views: 267

Answers (2)

CRD
CRD

Reputation: 53000

You state:

Both MALInterfaceController and MALControllerUnofficial are basically the same class that have the same methods, etc but are tailored to two different API's.

You want to consider (a) using a common base class (b) using a protocol or maybe (c) using a class cluster - the last is more obscure so we'll skip that one. Adopting any of these will address your problem.

(a) Common base class. Define a class with the code that is a generic version of what your object does, say MALControllerGeneric, and then create MALInterfaceController and MALControllerUnofficial as subclasses which tailor the generic version for the two different cases. Before your if declare interface to be of type MALControllerGeneric.

(b) Declare the common methods your two classes must provide as a protocol, this lists the methods an class conforming to the protocol must implement. Then declare your two classes as implementing this protocol. In outline this is:

@protocol MALController

- (void) someCommonProcedure;
// etc.

@end

// inherit from NSObject, implement MALController protocol
@interface MALInterfaceController : NSObject<MALController> 

// declare methods peculiar to MALInterfaceController (if any)

@end

@implementation MALInterfaceController

// implement protocol
- (void) someCommonProcedure { ... }

...

@end

You then declare interface to be any object which implements the protocol:

id<MALController> interface;

This improves (static) type-checking compared to use the more generic id type.

The choice between (a) and (b) depends on factors such as how much common code can be shared etc., there is no general right answer - you have to pick what suits.

Addendum - After Comment

Using the protocol approach, you should have the code along the lines of:

id<MALController> interface;

if (![self.defaults valueForKey:@"unofficialAPIOn"])
   interface = [MALInterfaceController new];
else
   interface = [MALControllerUnofficial new];

[interface verifyAuth:self.usernameField.text forPassword:self.passwordField.text];

BTW did you mean to call boolForKey: rather than valueForKey: above?

Upvotes: 2

Stephen Groom
Stephen Groom

Reputation: 3997

Why not use the dynamic type id?

id interface;
if (!([self.defaults valueForKey:@"unofficialAPIOn"])) {

        interface = [[MALInterfaceController alloc]init];

    }
    else{

        interface = [[MALControllerUnofficial alloc]init];

    }

    (id<protocolWhichBothClassesConformTo>)[interface verifyAuth:self.usernameField.text forPassword:self.passwordField.text];

Also, does this not mean you should be looking at a refactor if two of your classes have 'same methods etc'

Worth reading https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/WorkingwithProtocols/WorkingwithProtocols.html

Upvotes: 5

Related Questions