iOS快捷方便的初始化器自我使用。init调用

时间:2022-02-04 19:21:10

so I have been trying to create a "Period" class, with the following attributes:

因此,我一直在尝试创建一个具有以下属性的“Period”类:

class PTPeriod {

    // MARK: Stored Properties

    var start: Date
    var end: Date
    var place: PTPlace?


//MARK: DESIGNATED NITIALIZER
init(start: Date, end: Date, place: PTPlace? = nil) {
    self.start = start
    self.end = end
    self.place = place

}

And I want to initialize it with a convenience init that accepts a dictionary like the following:

我想用一个方便的init来初始化它接受一个像下面这样的字典:

        {
           "close" : {
              "day" : 1,
              "time" : "0000"
           },
           "open" : {
              "day" : 0,
              "time" : "0900"
           }
        }

This is my initializer, originally I put the heavy lifting into a helper method. However, i was getting the same error I have now so I removed the helper method and the error is still occurring. Unsure where it thinks I am calling self.

这是我的初始化器,最初我将繁重的工作放入助手方法中。但是,我得到了与现在相同的错误,所以我删除了helper方法,错误仍然在发生。不确定它认为我在哪里打电话。

UPDATE: moved the date formatting into a date formatter extension, but the error still persists! unsure WHY. new init shown:

更新:将日期格式移动到日期格式化程序扩展中,但是错误仍然存在!不知道为什么。新的init如图所示:

My new Convenience init:

我的新便利初始化:

// MARK: Convenience init for initializing periods pulled from Google Place API
convenience init?(placeData: [String:Any], place: PTPlace? = nil) throws {
    var start: Date? = nil
    var end: Date? = nil
    var formatter = DateFormatter()

    do {
        for (key, value) in placeData {
            let period = value as! [String: Any]
            if (key == "open") {
                start = try formatter.upcoming_date(with: period)
            } else if (key == "close") {
                end = try formatter.upcoming_date(with: period)
            } else {
                break
            }
        }
        if (start != nil && end != nil) { self.init(start: start!, end: end!, place: place) }
        else { print("we f'd up") }

    }

    catch { print(error.localizedDescription) }
}

Here is my DateFormatter.upcoming_date method:

这是我的dateformat。upcoming_date方法:

   func upcoming_date(with googlePlacePeriod: [String: Any]) throws -> Date? {
    if let day = googlePlacePeriod["day"] as? Int {
        if (day < 0) || (day > 6) { throw SerializationError.invalid("day", day) } // throw an error if day is not between 0-6
        if let time = googlePlacePeriod["time"] as? String {
            if time.characters.count != 4 { throw SerializationError.invalid("time", time) } // throw an error if time is not 4 char long
            var upcoming_date: Date
            let gregorian = Calendar(identifier: .gregorian)

            let current_day_of_week = Date().getDayOfWeekInt()
            let dayOfPeriod = day + 1

            ///TRUST THAT THIS WORKS... NO JODAS
            var distance = dayOfPeriod - current_day_of_week // inverse = false

            if (dayOfPeriod < current_day_of_week) {
                switch distance {
                case -1: distance = 6
                case -2: distance = 5
                case -3: distance = 4
                case -4: distance = 3
                case -5: distance = 2
                case -6: distance = 1
                default: break
                }
            }
            /** time example: "1535" translates into 3:35PM
             first two characters in string are "hour" (15)
             last two characters in string are "minute(35)
             **/

            let hour = Int(time.substring(to: time.index(time.startIndex, offsetBy: 2)))!
            let minute = Int(time.substring(from: time.index(time.endIndex, offsetBy: -2)))


            upcoming_date = Date().fastForward(amount: distance, unit: "days", inverse: false)!
            var components = gregorian.dateComponents([.year, .month, .day, .hour, .minute, .second], from: upcoming_date)
            components.hour = hour
            components.minute = minute
            upcoming_date = gregorian.date(from: components)!
            return upcoming_date
        }
        else { throw SerializationError.missing("time") }
    }
    else { throw SerializationError.missing("day") }
}

1 个解决方案

#1


1  

You have a failable initializer, so if it fails, you must return nil to let it know it failed:

你有一个可失败的初始化器,所以如果它失败了,你必须返回nil让它知道它失败了:

if (start != nil && end != nil) { 
    self.init(start: start!, end: end!, place: place) }
} else { 
    print("we f'd up") 
    return nil
}

Also, in your do-catch, you need to either

同样,在你的“接球”游戏中,你需要两者之一

  • re-throw the error in the catch block

    重新抛出捕获块中的错误

    catch {
        print(error.localizedDescription)
        throw error
    }
    
  • eliminate the do-catch blocks altogether; or

    完全消除执行捕获块;或

  • just return nil:

    只是返回nil:

    catch {
        print(error.localizedDescription)
        return nil
    }
    

    If you do this, you'd presumably not define this failable initializer as one that throws because you're no longer throwing.

    如果您这样做,您可能不会将这个可失败的初始化器定义为抛出,因为您不再抛出。


Given that you're unlikely to do anything meaningful with the thrown error, I'd just make it a failable initializer that doesn't throw:

考虑到您不太可能对抛出的错误做任何有意义的事情,我将它设置为一个不会抛出的可失败初始化器:

convenience init?(placeData: [String: Any], place: PTPlace? = nil) {
    var start: Date?
    var end: Date?
    let formatter = DateFormatter()

    for (key, value) in placeData {
        let period = value as! [String: Any]
        if key == "open" {
            start = try? formatter.upcoming_date(with: period)
        } else if key == "close" {
            end = try? formatter.upcoming_date(with: period)
        } else {
            break  // I'm not sure why you're doing this; it seems extremely imprudent (esp since dictionaries are not ordered)
        }
    }

    if let start = start, let end = end {
        self.init(start: start, end: end, place: place)
    } else {
        print("either start or end were not found")
        return nil
    }
}

#1


1  

You have a failable initializer, so if it fails, you must return nil to let it know it failed:

你有一个可失败的初始化器,所以如果它失败了,你必须返回nil让它知道它失败了:

if (start != nil && end != nil) { 
    self.init(start: start!, end: end!, place: place) }
} else { 
    print("we f'd up") 
    return nil
}

Also, in your do-catch, you need to either

同样,在你的“接球”游戏中,你需要两者之一

  • re-throw the error in the catch block

    重新抛出捕获块中的错误

    catch {
        print(error.localizedDescription)
        throw error
    }
    
  • eliminate the do-catch blocks altogether; or

    完全消除执行捕获块;或

  • just return nil:

    只是返回nil:

    catch {
        print(error.localizedDescription)
        return nil
    }
    

    If you do this, you'd presumably not define this failable initializer as one that throws because you're no longer throwing.

    如果您这样做,您可能不会将这个可失败的初始化器定义为抛出,因为您不再抛出。


Given that you're unlikely to do anything meaningful with the thrown error, I'd just make it a failable initializer that doesn't throw:

考虑到您不太可能对抛出的错误做任何有意义的事情,我将它设置为一个不会抛出的可失败初始化器:

convenience init?(placeData: [String: Any], place: PTPlace? = nil) {
    var start: Date?
    var end: Date?
    let formatter = DateFormatter()

    for (key, value) in placeData {
        let period = value as! [String: Any]
        if key == "open" {
            start = try? formatter.upcoming_date(with: period)
        } else if key == "close" {
            end = try? formatter.upcoming_date(with: period)
        } else {
            break  // I'm not sure why you're doing this; it seems extremely imprudent (esp since dictionaries are not ordered)
        }
    }

    if let start = start, let end = end {
        self.init(start: start, end: end, place: place)
    } else {
        print("either start or end were not found")
        return nil
    }
}