Доступ к свойствам Obj-C в файле расширения Swift

Я начал писать расширения Swift для своих контроллеров представления. Итак, у меня сейчас есть три файла:

Мой заголовочный файл, ViewController.h:

@interface MyViewController : UIViewController

@end

Мой файл реализации Obj-C, 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

И, наконец, ViewController.swift:

extension MyViewController {

    func customiseScrollView() {

    }
}

Мой вопрос: можно ли получить доступ к моим свойствам Obj-C из моего файла реализации Swift? Каждый раз, когда я обращаюсь к нему, я получаю сообщение об ошибке:

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

Бонус 1: Может ли кто-нибудь также уточнить, может ли компонент Swift видеть, что .m также является делегатом. (Чтобы уточнить, выполнение scrollView.delegate = self в Swift является ошибкой компиляции, поскольку файл Swift не понимает, что файл .m является UIScrollViewDelegate).

Бонус 2: Может ли файл расширения Swift вызывать методы Obj-C, объявленные из аналога .m?


person Enrico Susatyo    schedule 22.10.2015    source источник
comment
Если вы хотите получить доступ к свойству scrollView из Swift, вы должны поместить его в общедоступный интерфейс в файле .h. – Касательно бонуса 1: чему .m является делегатом, не имеет смысла. Делегат — это объект, а не файл. – Re Bonus 2: Да, Как вызвать код Objective C из Swift находится под номером 2 на вкладке частых [быстрых] вопросов.   -  person Martin R    schedule 22.10.2015
comment
@MartinR Спасибо, Мартин, я отредактировал эту часть вопроса, чтобы уточнить, что я имел в виду. Я также понял, что могу получить доступ к свойствам, когда помещаю их в файл .h, но я не хотел этого делать, потому что это открывает свойство и для других моих классов Obj-C.   -  person Enrico Susatyo    schedule 22.10.2015
comment
Объявления в файле .m видны только в этом файле. То же самое произойдет, если вы определите расширение в отдельном файле Objective-C, это не проблема Swift.   -  person Martin R    schedule 22.10.2015


Ответы (5)


Я думаю, что вы не можете получить доступ к личным свойствам из расширения. Ваше свойство scrollView находится в файле .m, а не .h, что означает, что оно является частным и не видно из файла расширения.

Решение: двигаться

@property (strong, nonatomic) UIScrollView *scrollView;

в ваш заголовочный файл.

person Kubba    schedule 22.10.2015
comment
Да, это работает! Но я надеялся, что мне не придется этого делать, потому что я не хочу, чтобы эти свойства были доступны из других моих классов Obj-C. - person Enrico Susatyo; 22.10.2015
comment
@EnricoSusatyo Было бы неплохо сделать это readonly в заголовке и readwrite только в файле реализации. - person Sulthan; 26.12.2018

Вы можете получить доступ к внутренним свойствам и методам objc, если объявите расширение класса objc в отдельном заголовке и включите этот заголовок в связующий заголовок.

МойКласс.h

@interface MyClass : NSObject

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

@end

Мой Класс+Private.h

#import "MyClass.h"

@interface MyClass ()

@property (nonatomic, copy) NSString *string;

@end

МойКласс.m

#import "MyClass+private.h"

@implementation MyClass

//...

@end

Project-Bridge-Header.h

#import "MyClass.h"
#import "MyClass+Private.h"
person Nicholas Spencer    schedule 26.12.2018

В Swift частные свойства недоступны из другого файла. Это значение private в Swift. Например:

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'
    }
}

Свойство, объявленное в реализации класса Objective-C, является частным свойством. Таким образом, к свойству нельзя получить доступ из расширения Swift, поскольку это обязательно будет из другого (.swift) файла...

person Milos    schedule 22.10.2015
comment
Обратите внимание, что в вашем примере соответствие протоколу делегата также объявляется конфиденциально, поэтому по той же причине это не будет видно из расширения Swift. То же самое с закрытыми методами... Однако, если ваш scrollView принимает участие в иерархии окон, вы можете получить к нему доступ через его publicly или internally объявленный супервизор... - person Milos; 22.10.2015

Вы можете. Все, что вам нужно, это создать связующий заголовок C цели.

Согласно документации Apple:

Чтобы импортировать набор файлов Objective-C в то же целевое приложение, что и ваш код Swift, вы полагаетесь на соединительный заголовок Objective-C, чтобы предоставить эти файлы Swift. Xcode предлагает создать этот файл заголовка, когда вы добавляете файл Swift в существующее приложение Objective-C или файл Objective-C в существующее приложение Swift.

person Abhinav    schedule 22.10.2015

Просто создайте файл Bridging-Header, а затем импортируйте в него файл ObjC, например:

#import <objectivec.h>

Позже в вашем быстром файле:

var a = objectivec()
a.method_from_those_file

Для получения дополнительной информации прочитайте документацию Apple по адресу здесь.

person Orkhan Alizade    schedule 22.10.2015