如何在swift中使用其他属性将实例作为属性传递

Posted

技术标签:

【中文标题】如何在swift中使用其他属性将实例作为属性传递【英文标题】:How to pass an instance as a property using other properties in swift 【发布时间】:2020-06-13 00:56:31 【问题描述】:

我是 swift 的新手,我正在尝试传递一个类 (CP) 的实例作为 swift UI 的 ContentView 结构的属性。此实例接受同一 ContentView 结构的另一个属性的参数。我希望能够从警报菜单中选择一个选项,将属性设置为一个变量,该变量将确定来自计时器的特定时间序列,并且由于此实例的参数是一个 inout 字符串,因此这些值将在实例中更新。我在这个网站上发现有人遇到类似情况,有人建议重写 viewDidLoad 函数。但是,这不适用于 SwiftUI 框架。

这是我认为足以理解问题的代码示例。 débatCP,将在其他元素中使用,因此在第一个按钮操作中声明它将不起作用。

struct ContentView: View 
@State var a = "Chronometre"
@State var partie = "Partie du débat"
@State var tempsString = "Temps ici"
@State var enCours = "CanadienParlementaire - Commencer"
@State var pausePlay = "pause"
@State var tempsMillieu = 420;
@State var tempsFermeture = 180
@State var round = 7;
@State var répartitionPM = "7/3"
var debatCP = CP(modePM: &répartitionPM)
@State private var showingAlert = false
//il va falloir un bouton pause
var body: some View 
    VStack 
        Text(String(self.round))
        Text(a)
            .font(.largeTitle)
            .fontWeight(.semibold)
            .lineLimit(nil)

        Text(partie)
        Button(action: 
            self.showingAlert = true
            if self.enCours != "Recommencer"
            let chrono = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true)  (chrono) in
                self.debatCP.verifierEtatDebut(round: &self.round, tempsActuel: &self.tempsMillieu, pause: &self.pausePlay, partie: &self.partie, tempsStr: &self.tempsString)
                if self.round <= 2
                     self.debatCP.verifierEtatFin(round: &self.round, tempsActuel: &self.tempsFermeture, pause: &self.pausePlay, partie: &self.partie, tempsStr: &self.tempsString)

                
                if self.round <= 0 
                    chrono.invalidate()
                    self.enCours = "Canadien Parlementaire - Commencer"
                
            
            
            else
                self.tempsMillieu = 420
                self.tempsFermeture = 180
                self.round = 7
            
            self.enCours = "Recommencer"

            self.a = "CP"
        , label: 
            Text(enCours)
                .alert(isPresented: $showingAlert) 
                    Alert(title: Text("6/4 ou 7/3"), message: Text("6/4 pour avoir plus de temps à la fin et 7/3 pour en avoir plus au début"), primaryButton: .default(Text("6/4"), action: 
                        self.répartitionPM = "6/4";
                    ), secondaryButton: .default(Text("7/3"), action: 
                        self.répartitionPM = "7/3"
                    ))
            
        )

我收到此错误消息:无法在属性初始化程序中使用实例成员“répartitionPM”;属性初始化器在“self”可用之前运行

编辑

这是 CP 类

class CP:Debat
init(modePM: inout String)

  override  var rondeFermeture:Int
        return 2;
    
    override var tempsTotalMillieu : Int
        return 420;
    ;
    override var tempsProtege:Int//60
        return 60;
    

    override var tempsLibre:Int//360
        return 360;
    
    override var tempsFermeture: Int
        return 180;

连同一个Defat类的样本

class Debat
var rondeFermeture:Int
    return 0;

var tempsTotalMillieu:Int//420
    return 0;
;
var tempsProtege:Int//60
    return 0;

var tempsLibre:Int//360
    return 0;

var tempsFermeture:Int
    return 0

func formatTime(time:Int) -> String 
    let minutes:Int = time/60
    let seconds:Int = time%60
    return String(minutes) + ":" + String(seconds)

func prochainTour(time: inout Int, round : inout Int)->Void
    if round > rondeFermeture 
    let tempsAvantLaFin = time % self.tempsTotalMillieu
        time -= tempsAvantLaFin
    
    if round <= rondeFermeture
        let tempsAvantLaFin = time % self.tempsFermeture
        time -= tempsAvantLaFin
    

【问题讨论】:

这是一个 inout 字符串 var debatCP = CP(modePM: &amp;"7/3")would 不能将不可变值作为 inout 参数传递:文字不可变 【参考方案1】:
@State var répartitionPM = "7/3"
var debatCP = CP(modePM: &répartitionPM)

SwiftUI 有不同的模式来处理@State 变量。目前尚不清楚CP 是什么,但无论如何以下是要走的路

struct AContentView: View 

    @State var repartitionPM = "7/3" // should be defined
    var debatCP:CP!=nil                  // declare-only

    init() 
        debatCP = CP(modePM: $repartitionPM) // pass as binding
    
    ...

CP 应该是这样的

class CP:Debat
@Binding var modePM:String

init(modePM:Binding <String>)
    self._modePM = modePM
    super.init()


【讨论】:

CP 是一个类,它继承自另一个类,所以我不认为结构在那里有用。 init() debatCP = CP(modePM:&amp;répartitionPM) 在初始化所有存储属性之前使用此错误“自我” @LouisCouture,class也可以包含@Binding,注意,我把绑定放在init,不是引用,其他的cmets很重要。 有效!然而,当前的语法需要在我们使用它之前初始化所有属性(参见***.com/questions/34474545/…)。这可以通过将 debatCP 设置为 nil 并使用 !将绑定变量分配给类的语法也不同。我会修改你的答案以反映变化

以上是关于如何在swift中使用其他属性将实例作为属性传递的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Angular 中的依赖注入将属性指令实例传递给嵌套组件

在@ swift中@ property / @ synthesize等效

Swift 属性

在添加/删除 ViewController 作为子视图 Swift 后,ParentView 属性设置为 nil

将属性从模态视图控制器传递给父级

如何处理包含 Swift 结构作为属性的 Swift 结构的编码