ios - 从 Kotlin Native 继承 UIView

标签 ios swift objective-c kotlin kotlin-native

UIKit 旨在通过子类和覆盖方法使用。
通常,drawRect UIView的objective-C方法在SWIFT中是这样实现的:

import UIKit
import Foundation

class SmileView: UIView {
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        
        let smile = ":)" as NSString
        smile.draw(in: rect, withAttributes: nil)
    }
}
不幸的是,Kotlin 中的 UIKit 导入将这些函数定义为无法覆盖的扩展函数。
有没有人通过自定义 cinterop 成功地从 Kotlin 继承 UIView?配置?

最佳答案

所以我们设法让它发挥作用。
1. 在 build.gradle.kts 添加 cinterop 配置任务

kotlin {
    android()
    ios {
        binaries {
            framework {
                baseName = "shared"
            }
        }
        compilations.getByName("main") {
            val uikit by cinterops.creating {
            }

        }
    }
2. 添加一个 `src/nativeinterop/cinterop/uikit.def` 文件。
package = demo.cinterop
language = Objective-C
---

#import <Foundation/Foundation.h>
#import <UIKit/UIView.h>

@protocol UIViewWithOverrides
- (void) drawRect:(CGRect)aRect;
- (void) layoutSubviews;
@end

3.创建自定义UIView类
该类从 UIKit 扩展了 UIView 并实现了之前创建的 UIViewWithOverrides 协议(protocol) (自动添加后缀)
package demo

import demo.cinterop.UIViewWithOverridesProtocol
import kotlinx.cinterop.*
import platform.CoreGraphics.*
import platform.UIKit.*

@ExportObjCClass
class MyView() : UIView(frame = CGRectMake(.0, .0, .0, .0)), UIViewWithOverridesProtocol {

    override fun layoutSubviews() {
        println("layoutSubviews")
        setNeedsDisplay()
    }

    override fun drawRect(aRect: CValue<CGRect>) {
        val rectAsString = aRect.useContents {
            "" + this.origin.x + ", " + this.origin.y + ", " + (this.origin.x +this.size.width) + ", " + (this.origin.y +this.size.height)
        }
        println("drawRect:: Rect[$rectAsString]")

        val context: CPointer<CGContext>? = UIGraphicsGetCurrentContext()
        CGContextSetLineWidth(context, 2.0)
        val components = cValuesOf(0.0, 0.0, 1.0, 1.0)
        CGContextSetFillColor(context, components)
        val square = CGRectMake(100.0, 100.0, 200.0, 200.0)
        CGContextFillRect(context, square)

    }

}

fun createMyView(): UIView = MyView()

4. 从 Swift 使用它
struct ChartView: View {

    var body: some View {

        VStack {
            Text("Chart View")
            MyView()
                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
        }
    }

}

struct ChartView_Previews: PreviewProvider {
    static var previews: some View {
        ChartView()
    }
}

struct MyView: UIViewRepresentable {

    func makeUIView(context: Context) -> UIView {
        UIChartViewKt.createMyView()
    }

    func updateUIView(_ uiView: UIView, context: Context) {
    }

}

关于ios - 从 Kotlin Native 继承 UIView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69266205/

相关文章:

xcode - 二元运算符 != 不能应用于 NSUrlConnection!.Type 和 NilLiteralConvertible 类型的操作数

iphone - UIView 基于 block 的动画的重复计数

iphone - 为 iPhone 应用程序制作手册的最简单和最快的方法是什么?

ios - Skobbler map - 无法计算路线

ios - 在未连接 Xcode 的情况下在设备上测试应用程序状态保存/恢复

javascript - 如何在 javascript 中取消选择/取消焦点文本字段

xcode - 加载 View 导致程序崩溃

ios - 为什么在向其 append 对象后数组为空

ios - 如果点击 iOS 屏幕上的任何其他地方,是否会关闭菜单?

ios - 我怎样才能从 FlutterViewController "push"UIViewController