Alwaysblue
Alwaysblue

Reputation: 11830

Understanding why assign is breaking code in swift

I made an xcframework (in objective c) which is working fine in objective C but throws an error when using swift.

On debugging, I realized that it was breaking in swift because I was using assign.

I went through his answer: https://stackoverflow.com/a/4511004/10433835

where they say this

In most cases you'll want to use weak so you're not trying to access a deallocated object

I didn't quite get what assign does, but I don't think I am trying to access a deallocated object.

This is what I am doing

I have config with these properties

#import <Foundation/Foundation.h>

@interface Config : NSObject
@property(nonatomic, assign, readwrite) NSString *name;
@property(nonatomic, assign, readwrite) NSString *id;
@property(nonatomic, assign, readwrite) NSString *api;
@end

This is my Config.m file

@implementation Config

 - (id)init {
  if (self = [super init]) {
   _api = @"https://api.xyz.in"
  }
  return self;
}

- (NSMutableDictionary *_Nonnull)configProperties {

 if (!_name) {
    [NSException raise:@"name" format:@"Room name cannot be null, please set room name"];
  } 
  NSLog(@"Room name: %@", _name);

At this line it will throw Thread 1: EXC_BAD_ACCESS

  NSLog(@" name: %@", _name);

if I remove assign, it won't throw any error

How am I calling it?

 let config:Config = Config();
    config.name = "varun_bindal";
    let props = config.configProperties()

Can someone please explain me why using assign in swift is crashing my code? and why not using it doesn't.

Upvotes: 0

Views: 121

Answers (2)

Duncan C
Duncan C

Reputation: 131408

The answer is: It's complicated.

Swift takes care of object ownership for you. Your only responsibility is to create strong or weak variables to avoid retain cycles. When you stay in Swift, it takes care of everything else.

Life is more complicated in Objective-C, and more complicated still when you need to have Objective-C and Swift code interact.

In order for Swift and Objective-C to work correctly together, you have to declare the memory semantics of your Objective-C classes correctly.

When you declare an Objective-C property as assign, you're telling the compiler not to do any memory management on it. Your Swift code won't set up strong references, and won't be notified if the object has been deallocated. If the Objective-C code doesn't need it any more and releases it, and your Swift code tries to reference it, you will crash.

(As mentioned in comments, Objective-C's assign is equivalent to unowned in Swift.)

As Larme says, assign is ok for non-object scalar types, but not for objects.

Upvotes: 1

SeaSpell
SeaSpell

Reputation: 758

You actually don't want a weak or assign set for that property. The object will be deallocated as soon as it is set. You want a strong reference because the object owns the property. weak will nil the pointer as soon as it's set. So checking the pointer will return nil. assign will keep the address of the pointer without keeping the actual memory set. Hence you're pointing to something that has been deallocated. ie: pointing to bad memory location. It's kind of a remnant of the old days really.. You can read here for more info on keywords: https://exceptionshub.com/property-and-retain-assign-copy-nonatomic-in-objective-c.html

Upvotes: 1

Related Questions