20210322のiOSに関する記事は5件です。

この素晴らしいSwiftUIにCoreDataを!【初期設定編】

こんにちは.
Sadmachineです.
いまさらながら,このすばを見始めました.
めぐみんかわいい.

この記事ではアプリ開発の基礎...
Xcodeプロジェクトの開始〜CoreDataの初期設定までをわかりやすく解説します!
スクリーンショットも適宜つけるので参考にしてください!

CoreDataのことだけ知りてえよ! っていう君はSection 2から見るといいと思うよ.

LGTMたくさんしてね!!!

そもそも「CoreData」ってなに?

CoreDataとは...

Xcode上から簡単にDBのようにデータ構造を設定できたり,アプリ上で扱うデータを保存,削除,更新するプログラムを簡単に書けるようになる仕組み
参考記事:やっとわかったSwift/CoreData入門 【part1:概念編】

とのこと.
もっと簡単に言うと...

アプリのデータをiPhoneの端末本体内のストレージに保存して永続化するために必要なもの!

って感じでしょうか.
ざっくりすぎたかな...

とりあえず,詳しいことは参考記事を見てみてね!

目次

0. 開発環境

筆者の開発環境をめっちゃ簡単に紹介します.

  • Xcode 12.3
  • SwitfUI

以上.
もっと詳しく知りたい人はTwitterに凸して,どうぞ.

1. プロジェクトを作ろう!

以下の項目はXcodeをインストールしてある前提で話していきます.

1-1 Xcodeの起動&プロジェクトファイルを作る

スクリーンショット 2021-03-22 21 54 25
Xcodeを起動すると上のような画面が出てくるので,Create a new Xcode Projectを押してください.

スクリーンショット 2021-03-22 22 00 01
そうするとこんな画面が出るので[App]を選択してNext.

スクリーンショット 2021-03-22 22 00 26
Product Nameとかは適当につけます.

白抜きの部分も適当な名前をつけてください.
重要なのは赤く囲まれたUse CoreDataのチェックマークです.
忘れずにつけましょう.

スクリーンショット 2021-03-22 22 06 45
こんな感じの画面になってればOK!

↑MugenMemoというプロジェクト名になっていますが,これがProduct Nameです.
人によって違います.

プロジェクトの作成は完了です.

1-2 ContentView.swiftの修正

1-1の最後の画像の通り,エラーが吐かれています.
とりあえず「ContentView.swift」の中身を以下のようにすればOKです.

ContentView.swift
import SwiftUI
import CoreData

struct ContentView: View {
    var body: some View {
        NavigationView {
            List {
                Text("TEST")
            }
        }
    }



}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

スクリーンショット 2021-03-22 22 12 31
ContentView.swiftの中身を変えればこんな感じでList形式でTESTという文字が出てくるはずです.
↑図ではResumeを使ってますが,エミュレーターでも同じように出ます.

これでSection 1 プロジェクトを作ろうは完了です!

2. CoreDataの初期設定をしよう

CoreDataの初期設定を進めていきます.

2-1 Entityの新規追加

スクリーンショット 2021-03-22 22 25 31
MugenMemo.xcdatamodeldを開いて,↑図のようにEntityを作ります.

Entityを作るには,Add Entityを選択して適当な名前をつけます.
今回はMemoにしました.
Entityを作ったら,Attributeを追加します.
Attributes下の+を押して,Attribute:title Type:String にします.

2-2 Entityのclass変更

ENTITESのMemoを押してDatamodelInspecter(右側の帯のいろいろな設定でるやつ)を表示させます.

スクリーンショット 2021-03-22 22 29 59
↑図の赤く囲った部分Class CodegenのClass DefinitionをManual/Noneに変更します.

スクリーンショット 2021-03-22 22 34 15
こんな感じになってればOKです.

2-3 CoreDataの管理に必要なコードを手動生成

Entity名+CoreDataClass.swift
Entity名+CoreDataProperties.swift
がないとCoreDataは使えないので手動で生成します.

スクリーンショット 2021-03-22 22 40 05
ENTITESのMemoを選択した状態で,Editor/NSManagedObject Subclass...を選択.
Memo+CoreDataClass.swift
Memo+CoreDataProperties.swift
の2つができたはずです.

Memo+CoreDataClass.swift
import Foundation
import CoreData

@objc(Memo)
public class Memo: NSManagedObject {

}
Memo+CoreDataProperties.swift
import Foundation
import CoreData


extension Memo {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Memo> {
        return NSFetchRequest<Memo>(entityName: "Memo")
    }

    @NSManaged public var title: String?

}

extension Memo : Identifiable {

}

以上でSection 2 CoreDataの初期設定をしよう は完了です.

2-* もしもEntityにAttributeを追加したら...

Entityに別の属性のAttributeを追加した場合はEntity名+CoreDataProperties.swiftを編集します.
例えば,MemoにAttribute:text Type:Stringを追加した場合は以下のように編集しましょう.

Memo+CoreDataProperties.swift
import Foundation
import CoreData


extension Memo {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Memo> {
        return NSFetchRequest<Memo>(entityName: "Memo")
    }

    @NSManaged public var title: String?
    @NSManaged public var text: String? // ここを追加

}

extension Memo : Identifiable {

}

@NSManaged public var text: String?」を追加することで完了です.

まとめ

プロジェクトの開始〜CoreDataの初期設定までをわかりやすく解説しました.
長くなりそうだったので今回はここまで.

次回は,

CoreDataの読み書きをしてみよう!

の予定です.
実際にSwiftUIを使いながらCoreDataに適当な文字列を追加し,保存するという一連の流れをやってみます.

備忘録的なまとめですが,誰かの参考になれば嬉しいです.
少しでも参考になりましたらLGTMやフォロー,Twitterでの拡散をしていただければ幸いです.

次回の記事:この素晴らしいSwiftUIにCoreDataを!【CoreData読み書き編】

参考サイト

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

複数行のUILabelのテキストを垂直方向に中央揃えにする方法(iOS)

はじめに

UILabelのテキストは工夫しないと垂直方向に中央揃えにできません。
先日私が教えてもらって実現した方法を紹介します。

環境

  • OS:macOS Big Sur 11.1
  • Xcode:12.4 (12D4e)
  • Swift:5.3.2
  • iOS:14.4

やり方

  1. 透明のビューを配置し、適切にAuto Layoutを設定する
  2. ラベルを透明のビューの上に配置し、Align Center Y to:に設定する
    スクリーンショット 2021-03-22 12.41.44.png

以下の画面の「名前」がこの方法で実現しています。
Simulator Screen Shot - iPhone SE (2nd generation) - 2021-03-21 at 20.36.22.png

「ドラゴン」など名前が1行でも垂直方向に中央揃えになっていることがわかります。

おわりに

これだけで実現できます!
UILabelはデフォルトでサイズが可変なので、それを利用した方法です。

参考リンク

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Could not build the application for the simulator. Error launching application on iPhone xx と怒られたとき

flutterのversionを変えたりしてiOSシュミレーターが原因でビルドが通らなくなったときすること

fluuter ios build error の対処

①「flutter clean」を実行する

プロジェクトフォルダ内
flutter_project_name % flutter clean
Cleaning Xcode workspace...                                         3.0s
Deleting build...                                                    8ms
Deleting .dart_tool...                                               0ms
Deleting Generated.xcconfig...                                       0ms
Deleting flutter_export_environment.sh...                            0ms
Deleting Flutter.podspec...                                          0ms
Deleting .flutter-plugins-dependencies...                            0ms
Deleting .flutter-plugins...                                         0ms

②「pod deintegrate」を実行する

プロジェクトフォルダ内
flutter_project_name % pod deintegrate 
[!] A valid Xcode project file is required.

Usage:

    $ pod deintegrate [XCODE_PROJECT]

      Deintegrate your project from CocoaPods. Removing all traces of CocoaPods from
      your Xcode project.

      If no xcodeproj is specified, then a search for an Xcode project will be made in
      the current directory.

Options:

    --project-directory=/project/dir/   The path to the root of the project directory
    --allow-root                        Allows CocoaPods to run as root
    --silent                            Show nothing
    --verbose                           Show more debugging information
    --no-ansi                           Show output without ANSI codes
    --help                              Show help banner of specified command

④このタイミングで「pub get」を実行してください

flutter_project_name % flutter pub get 

⑤iosフォルダに移動

flutter_project_name % cd ios 

⑥ iosフォルダ内で「pod install」

flutter_project_name/ios % pod install

以上でシュミレーターでビルドが通るはずです。僕は通りました。
お役に立てれば幸いです?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Expo SDK39をejectしてAsyncStorageの内容が消えた時の対象法

Expo sdk39のReact-native アプリをejectしたら、AsyncStorageの内容がクリアされる問題に遭遇しました。

原因

Expo下で参照されるAsyncStorageのデータ保存場所と、Eject後のAsyncStorageの保存場所が異なることから発生する問題のようです:frowning2:

解決方法 ※2021年3月22時点

今回は@react-native-community/async-storageを使ってやってます。
iexplorer等のツールを利用して保存元のファイルがどこにあるのか
確認して保存元のファイル名を変更すると問題なく引き継がれます。

例:expoでの保存先がRCTAsyncLocalStorageの場合

RNCAsyncStorage.m
static NSString *const RCTStorageDirectory = @"RCTAsyncLocalStorage_V1";  //保存先
static NSString *const RCTOldStorageDirectory = @"RNCAsyncLocalStorage_V1"; //保存元
RNCAsyncStorage.m
static NSString *const RCTStorageDirectory = @"RCTAsyncLocalStorage_V1";  //保存先
static NSString *const RCTOldStorageDirectory = @"RCTAsyncLocalStorage"; //保存元

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

UISceneDelegateをつかってUniversal Linkからの起動を制御する

概要

iOS13以降からUISceneDelegateが導入されたのでUniversal Linkからアプリが起動された挙動もUISceneDelegateのライフサイクルで制御します。
遷移したURLによってiOS側で制御を行いたいと思いますので、そちらを試した結果を記します。

実装

Universal Linkを利用するためのapple-app-site-associationの設置やAssociated Domainsの設定は完了しているものとします。
XCode11以降で作成されたプロジェクトにはSceneDelegate.swiftが含まれていてこちらにてライフサイクルの制御が管理されています。

Universal LinkなどをつかってSafariなどから遷移してきたときはscene(_:continue:)というDelegateメソッドで補足されます。
https://developer.apple.com/documentation/uikit/uiscenedelegate/3238056-scene

NSUserActivitywebpageURLというプロパティが存在するのでこちらでURLを取得しURLによって表示する画面などを決めて遷移できます。

以下はhogehogeというパスのURLでアプリに遷移した際にHogeHogeViewControllerをモーダル表示するときの実装です。

SceneDelegate.swift
    func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
        guard userActivity.activityType == NSUserActivityTypeBrowsingWeb else { return }
        guard let url = userActivity.webpageURL else { return }
        if url.scheme == "https" && url.host == "example.jp" && url.path == "hogehoge" {
            window?.rootViewController?.present(HogeHogeViewController(), animated: true, completion: nil)
        }
    }

問題

上記の実装でUniversal Linkから遷移を制御できるのですが、こちらはアプリがバックグラウンドで起動中しか保続できません。
新規にアプリが起動するときを制御するにはscene(_:willConnectTo:options:)にて同様の処理を用意する必要があります。

SceneDelegate.swift
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // URLが存在するものを補足
        guard let userActivity = connectionOptions.userActivities.first(where: { $0.webpageURL != nil }) else { return }

        guard userActivity.activityType == NSUserActivityTypeBrowsingWeb else { return }
        if url.scheme == "https" && url.host == "example.jp" && url.path == "hogehoge" {
            window?.rootViewController?.present(HogeHogeViewController(), animated: true, completion: nil)
        }
    }

こちらでアプリが起動していない場合でも画面の制御を行うことができるようになります。

あとがき

scene(_:continue:)だけだと未起動時の制御を補足できないですが、起動していないので実装時に見落としてしまいがちなのとデバッグがしにくく、ハマってしまうこともあるかとも思います。
こちらが役に立てば。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む