0

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.

Sulthan
  • 128,090
  • 22
  • 218
  • 270
Alwaysblue
  • 9,948
  • 38
  • 121
  • 210
  • 1
    If I remember correctly don't use `assign` for an object. Use `assign` only for primitives: float, double, Bool, etc. – Larme Jun 30 '21 at 14:41
  • See https://stackoverflow.com/a/26264260/1801544 – Larme Jun 30 '21 at 14:44
  • 2
    Not specifying assign will mean the property getter and setter will use strong. If you specify assign it means the generated functions for get/set will just take the pointer value and store that. No memory management, dangling pointers... Don't use assign for objects. You probably want to use "copy" semantics because this is a value object, and you don't want someone passing a NSMutableString and mutating it under your feet – Shadowrun Jun 30 '21 at 15:06

2 Answers2

1

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.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Semi-related: is the `assign` property modifier the Objective C equivalent to Swift’s `unowned` (When talking about objects)? – Alexander Jun 30 '21 at 16:22
  • 1
    Yes, Objective-C's assign is equivalent to unowned. – Duncan C Jun 30 '21 at 17:02
  • Duncan, Thanks a lot for answering. Just couple of questions, I added `- (void) dealloc { NSLog(@"Deallocated Object"); }` to get whenever object memory gets deallocated but I never saw a log in my xcode console? – Alwaysblue Jul 01 '21 at 00:19
1

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

SeaSpell
  • 678
  • 3
  • 9
  • Thanks a lot for answering, why would object be deallocated as soon as it is set? – Alwaysblue Jul 01 '21 at 00:23
  • In the old day the object was managed by the programmer. In the last ten years or so the compiler added management code for you behind the scenes. It had to know some things about how to keep something in the heap though. Beyond the scope of what you need to know the compiler used the keyword to decide how to keep a reference with Automatic Reference Counting. Apple has always used a very static means of memory clearing. Now days it's handled behind the scenes. Back in the day you had to deallocate memory manually or add a retain cycle to it. – SeaSpell Jul 01 '21 at 00:43