4

I'm trying to implement a Dynamic property in my project This is my code.

MyClass.h

@interface MyClass : UIView @property (strong, nonatomic) NSString *name; @end 

MyClass.m

@implementation MyClass @dynamic name; -(void)setName:(NSString *)name{ self.name = name; } @end 

But when I run my app has crashed.

enter image description here

When I use an ivar had this error. enter image description here

5
  • 2
    Why do you want to use @dynamic here? @dynamic is for properties where you're not providing an implementation at compile time, but adding it later via Objective-C runtime magic. Since you're providing a setter here, that's clearly not the case, so... what is it that you're trying to do? Commented Sep 17, 2018 at 22:25
  • It's just an example @CharlesSrstka Commented Sep 17, 2018 at 22:29
  • 1
    But an example of what? What are you trying to do? Commented Sep 17, 2018 at 22:37
  • I agree that the use of @dynamic here is useless and misleading. But it's a non-operation and it doesn't produce the crash. I see a stack overflow because of infinite recursion though. Commented Sep 18, 2018 at 18:02
  • 1
    People.. please don't vote as "unclear what you are asking" - the problem is crystal clear: the OP does not understand (1) the relationship between properties, accessors and iVars, (2) how to declare iVars, and (3) the meaning of @dynamic. He is (4) mixing "dynamic property" with @dynamic property, which is not really the same thing, although it sounds the same when spoken. Maybe I can write an answer before the question is closed.. Commented Sep 18, 2018 at 18:07

3 Answers 3

12

A property is just a bundle of two methods: a getter and a setter. So, when you write

@property (strong, nonatomic) NSString *name; 

what you are really saying is

- (NSString *)name; - (void)setName:(NSString *)name; 

After that, each time the compiler encounters an expression of the form obj.name, it translates it to [obj name]. And each time you see a statement like obj.name = @"hello";, the compiler translates it to [obj setName:@"hello"].

The next thing is you have to make sure the property behaves properly. You have many options:

  • Write getters and setters manually, referring to an iVar
  • Synthesize getter and setter
  • Autosynthesize getter and setter
  • Write custom getters and setters
  • Use @dynamic to avoid compile time warnings, because you intend to do runtime magic. (Really, that's not what you want to do, because you need to understand the basics first.)

Write getters and setters manually, referring to an iVar

@interface MyClass : UIView { NSString *_name; } @property (strong, nonatomic) NSString *name; @end 

and in the implementation

@implementation MyClass - (NSString *)name { return _name; } - (void)setName:(NSString *)name { _name = name; } @end 

Synthesize getter and setter

The last section is basically equivalent to this

@interface MyClass : UIView { NSString *_name; } @property (strong, nonatomic) NSString *name; @end @implementation MyClass @synthesize name = _name; @end 

Autosynthesize getter and setter

In practice, you would just use "autosynthetisation".

@interface MyClass : UIView @property (strong, nonatomic) NSString *name; @end @implementation MyClass @end 

This means,

  • if you just declare a property
  • don't call @synthesize or @dynamic
  • don't implement any custom getter and setter

the code above will just create an iVar named _name and a getter and setter that looks exactly like the one in the first example.

This means that the the first two and this sections are equivalent, because they produce the same code.

Write custom getters and setters

This is what the term "dynamic property" really means. For example, you may want the name to be always uppercase. So you may write a property like this.

@interface MyClass : UIView { NSString *_name; } @property (copy, nonatomic) NSString *name; @end @implementation MyClass - (NSString *)name { return _name; } - (void)setName:(NSString *)name { _name = [name uppercaseString]; } @end 

(in the code above, I changed strong to copy - don't worry, this is just a comment anyways. And it's a true one, because the uppercaseString will never be the same, it will always be a copy of the original.)

This is maybe the only really interesting case! For example, this kind of property is what UIKit uses all the time, e.g. the text property of UILabel is a dynamic property like that. It doesn't just set some iVar, but it also makes sure that the visible text on the screen changes too.

@dynamic properties

they are really tricky to get right, and most of the time they are not worth the hassle IMHO.

Note: I simplified some things and left out details which are only detectable when using objc runtime inspection APIs

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

Comments

4

This StackOverflow answer: https://stackoverflow.com/a/1160545/7833793 does a good job of explaining what the differences between @synthesize and @dynamic are. Typically you use @dynamic if you're delegating the task of implementing the accessors (get, set). It seems to me like you would want to use @synthesize here. But with modern objective c, you shouldn't even need to specify and the iVar will be created for you automatically.

i.e.:

MyClass.h

#import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface MyClass : NSObject @property (strong, nonatomic) NSString *name; @end NS_ASSUME_NONNULL_END 

MyClass.m

#import "MyClass.h" @implementation MyClass - (void)setName:(NSString *)name { _name = name; } @end 

Comments

1

Your solution leads to recursion, you are getting crash since you are not using ivar in setter, try this instead:

-(void)setName:(NSString *)name{ _name = name; } 

1 Comment

@JosuéH. That's because you didn't declare the ivar.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.