Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing Obj-C properties in Swift extension file

I started writing Swift extensions on my view controllers. So I have three files right now:

My header file, ViewController.h:

@interface MyViewController : UIViewController

@end

My Obj-C implementation file, ViewController.m:

@interface MyViewController () <UIScrollViewDelegate>
@property (strong, nonatomic) UIScrollView *scrollView;
@end

@implementation MyViewController

- (void)viewDidLoad {

    [super viewDidLoad];

    self.scrollView = [[UIScrollView alloc] init];
    [self customiseScrollView]; //This is Swift method called from Obj-C file
}

@end

And finally, ViewController.swift:

extension MyViewController {

    func customiseScrollView() {

    }
}

My question is, is it possible to access my Obj-C properties from my Swift implementation file? Every time I refer to it, I got an error:

Value of type 'MyViewController' has no member 'scrollView'

Bonus 1: Can someone also clarify if the Swift component can see what the .m is a delegate of as well. (To clarify, doing scrollView.delegate = self in Swift is a compile error because the Swift file does not realise that the .m file is a UIScrollViewDelegate).

Bonus 2: Can Swift extension file call Obj-C methods that are declared from the .m counterpart?

like image 514
Enrico Susatyo Avatar asked Oct 22 '15 07:10

Enrico Susatyo


People also ask

Can Swift extension have properties?

Extensions can add new computed properties, but they can't add stored properties, or add property observers to existing properties.

Does Swift use the Objective-C runtime?

Even when written without a single line of Objective-C code, every Swift app executes inside the Objective-C runtime, opening up a world of dynamic dispatch and associated runtime manipulation.


3 Answers

I think that you can't access private properties from extension. Your scrollView property is in .m file, not .h - which means it's private and it's not visible from extension file.

Solution: move

@property (strong, nonatomic) UIScrollView *scrollView;

to your header file.

like image 60
Kubba Avatar answered Nov 09 '22 04:11

Kubba


You can access internal objc properties and methods if you declare the objc class extension in a separate header and include that header in the bridging header.

MyClass.h

@interface MyClass : NSObject

@property (nonatomic, copy, readonly) NSString *string;

@end

MyClass+Private.h

#import "MyClass.h"

@interface MyClass ()

@property (nonatomic, copy) NSString *string;

@end

MyClass.m

#import "MyClass+private.h"

@implementation MyClass

//...

@end

Project-Bridging-Header.h

#import "MyClass.h"
#import "MyClass+Private.h"
like image 43
Nico Spencer Avatar answered Nov 09 '22 06:11

Nico Spencer


In Swift, private properties are not accessible from another file. This is the meaning of private in Swift. For example:

file1.swift

class MyClass {
    private var privateProperty: String = "Can't get to me from another file!"
}
extension MyClass: CustomStringConvertible {
    var description: String {
        return "I have a `var` that says: \(privateProperty)"
    }
}

file2.swift

extension MyClass {
    func cantGetToPrivateProperties() {
        self.privateProperty // Value of type 'MyClass' has no memeber 'privateProperty'
    }
}

A property declared in the implementation of an Objective-C class is a private property. As such, the property cannot be accessed from a Swift extension since this will be necessarily from a different (.swift) file...

like image 1
Milos Avatar answered Nov 09 '22 06:11

Milos