'不能在属性初始值设定项中使用实例成员'allEvents';属性初始化程序在'self'可用之前运行'错误

时间:2016-12-12 14:22:10

标签: ios swift

var allEvents: [String] = ["SOUTHERN STATES PASS LAWS TO DISENFRANCISE BLACKS", "THEODORE ROOSEVELT ELECTED VICE PRESIDENT", "WRIGHT BROTHERS FIRST FLIGHT", "SAN FRANCISCO EARTHQUAKE", "FORD INTRODUCES MODEL T", "WORLD WAR I BEGINS IN EUROPE", "WORLD WAR I ENDS", "TR DIES – CARNEGIE DIES", "GERMAN MONEY HYPER INFLATES", "TREATY OF VERSAILLES, 19TH AMENDMENT", "HINDENBURG ELECTED PRESIDENT OF GERMANY", "STOCK MARKET CRASHES, DEPRESSION BEGINS", "HITLER’S NAZI PARTY GAINS MAJORITY IN PARLIAMENT", "HITLER BEGINS TO TAKE POWER IN GERMANY", "FRANKLIN ROOSEVELT ELECTED PRESIDENT", "FDR INAUGURATED “100 DAYS”", "HINDENBURG DIES, HITLER APPOINTS HIMSELF PRESIDENT  -  “ FUEHRER”", "FDR RE-ELECTED", "German airship HINDENBURG BURNS IN NEW JERSEY", "“MUNICH” – British P.M. Chamberlain agrees that Hitler can have Czechoslovakia.", "Germany invades Holland, Belgium and France – Churchill becomes P.M.", "Germany invades Russia", "JAPANESE ATTACK PEARL HARBOR – U.S. DECLARES WAR ON JAPAN", "HITLER DECLARES WAR ON U.S."]

var eventIndex1: Int = 0
var eventIndex2: Int = 0
var eventIndex3: Int = 0
var eventIndex4: Int = 0

func generateRandomIndex() -> [Int] {
    while (eventIndex1 == eventIndex2) && (eventIndex2 == eventIndex3) && (eventIndex1 == eventIndex3) && (eventIndex1 == eventIndex4) && (eventIndex2 == eventIndex4) && (eventIndex3 == eventIndex4) {
        eventIndex1 = GKRandomSource.sharedRandom().nextInt(upperBound: allEvents.count)
        eventIndex2 = GKRandomSource.sharedRandom().nextInt(upperBound: allEvents.count)
        eventIndex3 = GKRandomSource.sharedRandom().nextInt(upperBound: allEvents.count)
        eventIndex4 = GKRandomSource.sharedRandom().nextInt(upperBound: allEvents.count)
    }
    return [eventIndex1, eventIndex2, eventIndex3, eventIndex4]
}

var eventIndexes = generateRandomIndex()
var index1 = eventIndexes[0]
var index2 = eventIndexes[1]
var index3 = eventIndexes[2]
var index4 = eventIndexes[3]
var event1 = allEvents[index1]
var event2 = allEvents[index2]
var event3 = allEvents[index3]
var event4 = allEvents[index4]

以上代码基本上是使用函数应该生成的无重复随机索引从allEvents数组中提取的。除了每个事件变量之外,在属性初始值设定项中还有一个“不能使用实例成员'allEvents';属性初始化程序在'self'可用之前运行'。有什么建议?不知道如何解决。

1 个答案:

答案 0 :(得分:2)

您不能使用另一个属性的值初始化标准属性(并且没有承诺它们将按照您假设它们的方式在源代码顺序中初始化)。您可以使用另一个属性初始化lazy属性,但这对于此问题来说太复杂了。访问对象的属性需要初始化整个对象,并且在设置所有属性之前不会对其进行初始化。

这种逻辑最好在init中完成。以下是我自己编写的内容(使用shuffle extension):

class ViewController {
    //There's just one of these in the world, not one per class. And I can't
    // imagine it changing (so should be let)
    static let allEvents = ["SOUTHERN STATES PASS LAWS TO DISENFRANCISE BLACKS", "THEODORE ROOSEVELT ELECTED VICE PRESIDENT", "WRIGHT BROTHERS FIRST FLIGHT", "SAN FRANCISCO EARTHQUAKE", "FORD INTRODUCES MODEL T", "WORLD WAR I BEGINS IN EUROPE", "WORLD WAR I ENDS", "TR DIES – CARNEGIE DIES", "GERMAN MONEY HYPER INFLATES", "TREATY OF VERSAILLES, 19TH AMENDMENT", "HINDENBURG ELECTED PRESIDENT OF GERMANY", "STOCK MARKET CRASHES, DEPRESSION BEGINS", "HITLER’S NAZI PARTY GAINS MAJORITY IN PARLIAMENT", "HITLER BEGINS TO TAKE POWER IN GERMANY", "FRANKLIN ROOSEVELT ELECTED PRESIDENT", "FDR INAUGURATED “100 DAYS”", "HINDENBURG DIES, HITLER APPOINTS HIMSELF PRESIDENT  -  “ FUEHRER”", "FDR RE-ELECTED", "German airship HINDENBURG BURNS IN NEW JERSEY", "“MUNICH” – British P.M. Chamberlain agrees that Hitler can have Czechoslovakia.", "Germany invades Holland, Belgium and France – Churchill becomes P.M.", "Germany invades Russia", "JAPANESE ATTACK PEARL HARBOR – U.S. DECLARES WAR ON JAPAN", "HITLER DECLARES WAR ON U.S."]

    // Do you really need both of these? If so, I'd probably actually just keep
    // eventIndices and compute events when needed, but if you access it a lot,
    // this is fine. But "event1" "event2" etc is bad practice
    let eventIndices: [Int]
    let events: [String]

    init() {
        eventIndices = Array(ViewController.allEvents.indices.shuffled().prefix(4))
        events = eventIndices.map { ViewController.allEvents[$0] }
    }
}

好的,我就是这样做的,但如果我们想保持你的风格,我们仍然可以做到。您仍然需要allEvents成为static

class ViewController {

    static let allEvents: [String] = ["SOUTHERN STATES PASS LAWS TO DISENFRANCISE BLACKS", "THEODORE ROOSEVELT ELECTED VICE PRESIDENT", "WRIGHT BROTHERS FIRST FLIGHT", "SAN FRANCISCO EARTHQUAKE", "FORD INTRODUCES MODEL T", "WORLD WAR I BEGINS IN EUROPE", "WORLD WAR I ENDS", "TR DIES – CARNEGIE DIES", "GERMAN MONEY HYPER INFLATES", "TREATY OF VERSAILLES, 19TH AMENDMENT", "HINDENBURG ELECTED PRESIDENT OF GERMANY", "STOCK MARKET CRASHES, DEPRESSION BEGINS", "HITLER’S NAZI PARTY GAINS MAJORITY IN PARLIAMENT", "HITLER BEGINS TO TAKE POWER IN GERMANY", "FRANKLIN ROOSEVELT ELECTED PRESIDENT", "FDR INAUGURATED “100 DAYS”", "HINDENBURG DIES, HITLER APPOINTS HIMSELF PRESIDENT  -  “ FUEHRER”", "FDR RE-ELECTED", "German airship HINDENBURG BURNS IN NEW JERSEY", "“MUNICH” – British P.M. Chamberlain agrees that Hitler can have Czechoslovakia.", "Germany invades Holland, Belgium and France – Churchill becomes P.M.", "Germany invades Russia", "JAPANESE ATTACK PEARL HARBOR – U.S. DECLARES WAR ON JAPAN", "HITLER DECLARES WAR ON U.S."]

    static func generateRandomIndex() -> [Int] {
        var eventIndex1: Int = 0
        var eventIndex2: Int = 0
        var eventIndex3: Int = 0
        var eventIndex4: Int = 0

        while (eventIndex1 == eventIndex2) || (eventIndex2 == eventIndex3) || (eventIndex1 == eventIndex3) || (eventIndex1 == eventIndex4) || (eventIndex2 == eventIndex4) || (eventIndex3 == eventIndex4) {
            eventIndex1 = GKRandomSource.sharedRandom().nextInt(upperBound: allEvents.count)
            eventIndex2 = GKRandomSource.sharedRandom().nextInt(upperBound: allEvents.count)
            eventIndex3 = GKRandomSource.sharedRandom().nextInt(upperBound: allEvents.count)
            eventIndex4 = GKRandomSource.sharedRandom().nextInt(upperBound: allEvents.count)
        }
        return [eventIndex1, eventIndex2, eventIndex3, eventIndex4]
    }

    let index1: Int
    let index2: Int
    let index3: Int
    let index4: Int

    let event1: String
    let event2: String
    let event3: String
    let event4: String

    init() {
        let eventIndexes = ViewController.generateRandomIndex()
        index1 = eventIndexes[0]
        index2 = eventIndexes[1]
        index3 = eventIndexes[2]
        index4 = eventIndexes[3]
        event1 = ViewController.allEvents[index1]
        event2 = ViewController.allEvents[index2]
        event3 = ViewController.allEvents[index3]
        event4 = ViewController.allEvents[index4]
    }
}

如果不需要在此文件之外看到allEvents,您可以通过将其提升到文件范围来简化它:

fileprivate let allEvents: [String] = ["SOUTHERN STATES PASS LAWS TO DISENFRANCISE BLACKS", "THEODORE ROOSEVELT ELECTED VICE PRESIDENT", "WRIGHT BROTHERS FIRST FLIGHT", "SAN FRANCISCO EARTHQUAKE", "FORD INTRODUCES MODEL T", "WORLD WAR I BEGINS IN EUROPE", "WORLD WAR I ENDS", "TR DIES – CARNEGIE DIES", "GERMAN MONEY HYPER INFLATES", "TREATY OF VERSAILLES, 19TH AMENDMENT", "HINDENBURG ELECTED PRESIDENT OF GERMANY", "STOCK MARKET CRASHES, DEPRESSION BEGINS", "HITLER’S NAZI PARTY GAINS MAJORITY IN PARLIAMENT", "HITLER BEGINS TO TAKE POWER IN GERMANY", "FRANKLIN ROOSEVELT ELECTED PRESIDENT", "FDR INAUGURATED “100 DAYS”", "HINDENBURG DIES, HITLER APPOINTS HIMSELF PRESIDENT  -  “ FUEHRER”", "FDR RE-ELECTED", "German airship HINDENBURG BURNS IN NEW JERSEY", "“MUNICH” – British P.M. Chamberlain agrees that Hitler can have Czechoslovakia.", "Germany invades Holland, Belgium and France – Churchill becomes P.M.", "Germany invades Russia", "JAPANESE ATTACK PEARL HARBOR – U.S. DECLARES WAR ON JAPAN", "HITLER DECLARES WAR ON U.S."]

class ViewController {
    ...
        event1 = allEvents[index1]
        event2 = allEvents[index2]
        event3 = allEvents[index3]
        event4 = allEvents[index4]
    ...

但所有这一切的关键教训是,在初始化对象之前,您无法访问对象中的属性。