将成员初始化为 class 函数导致 'self' used in method call 错误
Initialising member to class function causes 'self' used in method call error
我有一个指向 class 函数之一的 class 属性。但是,当我尝试使用其中一个函数初始化此变量时,出现以下错误:
'self' used in method call before all stored properties are initialized.
我可以为这些函数初始化任何其他变量,但错误使它听起来像我正在调用函数,即使我没有。
import UIKit
import AudioToolbox
class BeatMaker {
// iPhone 7 and up use beat function, iPhone 6s use beatFallback
let hapticFunction: () -> ()
let impactGenerator = UIImpactFeedbackGenerator.init(style: .heavy)
init(supportsImpactGenerator: Bool) {
// error 1: 'self' used in method call 'beat' before all stored properties are initialized
// error 2: 'self' used in method call 'beatFallback' before all stored properties are initialized
self.hapticFunction = (supportsImpactGenerator) ? beat : beatFallback
}
private func beat() {
impactGenerator.impactOccurred()
}
private func beatFallback() {
AudioServicesPlaySystemSound(1520)
}
func makeABeat() {
hapticFunction()
}
}
在这种特定情况下,我想利用 Taptic Engine 并通过 UIImpactFeedbackGenerator
模拟点击。 iPhone 6s 不支持这个引擎,所以我想调用一个产生类似效果的回退函数。
我也试过当场初始化变量:
// this works
var hapticFunction: (BeatMaker) -> () -> () = beat
init(supportsImpactGenerator: Bool) {
if !supportsImpactGenerator {
// error: Cannot assign value of type '() -> ()' to type '(BeatMaker) -> () -> ()'
self.hapticFunction = beatFallback
// produces same error
self.hapticFunction = beatFallback.self
}
}
我知道我可以将所有内容设为静态或将所有内容从 class 中移除,但是 感觉 应该可以,但实际上没有。我错过了什么吗?
编辑
将hapticFunction
的type of type 设置为optional 似乎可行,但这对我来说没有任何意义。有什么区别?
// this works
var hapticFunction: (() -> ())?
init(supportsImpactGenerator: Bool) {
self.hapticFunction = (supportsImpactGenerator) ? beat : beatFallback
}
有两种方法可以解决这个问题
您可以:
给hapticFunction
一个初始值,比如{}
或修正为:
class BeatMaker {
let impactGenerator = UIImpactFeedbackGenerator.init(style: .heavy)
let supportsImpactGenerator: Bool
init(supportsImpactGenerator: Bool) {
self.supportsImpactGenerator = supportsImpactGenerator
}
private func beat() {
if supportsImpactGenerator {
impactGenerator.impactOccurred()
} else {
AudioServicesPlaySystemSound(1520)
}
}
func makeABeat() {
beat()
}
}
最好不要使用 Bool
,而是使用嵌套的 Enum
,如果您想稍后添加其他一些触觉反馈模式,它也更具可扩展性。
我有一个通用的解决方案来解决你的问题。所以要么你这样做:
public class FunctionOwner {
private let mode: Mode
public init(`do` mode: Mode = .default) {
self.mode = mode
}
}
public extension FunctionOwner {
enum Mode {
case foo, bar
}
func fooOrBar() {
switch mode {
case .foo: foo()
case .bar: bar()
}
}
}
private extension FunctionOwner {
func foo() {
print("doing foo")
}
func bar() {
print("doing bar")
}
}
public extension FunctionOwner.Mode {
static var `default`: FunctionOwner.Mode {
return .foo
}
}
// USAGE
FunctionOwner(do: .bar).fooOrBar() // prints "doing foo"
FunctionOwner(do: .foo).fooOrBar() // prints "doing bar"
或者如果您出于某种原因确实想保留存储的 Mode
,您可以这样做(可能与您的实际问题有关,即如何在初始化。):
public class FunctionOwner {
private let _function: (FunctionOwner) -> Void
public init(`do` mode: Mode = .default) {
_function = { functionOwner in
switch mode {
case .foo: functionOwner.foo()
case .bar: functionOwner.bar()
}
}
}
}
public extension FunctionOwner {
enum Mode {
case foo, bar
}
func fooOrBar() {
_function(self)
}
}
// The rest of the code is the same as the example above
我有一个指向 class 函数之一的 class 属性。但是,当我尝试使用其中一个函数初始化此变量时,出现以下错误:
'self' used in method call before all stored properties are initialized.
我可以为这些函数初始化任何其他变量,但错误使它听起来像我正在调用函数,即使我没有。
import UIKit
import AudioToolbox
class BeatMaker {
// iPhone 7 and up use beat function, iPhone 6s use beatFallback
let hapticFunction: () -> ()
let impactGenerator = UIImpactFeedbackGenerator.init(style: .heavy)
init(supportsImpactGenerator: Bool) {
// error 1: 'self' used in method call 'beat' before all stored properties are initialized
// error 2: 'self' used in method call 'beatFallback' before all stored properties are initialized
self.hapticFunction = (supportsImpactGenerator) ? beat : beatFallback
}
private func beat() {
impactGenerator.impactOccurred()
}
private func beatFallback() {
AudioServicesPlaySystemSound(1520)
}
func makeABeat() {
hapticFunction()
}
}
在这种特定情况下,我想利用 Taptic Engine 并通过 UIImpactFeedbackGenerator
模拟点击。 iPhone 6s 不支持这个引擎,所以我想调用一个产生类似效果的回退函数。
我也试过当场初始化变量:
// this works
var hapticFunction: (BeatMaker) -> () -> () = beat
init(supportsImpactGenerator: Bool) {
if !supportsImpactGenerator {
// error: Cannot assign value of type '() -> ()' to type '(BeatMaker) -> () -> ()'
self.hapticFunction = beatFallback
// produces same error
self.hapticFunction = beatFallback.self
}
}
我知道我可以将所有内容设为静态或将所有内容从 class 中移除,但是 感觉 应该可以,但实际上没有。我错过了什么吗?
编辑
将hapticFunction
的type of type 设置为optional 似乎可行,但这对我来说没有任何意义。有什么区别?
// this works
var hapticFunction: (() -> ())?
init(supportsImpactGenerator: Bool) {
self.hapticFunction = (supportsImpactGenerator) ? beat : beatFallback
}
有两种方法可以解决这个问题
您可以:
给hapticFunction
一个初始值,比如{}
或修正为:
class BeatMaker {
let impactGenerator = UIImpactFeedbackGenerator.init(style: .heavy)
let supportsImpactGenerator: Bool
init(supportsImpactGenerator: Bool) {
self.supportsImpactGenerator = supportsImpactGenerator
}
private func beat() {
if supportsImpactGenerator {
impactGenerator.impactOccurred()
} else {
AudioServicesPlaySystemSound(1520)
}
}
func makeABeat() {
beat()
}
}
最好不要使用 Bool
,而是使用嵌套的 Enum
,如果您想稍后添加其他一些触觉反馈模式,它也更具可扩展性。
我有一个通用的解决方案来解决你的问题。所以要么你这样做:
public class FunctionOwner {
private let mode: Mode
public init(`do` mode: Mode = .default) {
self.mode = mode
}
}
public extension FunctionOwner {
enum Mode {
case foo, bar
}
func fooOrBar() {
switch mode {
case .foo: foo()
case .bar: bar()
}
}
}
private extension FunctionOwner {
func foo() {
print("doing foo")
}
func bar() {
print("doing bar")
}
}
public extension FunctionOwner.Mode {
static var `default`: FunctionOwner.Mode {
return .foo
}
}
// USAGE
FunctionOwner(do: .bar).fooOrBar() // prints "doing foo"
FunctionOwner(do: .foo).fooOrBar() // prints "doing bar"
或者如果您出于某种原因确实想保留存储的 Mode
,您可以这样做(可能与您的实际问题有关,即如何在初始化。):
public class FunctionOwner {
private let _function: (FunctionOwner) -> Void
public init(`do` mode: Mode = .default) {
_function = { functionOwner in
switch mode {
case .foo: functionOwner.foo()
case .bar: functionOwner.bar()
}
}
}
}
public extension FunctionOwner {
enum Mode {
case foo, bar
}
func fooOrBar() {
_function(self)
}
}
// The rest of the code is the same as the example above