3

I have two objc .m classes, we'll call them controller1.m and controller2.m. In both controller1.m and controller2.m I have instances of UIAlertController, something like this:

controller1.m

@implementation controller1
    UIAlertController *alertController;
//more code
@end

controller2.m

@implementaion controller2
    UIAlertController *alertController;
//more code
@end

When I try to build the project, I get the error

linker command failed with exit code 1 (use -v to see invocation)

And the error log looks like this

duplicate symbol _alertController in:
/Users/.../Xcode/DerivedData/AppName-cdtbqibmmbsosrdeyqughefeazaa/Build/Intermediates/AppName.build/Debug-iphonesimulator/AppName.build/Objects-normal/x86_64/controller1.o
/Users/.../Xcode/DerivedData/AppName-cdtbqibmmbsosrdeyqughefeazaa/Build/Intermediates/AppName.build/Debug-iphonesimulator/AppName.build/Objects-normal/x86_64/controller2.o

I changed the names of the instance variables for now and it worked... Why do I have to do this? Does Xcode realize that these variables are being used in the same way (due to their name), and that I should have them declared globally, somehow?

2
  • 1
    Declare them in the interface as properties. Commented Aug 6, 2016 at 0:10
  • @danh Ah, okay. But why is that? [Forgive me, I'm pretty new with objective-c] Commented Aug 6, 2016 at 0:15

2 Answers 2

5

Your problem is that those variables are not instance variables. They are global variables.

To make them instance variables they need to be in the curly braces of the @implementation block as follows:

@implementation controller1 {
    UIAlertController *alertController;
}

//more code

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

3 Comments

Ah okay, thanks. And is there a difference between doing it the way you have it versus the way @Danh recommended, by making it a property of the class?
My way fixes your declaration of the instance variable. Dan's way replaces the instance variable with a property. There are plenty of debates about whether you should use private properties or instance variables. Either approach works.
Okay, thanks. It looks like I have to read up on the difference between instance variables and properties. So far it looks like they are accessed differently and thats about it
1

As you have it, the code declares a global with the same name in each module. To make the pointers private to their respective classes, use properties...

// controller1.m

@interface controller1 ()

@property(strong,nonatomic) UIAlertController *alertController;
// any other property private to controller1

@end

@implementation controller1

// only methods here

@end

5 Comments

You do not need to change them to properties to fix them properly.
Thanks! Is there a difference in what you are recommending versus what @rmaddy recommended/why did you recommend that? I accepted rmaddy's answer because his answers appeared slightly before yours. I do see that you commented on my question before him though
sure. the difference is that I'm suggesting a little more modern declaration that, under the covers, creates a getter and a setter method for you. So you can say self.alertControlleror self.alertController = // blah.
Hmm thats interesting. So I'm guessing that @properties take up more memory (not that it matters for the small scale apps I build), and should be used when I have setting/getting them in mind? Whereas I should make an ivar if I don't need that stuff for it?
They are the same data-wise. The object gets two more methods that I would argue are a net benefit.

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.