在Swift初始化期间调用实例方法

时间:2015-02-21 14:21:47

标签: ios swift constructor initialization

我是Swift的新手,想要使用像这样的实例方法初始化对象的成员变量:

class MyClass {
  var x: String
  var y: String

  func createY() -> String {
    self.y = self.x + "_test" // this computation could be much more complex
  }

  init(x: String) {
    self.x = x
    self.y = self.createY()
  }     
}

基本上,我不想在init方法中内联所有初始化代码,而是将y的初始化代码提取到专用方法createY并调用此实例方法{{1在createY中。但是,Swift编译器(Xcode 6.3 beta中的Swift 1.2编译器)抱怨道:

  

在super.init初始化self

之前,在方法调用'xxx'中使用'self'

这里'xxx'是实例方法的名称(createY)。

我可以理解Swift编译器正在抱怨什么以及它想要解决的潜在问题。但是,我不知道如何解决它。什么应该是Swift在init中调用初始化代码的其他实例方法的正确方法?

目前,我使用以下技巧作为解决方法,但我不认为这是解决此问题的惯用方法(此解决方法需要使用init而不是{{y声明var 1}}这让我感到不安):

let

任何评论都表示赞赏。感谢。

7 个答案:

答案 0 :(得分:10)

createY()转换为接受x作为参数的全局或类函数,并返回y

func createY(x: String) -> String {
    return x + "_test" // this computation could be much more complex
}

然后从您的init正常调用它。

class MyClass {
  let x: String
  let y: String

  init(x: String) {
    self.x = x
    self.y = createY(x)
  }     
}

答案 1 :(得分:2)

我认为Swift的方法是使用Computed Properties(https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html

修改

您可以使用计算属性来代替调用函数来修改set / get上的属性:

class MyClass {

    var x: String?
    var y: String? {
        get {
            return "\(x!)_test"
        }
    }

    init(x: String!){
       self.x = x
    }
}

let myClass = MyClass(x: "string") 
print(myClass.y!) #=> "string_test"

答案 2 :(得分:2)

在Swift 3中,我一直在使用这种模式,

class MyClass {
  var x: String?
  private(set) lazy var y: String? = self.createY()

  init(x: String){ self.x = x }

  private func createY() -> String?
  {
    return "\(x ?? "nil") test"
  }
}

这里的秘诀是使用private(set) lazy。这样,您就可以将您的媒体资源标记为var。并且lazy将延迟初始化,直到您的init函数完成。使用private(set)仅允许此类中的函数修改该属性,包括lazy关键字,但不允许公共接口更改它。当然,如果您希望界面更改您的媒体资源,那么您也可以将其标记为internal(默认)或public。但您需要将其标记为lazy var

答案 3 :(得分:1)

回答here,创建一个类函数。我添加了完整的代码。

class MyClass {
    var x: String
    var y: String

    class func createY(x: String) -> String {
         return x + "_test" // this computation could be much more complex
    }

    init(x: String) {
        self.x = x
        self.y = MyClass.createY(x)
    }     
}

答案 4 :(得分:0)

您可以使用此方法

类MyClass:NSObject {

        let x: String
        var y: String

        init(x: String) {

            self.x = x
            self.y = self.x + "_test"
            print(self.x)
            print(self.y)
        }
}

答案 5 :(得分:0)

Set-SPCustomLayoutsPage -Identity AccessDenied -RelativePath "/_layouts/custompages/myaccessdenied.aspx" -WebApplication "http://server_name/mywebapp"

答案 6 :(得分:0)

请参见Two-Phase Initialization和示例: https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html#ID52 在无主引用和隐式展开的可选属性中

class Country {
    let name: String
    var capitalCity: City!
    init(name: String, capitalName: String) {
        self.name = name
        self.capitalCity = City(name: capitalName, country: self)
    }  
}
class City {
    let name: String
    unowned let country: Country
    init(name: String, country: Country) {
        self.name = name
        self.country = country
    }
}
  

要在两个类之间建立相互依赖关系,City的初始化程序将使用一个Country实例,并将该实例存储在其country属性中。

     

从Country的初始化程序中调用City的初始化程序。但是,Country的初始化程序无法将自身传递给City初始化程序,直到完全初始化了新的Country实例为止,如两阶段初始化中所述。

     

为满足此要求,您将Country的capitalCity属性声明为一个隐式展开的可选属性,由其类型注释(City!)末尾的感叹号指示。这意味着与任何其他可选参数一样,capitalCity属性的默认值为nil,但是无需进行隐式解包的可选参数中所述的解包即可访问它。

     

由于capitalCity具有默认的nil值,因此,一旦Country实例在其初始值设定项中设置其name属性,便认为该Country实例已完全初始化。这意味着一旦设置了name属性,Country初始化器就可以开始引用并传递隐式的self属性。因此,当Country初始化器设置自己的capitalCity属性时,Country初始化器可以将self作为City初始化器的参数之一传递。

因此添加y类型的感叹号-> var y: String!