カテゴリー
SugiBlog Webエンジニアのためのお役立ちTips

iOS13で発生するクラッシュ NSInternalInconsistencyException

GoogleMapを使用したiOSアプリを使っていて、地図を表示しているときに急にクラッシュするようになったので原因を調べました。
発生するエラーの内容は以下の通り

Fatal Exception: NSInternalInconsistencyException
Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.

iOS13で内部仕様が変わったことによるもののようです。

どうもバックグラウンドスレッドからUIを触るなということらしいですが、
そんなことはしていないつもりでした。
おそらくこれまでよりも厳密になったのでしょうか…。
とにかく対応するしかありません。

元のソースコード

let session = URLSession(configuration: URLSessionConfiguration.default)

let task = session.dataTask(with: URLRequest(url: Foundation.URL(string: url)!), completionHandler: { (data, response, error) in
    if let urlContent = data {
        print(urlContent)
    }
})
task.resume()

修正したコード

let session = URLSession(configuration: URLSessionConfiguration.default)

let task = session.dataTask(with: URLRequest(url: Foundation.URL(string: url)!), completionHandler: { (data, response, error) in
    if let urlContent = data {
        DispatchQueue.main.sync {
            print(urlContent)
        }
    }
})
task.resume()
8,925 views

Realm.addでコンパイルエラー

Realm.addメソッドで以下のようなコンパイルエラーが出ました。

'add(_:update:)' is unavailable: Pass .error, .modified or .all rather than a boolean. .error is equivalent to false and .all is equivalent to true.

どうやら第2引数にbool値を与える仕様が変わった模様。
第2引数に与える値はRealm.UpdatePolicyだそうで、
これまでfalseにしていた場合は.error、trueにしていた場合は.allを指定すればいいようです。

Xcode 11.2.1
Swift 5

799 views

JSONデータをCodableを使って構造化する

JSONデータを解析するためにJSONSerializerを使っていましたが、Swift4からもっと簡単にできるようになったのでやってみました。

CodableというプロトコルがSwift4から新たに追加されました。
これを利用すれば簡単に構造体に落とし込むことができます。

まずはデータを扱う構造体を宣言します。
Codableと付け加えましょう。

struct myData: Codable {
    
    let ID_C: Int
    let NAME_C: String
    let COMMENT_C: String? //nullを許容
    let DATE_C: String

}

次にWEB上からデータを取得するため、URLSessionを使用します。

let session = URLSession(configuration: URLSessionConfiguration.default)
let url = "http://www.example.jp/json.php" //JSONデータを取得するURL

単純に文字列で出力してみましょう。 続きを読む…»

2,221 views

図形を描画して内部の面積を計測する

iOSアプリ上のGoogleMapで図形を描画し、そのパス内部の面積を計測することができます。

まずは図形を描画します。

// Create a rectangular path
let rect = GMSMutablePath()
rect.add(CLLocationCoordinate2D(latitude: 37.36, longitude: -122.0))
rect.add(CLLocationCoordinate2D(latitude: 37.45, longitude: -122.0))
rect.add(CLLocationCoordinate2D(latitude: 37.45, longitude: -122.2))
rect.add(CLLocationCoordinate2D(latitude: 37.36, longitude: -122.2))

// Create the polygon, and assign it to the map.
let polygon = GMSPolygon(path: rect)
polygon.fillColor = UIColor(red: 0.25, green: 0, blue: 0, alpha: 0.05);
polygon.strokeColor = .black
polygon.strokeWidth = 2
polygon.map = mapView

面積を計測

let a: Double = GMSGeometryArea(polygon.path!)

JavaScriptのAPIではパスが閉じている必要がありましたが、
こちらは閉じていなくても閉じているものと仮定してくれるようです。

ただ、実際に使ってみた結果、JavaScript APIのほうで測った面積と24m²ほど差がありました。

JavaScriptでの計測はこちら→GoogleMapで面積計測(v3)

Xcode: 9.4.1
Swift: 3.3
OS: High Sierra 10.13.6

1,624 views

ナビゲーションバーのタイトルを変更

UINavigationControllerのタイトルを動的に変更することができます。
短いですが、メモ的に。

// タイトルをセット
self.navigationItem.title = "テストタイトル"

Xcode: 9.4.1
Swift: 3.3
OS: High Sierra 10.13.6

3,457 views