切換語言為:簡體

iOS APP 中由於時間制式設定導致的 Bug 排查與修復過程

  • 爱糖宝
  • 2024-07-05
  • 2074
  • 0
  • 0

我們的 iOS APP 有一個小 Bug,場景簡化後是這樣:

介面返回一個時間字串,APP 裡比較它與當前時間,如果當前時間晚於它,就顯示一個按鈕,否則不顯示。

本來是一個很簡單的邏輯,但是,有一部分使用者反饋,按鈕該顯示的時候卻沒有顯示。

分析

結合使用者反饋的資訊,經過多次嘗試後,才發現這個行為竟然與使用者手機的時間制式有關——如果使用者手機設定裡的 24小時制 開關沒有開啟,那麼這個 Bug 就會出現。

相關的邏輯是這樣寫的:

NSDate *remoteDate = [NSDate dateFromStr:remoteDateString];
if (remoteDate) {
    // 比較 remoteDate 和 本地當前時間,控制按鈕顯隱
}


這個 dateFromStr: 是一個 category 方法,實現是這樣的:

+ (NSDate*)dateFromStr:(NSString *)dateStr {
    NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    return [dateFormatter dateFromString:dateStr];
}


經過除錯,發現 remoteDate 在 24小時制 開關關閉時,返回的是 nil,而在開啟時,返回的是正確的時間。

蘋果官方文件裡,NSDateFormatter 的 dateFromString: 方法是這樣描述的:

Returns a date representation of a given string interpreted using the receiver’s current settings.

Return Value
A date representation of string. If dateFromString: can’t parse the string, returns nil.

同時還給出了 Working With Fixed Format Date Representations 的參考連結,裡面有說明:

When working with fixed format dates, such as RFC 3339, you set the dateFormat property to specify a format string. For most fixed formats, you should also set the locale property to a POSIX locale ("en_US_POSIX"), and set the timeZone property to UTC.

這個頁面裡還給出了一個 QA 連結 Technical Q&A QA1480 “NSDateFormatter and Internet Dates”,裡面有這樣的描述:

On iOS, the user can override the default AM/PM versus 24-hour time setting (via Settings > General > Date & Time > 24-Hour Time), which causes NSDateFormatter to rewrite the format string you set, which can cause your time parsing to fail.
...
On the other hand, if you're working with fixed-format dates, you should first set the locale of the date formatter to something appropriate for your fixed format.

裡面提到了使用者可以透過設定 24小時制 來影響 NSDateFormatter 的行為,還提到了當嘗試把固定格式的日期字串轉換成日期物件時,應該設定 locale

至此破案了,這個 Bug 就是由於沒有設定 NSDateFormatter 的 locale 屬性導致的。

解決

修改後的程式碼是這樣的,僅加了一行 locale 設定:

+ (NSDate*)dateFromStr:(NSString *)dateStr {
    NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]];
    return [dateFormatter dateFromString:dateStr];
}


經過測試功能正常了,不管使用者手機的 24小時制 開關是否開啟,都能正常解析服務端返回的時間字串了。

參考

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.