从 Objective C 类更新 SwiftUI 视图

Ali*_*may 5 objective-c ios swift swiftui

我对 IOS 开发没有经验,但有一些基本的了解,可以通过阅读文档和教程来完成它。

我想从 Swift 调用 Objective C 代码并且它运行良好,现在我想做相反的事情并且有点困惑。

基本上,我首先在 SwiftUI 中的 Button 操作中调用 Objective C 函数,然后我希望该函数在同一个 SwiftUI 视图中更新 ObservedObject 并希望该视图重新呈现。

我已经找到并关注了一些关于它的资源,它们是

https://medium.com/@iainbarclay/adding-swiftui-to-objective-c-apps-63abc3b26c33

https://pinkstone.co.uk/how-to-use-swift-classes-in-objective-c/

Swift UI 视图看起来像

class Foo : ObservableObject {
    @Published var bar = ""
}

struct ContentView: View {
    @ObservedObject var baz = Foo();
    
    // Then access later as self.baz.bar as a parameter somewhere..

Run Code Online (Sandbox Code Playgroud)

bar在这里更新的正确方法是什么?

我做了正确的构建设置并添加了@objc标签并导入了project_name-swift.h. 实施并修改了https://medium.com/@iainbarclay/adding-swiftui-to-objective-c-apps-63abc3b26c33 中的示例, 但由于我在这些环境中缺乏经验,所以有点迷失。

也许有人可以将我推向正确的方向。

谢谢你。

假设我的项目名称是Project.

示例代码:(与此非常相似的代码,编译良好,目标 C 函数调用,但在快速方面,我没有输出到控制台,文本也没有呈现。如果您指出我的错误,我将不胜感激,因为我很少参与 iOS 开发。)

内容视图.swift

import Foundation
import SwiftUI

var objectivec_class = Objectivec_Class()

class Foo : ObservableObject {
    @Published var bar = ""
}

@objc
class BridgingClass: NSObject {

    @ObservedObject var baz = Foo();
    @objc func updateString(_ content: NSMutableString) {
        print("This function is called from Objective C")
        self.baz.bar += content as String
    }

}

struct ContentView: View {
    /** 
     * This part seems fishy to me, 
     * It would have been better to inject the instance of Foo here in 
     * BridgingClass but, couldn't figure out how to.
     * This is only for showing my intention. 
     */
    @ObservedObject var baz = Foo();
    var body: some View {
        Button(action: {
            objectivec_class.updateSwiftUi()
        })
        {
            Text(self.baz.bar)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Run Code Online (Sandbox Code Playgroud)

目标 C 桥接标题,

Project-Bridging-Header.h

#import "Objectivec_Class.h"

Run Code Online (Sandbox Code Playgroud)

Objectivec_Class.h

#ifndef Objectivec_Class_h
#define Objectivec_Class_h

#import <Foundation/Foundation.h>
#import "Project-Swift.h"

@interface Objectivec_Class : NSObject

    @property (strong, nonatomic) NSMutableString* stringWhichWillBeRendered;
    @property  BridgingClass *bridgingClass;

    - (id) init;

    - (void) updateSwiftUi;

@end

#endif /* Objectivec_Class_h */

Run Code Online (Sandbox Code Playgroud)

Objectivec_Class.m


#import <Foundation/Foundation.h>
#import "Project-Swift.h"
#import "Objectivec_Class.h"

@implementation Objectivec_Class

    - (id)init{
        if( self = [super init] ){
            _stringWhichWillBeRendered  = [NSMutableString stringWithString:@""];
            BridgingClass *bridgingClass = [BridgingClass new];
        }
        return self;
    }

    - (void) updateSwiftUi {
        NSString *thisWillBeRendered = @"Render this string.";
        [_stringWhichWillBeRendered appendString:thisWillBeRendered];
        [[self bridgingClass] updateString:_stringWhichWillBeRendered];
    }

@end


Run Code Online (Sandbox Code Playgroud)

Asp*_*eri 4

尝试以下操作

@objc
class BridgingClass: NSObject {

    var baz = Foo()  // here !!
...
Run Code Online (Sandbox Code Playgroud)

struct ContentView: View {

    @ObservedObject var baz = objectivec_class.bridgingClass.baz    // << this !!

    var body: some View {
        Button(action: {
            objectivec_class.updateSwiftUi()
        })
        {
            Text(self.baz.bar)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Objectivec_Class.m

@implementation Objectivec_Class

    - (id)init{
        if( self = [super init] ){
            _stringWhichWillBeRendered  = [NSMutableString stringWithString:@""];
            self.bridgingClass = [BridgingClass new]; // here !!

...
Run Code Online (Sandbox Code Playgroud)