Xcode 9に更新した後、私のプロジェクト(元々Swift 3)で作成された)に紫色の警告が表示される理由がわかりません:UITextField.textメインスレッドからのみ使用する必要があります
テキストフィールドが空の場合にのみIfステートメントをチェックインしています...スクリーンショットを添付しています。
ログインマネージャーはメインスレッド以外のスレッドでクロージャーを実行しているため、メインスレッド以外でユーザーインターフェイス要素を使用することはできません。
他の人は、サイドスレッドのUIプロパティを読むだけで大丈夫だと言っており、おそらく正しいと言っていますが、絶対的な保証はなく、個人的には警告に注意します。たとえば、これらのプロパティにアクセスすると、副作用が発生する可能性があります。おそらく、それらの値はどこかにキャッシュされており、メインスレッドは、アクセスしたいときにプロパティを更新または削除している最中です。
警告を消音する適切な方法は、メインスレッドでクロージャーを実行することです。
LoginManager.checkLoginStatus {
isLoggedIn in
DispatchQueue.main.async {
// Do all your UI stuff here
}
}
このように、クロージャを実行するスレッドは、常にメインスレッドで実行されるメインキューで実行されるようにコードをスケジュールする以外は何もしません。
XCode 9には メインスレッドチェッカー ツールが含まれており、UIKit関連の処理がメインスレッドで発生しているかどうかをチェックします。バックグラウンドスレッドからUIKitに触れると問題が発生するのを防ぐためです。
ただし、このツールをそのままにしておくことをお勧めしますが、あまりにも面倒な場合は、オフにすることができます。
XCode-> Edit Scheme-> Target-> Diagnostics-> Uncheck RunTime APIChecking
DispatchQueue.main.asyncを追加するだけでこれを防ぐことができ、Swiftドキュメントで推奨されています。
DispatchQueue.main.async {
//code that caused error goes here
}
これがAppleメインスレッドチェッカーのガイドラインです
- Xcode 9の新機能–メインスレッドチェッカー。
- バックグラウンドスレッドからのUIAPIの誤用の検出を有効にする
- メインスレッドで行われていないAppKit、UIKit、およびWebKitメソッド呼び出しを検出します。
- デバッグ中に自動的に有効になり、スキームエディタの[診断]タブで無効にできます。
- メインスレッドチェッカーはSwiftおよびC言語で動作します。
これを試してください:コードを次のコードに置き換えて、を参照してください。これは、警告を無効にすることなく、永続的な解決策です。
@IBAction fund saveButtonTapped(_ sender: Any) {
LoginManager.checkLoginStatus { isLogged in
if isLogged {
// Updates your UIs on main queue
DispatchQueue.main.async(execute: {
if self.priceTextField.text == "" {
GlobalVariables.sharedManager.itemPrice = 0
} else {
GlobalVariables.sharedManager.itemPrice = Double(self.priceTextField.text!)!
}
if self.titleTextView.text == "" {
GlobalVariables.sharedManager.expenseTitle = "N/A"
} else {
GlobalVariables.sharedManager.expenseTitle = self.titleTextView.text!
}
if self.descriptionTextView.text == "" {
GlobalVariables.sharedManager.expenseDescription = "N/A"
} else {
GlobalVariables.sharedManager.expenseDescription = self.descriptionTextView.text!
}
if self.categoryPickerTextFld.text == "" {
GlobalVariables.sharedManager.expenseCategory = "N/A"
} else {
GlobalVariables.sharedManager.expenseCategory = self.categoryPickerTextFld.text!
}
if self.imageView.image == nil {
GlobalVariables.sharedManager.expenseSelectedImage = nil
} else {
GlobalVariables.sharedManager.expenseSelectedImage = self.imageView.image
}
})
}
}
}
または、プロジェクトターゲットからメインスレッドチェッカーを無効にすることで、警告を無効にすることができます
(Xcodeプロジェクトターゲット-デバイスリストの下)>>スキームの編集>>ターゲット>>診断>>ランタイムAPIチェック-チェック解除
問題はまさにそれです-あなたはバックグラウンドスレッドからUI要素を使用しています。メインスレッドからコードにアクセスするには、コードを変更してみてください。
Xcode 9には新機能があります。実行時にこのような問題をチェックし、実行中に報告することができます。
本当に必要ない場合は、スキーム設定で無効にすることができます。スキームの編集...->(スキームを選択)->診断->「メインスレッドチェッカー」を無効にする
警告は、textFieldが空であるかどうかのみをチェックしており、UIで何も変更していないことを示しているため、過度に攻撃的であるように見えます。警告は、メインスレッドからのUI要素の使用を阻止しようとしています。これはもちろん悪いことではありませんが、あなたのようなエッジケースは考慮されていません。