[解決済み] NSDateFormatterのロケール「feechur」に対応する最善の方法を教えてください。
質問
どうやら
NSDateFormatter
には、思わぬところで噛み付く機能があります。 単純な "fixed" の書式操作を行うと、次のような問題が発生します。
NSDateFormatter* fmt = [[NSDateFormatter alloc] init];
[fmt setDateFormat:@"yyyyMMddHHmmss"];
NSString* dateStr = [fmt stringFromDate:someDate];
[fmt release];
しかし、24時間制の携帯電話を使用している人が、設定で12時間/24時間スイッチを12時間に設定すると、米国やほとんどの地域で正常に動作します。 そうすると、上記のように文字列の末尾に "AM" や "PM" が追加されるようになる。
(参照:例. NSDateFormatter, 私は何か間違っているのでしょうか、それともバグなのでしょうか? )
(そして https://developer.apple.com/library/content/qa/qa1480/_index.html )
どうやらAppleはこれを "BAD" -- Broken As Designed と宣言し、修正するつもりはないようです。
この回避策は、どうやら日付フォーマッタのロケールを特定の地域、一般的には米国に設定することらしいが、これは少し面倒だ。
NSLocale *loc = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
[df setLocale: loc];
[loc release];
オンシツーツーシツでは悪くないのですが、10種類くらいのアプリを扱っていて、最初に見たアプリにはこのシナリオのインスタンスが43個もあります。
そこで、コードをわかりにくくすることなく、すべてを変更する労力を最小限にするためのマクロ/オーバーライドされたクラス/何か賢いアイデアはないでしょうか? (私の最初の直感は、initメソッドでロケールを設定するバージョンでNSDateFormatterをオーバーライドすることです。 alloc/init 行と追加された import の 2 行を変更する必要があります)。
追加
これは、私がこれまでに考え出したもので、すべてのシナリオで機能するようです。
@implementation BNSDateFormatter
-(id)init {
static NSLocale* en_US_POSIX = nil;
NSDateFormatter* me = [super init];
if (en_US_POSIX == nil) {
en_US_POSIX = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
}
[me setLocale:en_US_POSIX];
return me;
}
@end
バウンティ!
火曜日の正午までに私が見た最も良い(正当な)提案/批評に懸賞金を授与します。[下記参照 -- 期限延長しました]。
更新情報
OMZの提案について、以下のようなことがわかりました。
以下、カテゴリ版 -- hファイルです。
#import <Foundation/Foundation.h>
@interface NSDateFormatter (Locale)
- (id)initWithSafeLocale;
@end
カテゴリmファイル。
#import "NSDateFormatter+Locale.h"
@implementation NSDateFormatter (Locale)
- (id)initWithSafeLocale {
static NSLocale* en_US_POSIX = nil;
self = [super init];
if (en_US_POSIX == nil) {
en_US_POSIX = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
}
NSLog(@"Category's locale: %@ %@", en_US_POSIX.description, [en_US_POSIX localeIdentifier]);
[self setLocale:en_US_POSIX];
return self;
}
@end
コードです。
NSDateFormatter* fmt;
NSString* dateString;
NSDate* date1;
NSDate* date2;
NSDate* date3;
NSDate* date4;
fmt = [[NSDateFormatter alloc] initWithSafeLocale];
[fmt setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
dateString = [fmt stringFromDate:[NSDate date]];
NSLog(@"dateString = %@", dateString);
date1 = [fmt dateFromString:@"2001-05-05 12:34:56"];
NSLog(@"date1 = %@", date1.description);
date2 = [fmt dateFromString:@"2001-05-05 22:34:56"];
NSLog(@"date2 = %@", date2.description);
date3 = [fmt dateFromString:@"2001-05-05 12:34:56PM"];
NSLog(@"date3 = %@", date3.description);
date4 = [fmt dateFromString:@"2001-05-05 12:34:56 PM"];
NSLog(@"date4 = %@", date4.description);
[fmt release];
fmt = [[BNSDateFormatter alloc] init];
[fmt setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
dateString = [fmt stringFromDate:[NSDate date]];
NSLog(@"dateString = %@", dateString);
date1 = [fmt dateFromString:@"2001-05-05 12:34:56"];
NSLog(@"date1 = %@", date1.description);
date2 = [fmt dateFromString:@"2001-05-05 22:34:56"];
NSLog(@"date2 = %@", date2.description);
date3 = [fmt dateFromString:@"2001-05-05 12:34:56PM"];
NSLog(@"date3 = %@", date3.description);
date4 = [fmt dateFromString:@"2001-05-05 12:34:56 PM"];
NSLog(@"date4 = %@", date4.description);
[fmt release];
その結果
2011-07-11 17:44:43.243 DemoApp[160:307] Category's locale: <__NSCFLocale: 0x11a820> en_US_POSIX
2011-07-11 17:44:43.257 DemoApp[160:307] dateString = 2011-07-11 05:44:43 PM
2011-07-11 17:44:43.264 DemoApp[160:307] date1 = (null)
2011-07-11 17:44:43.272 DemoApp[160:307] date2 = (null)
2011-07-11 17:44:43.280 DemoApp[160:307] date3 = (null)
2011-07-11 17:44:43.298 DemoApp[160:307] date4 = 2001-05-05 05:34:56 PM +0000
2011-07-11 17:44:43.311 DemoApp[160:307] Extended class's locale: <__NSCFLocale: 0x11a820> en_US_POSIX
2011-07-11 17:44:43.336 DemoApp[160:307] dateString = 2011-07-11 17:44:43
2011-07-11 17:44:43.352 DemoApp[160:307] date1 = 2001-05-05 05:34:56 PM +0000
2011-07-11 17:44:43.369 DemoApp[160:307] date2 = 2001-05-06 03:34:56 AM +0000
2011-07-11 17:44:43.380 DemoApp[160:307] date3 = (null)
2011-07-11 17:44:43.392 DemoApp[160:307] date4 = (null)
携帯電話[iPod Touchにする]はイギリスに設定され、12/24スイッチは12に設定されています。 この2つの結果には明らかな違いがあり、私はカテゴリー版の方が間違っていると判断しています。 なお、カテゴリ版のログは実行されている(コードに置かれたストップもヒットしている)ので、単にコードが使われていないだけではありません。
バウンティーの更新です。
まだ該当する返信がないので、懸賞金の期限をもう1~2日延長することにします。
賞金は21時間後に終了します。たとえその答えが私の場合あまり役に立たなかったとしても、最も努力した人に贈られます。
不思議な観察
カテゴリの実装を少し修正。
#import "NSDateFormatter+Locale.h"
@implementation NSDateFormatter (Locale)
- (id)initWithSafeLocale {
static NSLocale* en_US_POSIX2 = nil;
self = [super init];
if (en_US_POSIX2 == nil) {
en_US_POSIX2 = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
}
NSLog(@"Category's locale: %@ %@", en_US_POSIX2.description, [en_US_POSIX2 localeIdentifier]);
[self setLocale:en_US_POSIX2];
NSLog(@"Category's object: %@ and object's locale: %@ %@", self.description, self.locale.description, [self.locale localeIdentifier]);
return self;
}
@end
基本的には、静的ロケール変数の名前を変更し(サブクラスで宣言された静的変数と衝突する場合に備えて)、追加のNSLogを追加しただけのことです。 しかし、そのNSLogが表示するものを見てください。
2011-07-15 16:35:24.322 DemoApp[214:307] Category's locale: <__NSCFLocale: 0x160550> en_US_POSIX
2011-07-15 16:35:24.338 DemoApp[214:307] Category's object: <NSDateFormatter: 0x160d90> and object's locale: <__NSCFLocale: 0x12be70> en_GB
2011-07-15 16:35:24.345 DemoApp[214:307] dateString = 2011-07-15 04:35:24 PM
2011-07-15 16:35:24.370 DemoApp[214:307] date1 = (null)
2011-07-15 16:35:24.378 DemoApp[214:307] date2 = (null)
2011-07-15 16:35:24.390 DemoApp[214:307] date3 = (null)
2011-07-15 16:35:24.404 DemoApp[214:307] date4 = 2001-05-05 05:34:56 PM +0000
見ての通り、setLocaleは単にしなかっただけです。 フォーマッタのロケールは en_GB のままです。 どうやら、カテゴリ内のinitメソッドについて、何か奇妙なことがあるようです。
最終回答
をご覧ください。 回答 の下にあります。
解決方法は?
ダッ!
アハッ!」と思うこともあれば、「ダッ!」と思うこともある。 のカテゴリーでは
initWithSafeLocale
the "super"
init
は、次のようにコード化されました。
self = [super init];
. の SUPERCLASS になります。
NSDateFormatter
を使用することはできませんが
init
は
NSDateFormatter
オブジェクトそのものです。
どうやらこの初期化が省略された場合のようです。
setLocale
これは、おそらくオブジェクトに何らかのデータ構造が欠けているためと思われます。 オブジェクトの
init
から
self = [self init];
は
NSDateFormatter
の初期化が行われ
setLocale
が再び幸せになる。
以下は、カテゴリの.m.の"final"のソースです。
#import "NSDateFormatter+Locale.h"
@implementation NSDateFormatter (Locale)
- (id)initWithSafeLocale {
static NSLocale* en_US_POSIX = nil;
self = [self init];
if (en_US_POSIX == nil) {
en_US_POSIX = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
}
[self setLocale:en_US_POSIX];
return self;
}
@end
関連
-
[解決済み] iOSまたはmacOSで、インターネット接続が有効かどうかを確認するにはどうすればよいですか?
-
[解決済み] NSの接頭辞はどういう意味ですか?
-
[解決済み] Objective-CでNSNotificationCenterを通してメッセージを送受信する?
-
[解決済み] synthesize vs @dynamic、その違いとは?
-
[解決済み] UINavigationBarの1px下の行を非表示にする方法
-
[解決済み] iOSシミュレータでスクリーンショットを撮る
-
[解決済み] ブロック(__block)」というキーワードはどういう意味ですか?
-
[解決済み] Swiftの配列を文字列に変換するには?
-
[解決済み】Objective-Cのコードをユニットテストするのに最適な方法は何ですか?
-
[解決済み】アプリ内でロケールを変更する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
iOSコンパイルポッドでエラー CocoaPods could not find compatible versions for pod "XXXXX" が報告される。
-
[解決済み] Xcodeにおけるバージョンとビルドの比較
-
[解決済み] UITextViewのサイズをコンテンツに合わせるには?
-
[解決済み] iOSシミュレータでスクリーンショットを撮る
-
[解決済み] UIButtonのタイトルを左揃えにするにはどうしたらよいですか?
-
[解決済み] テキストフィールドを移動する方法(次へボタン/完了ボタン)
-
[解決済み] NSOperationとGrand Central Dispatchの比較
-
[解決済み] iPadマルチタスクのサポートには、これらの方向が必要です。
-
[解決済み] UIImageのサイズを変更する最も簡単な方法?
-
[解決済み] UITableView - トップにスクロールする