React Native チュートリアル – JavaScript で最初の iOS アプリを構築する (パート 1)
On 11月 24, 2021 by admin著者について
Nash Vail氏はユーザインターフェースを構築して設計することへの熱意を持つ人です。 彼は現在コンピュータサイエンスの学部生で、インターンシップの機会を積極的に探しています。 …More aboutNash↬
- 22 min read
- Mobile,JavaScript,Apps,iOS,React,Swift
- Saved for offline reading
- Share on Twitter.com
- Shared on Twitter.com
JavaScript でモバイル アプリケーションを構築するという考えは、新しいものではありません。 Ionic や PhoneGap のようなフレームワークがこの課題に取り組み、開発者やコミュニティのサポートを得て、ある程度成功したのを見てきました。 チュートリアルのパート 2 に進みます。
これらのフレームワークと、JavaScript でモバイル アプリを構築するという全体的なアイデアは、私には魅力的ではありませんでした。 Swift/Objective-CやJavaを学んで、本物のアプリを作ればいいじゃないか、といつも思っていました。 確かにかなりの量の学習が必要ですが、それこそが私たち開発者の仕事であり、得意とすべきことではないでしょうか? 新しい言語やフレームワークを素早く習得すること? では、何が言いたいのでしょうか?
Chalk + Chisel のこの記事、特に次の行を読むまで:
Fast-forward a couple of months, and I’m confident enough to say I might never write an iOS app in Objective-C or Swift again.
What’s? あなたは、まるで…真剣ですか?
SmashingMag でさらに読む:
- Why You Should Consider React Native For Your Mobile App
- Server-Side Rendering With React, Node And Express
- How To Scale React Applications
- Internationalizing React Apps
この大胆な主張を読んで、私も React Native を試しにやってみようかなと思ったのでした。 なぜでしょう? 私はすでに React を使用しており、それを気に入っていました。 React Native は React に非常によく似ているので(当たり前だ!)、すでに React の開発者であれば、すぐに馴染めるでしょう。 7732>
What We Will Be Building
App store で iPhone 用の完璧な壁紙アプリを見つけたことは一度もありません。 デスクトップでは、Unsplash が私のすべての壁紙のニーズを満たすワンストップショップです。 携帯電話では 設定 → 壁紙 🙁
) このチュートリアルでは、カウンターを構築してほとんど使用しない他のチュートリアルとは異なり、Unsplash からランダムに素晴らしい壁紙を取得し、美しい方法でそれらを表示し、カメラロールにお好みの壁紙を保存できるアプリを一緒に構築してみましょう。 信じてほしいのですが、私はこのアプリを最初に思っていた以上に使っているんです。 このチュートリアルが終わるまでに、React Nativeがあなたを感動させなかったとしても、あなたは本当にクールな壁紙アプリを手に入れることになるのです。
Before we start, here are some things you should be familiar with:
- JavaScript
- Some ES2015 features, namely Classes, Arrow Functions, Destructuring and Template Strings
- Mac OS X Terminal
- CSS (yup!).)
- React (オプション)
もう1つ。 タイトルに明記されているように、このチュートリアルでは、iOSアプリを作ります。 そのため、React Native を使用する場合でも、Mac を使用する必要があります。 React Nativeでは、AndroidアプリはWindowsやLinuxで間違いなく作れますが、iOSのアプリは作れません。 したがって、ここから先、このチュートリアルでは、Mac OS X を実行していることを前提としています。
Takeaways
このチュートリアルが終わるころには、自分のアプリをすぐに書き始められるほど React Native に精通していることでしょう。 Xcode でのプロジェクトのセットアップ、サード パーティ製モジュールとコンポーネントのインストール、ライブラリのリンク、フレックスボックスによるスタイル設定、カスタム ジェスチャー リスナーの作成、およびその他多くのことについて説明します。 React は、多くの可能性を秘めた新しいホットな JS ライブラリであり、近い将来どこにも行くことはないと思います。
このチュートリアルは、便宜上 2 部に分かれています。 各パートには5つのセクションがあります。 各セクションでは、アプリの完成に一歩近づくための目標を達成します。 そうすることで、流れを中断することなく、私が紹介しようとしているコンセプト全体を知ることができます。
参考までに、今回作成するアプリの最終的なコードは、この GitHub リポで見つけることができます。
Set Up A Blank React Native Project
Xcode 7.0 以上がインストールされていることを確認します。これは App Store から無料でダウンロードできます。 しかし、そうでない場合は、先に進んで Node もインストールしてください。 もう1つ必要な重要なツールはnpmです。 Nodeにはnpmがインストールされています。ただし、npmは割と頻繁にアップデートされるので、アップデートする必要があります。
必要なものはこれだけです。 さて、ターミナルから npm install -g react-native-cli
を実行します。 これにより、React Native がシステム上にグローバルにインストールされます。
すべてが新しく感じられる場合、またはインストール プロセス全体に少し迷いがある場合、公式の Getting Start ガイドがいつでもあなたを助けてくれます。 そこで、ターミナルから react-native init SplashWalls
.
を実行すると、必要なすべてのモジュールが取得されてインストールされ、SplashWalls という新しいフォルダーが作成されます。
React Native についての素晴らしいことの 1 つは、Android と iOS アプリケーションを両方書いて、大部分の JavaScript コードがそれらの間で共有できることです。 新しく作成されたフォルダーの中には、index.android.js と index.ios.js という 2 つの .js ファイルがあり、その名前は一目瞭然です。 iOS アプリを作成する場合は index.ios.js で作業し、Android アプリの場合は index.android.js で作業し、両方のプラットフォームで作業します。
今回は iOS アプリを作成するので、このチュートリアルのために、また状況をきれいに保つために index.android.js と android フォルダーを完全に削除します。
次に、ios フォルダーに移動して SplashWalls.xcodeproj を起動します。
上の画像で “No matching provisioning profiles found” という警告に注目します。 これを修正しましょう。
まず、Bundle Identifier フィールドのテキストを何かカスタムなものに変更します。 入力するものはすべて、組織のドメイン名を逆にしてさらに識別子を接尾させる逆 DNS 規則に従っていることを確認する必要があります。 この規約は、デバイス上やApp Store上であなたのアプリケーションを他のものと区別するのに役立ちます。 私は com.nashvail.me.tutorial.SplashWalls を使用します。もし何か作ることができないようでしたら、私の名前の代わりにあなたの名前を代入してください。
次に、チームのドロップダウンから名前を選択します。
App を縦表示のみにして、ステータス バーも非表示にしてみます。 下のようなターミナルウィンドウが表示されます。 最初の変換に少し時間がかかります。
完了したら、シミュレーターで次のような出力が表示されるはずです:
Fetching Wallpaper Data From The API
このセクションでは Unsplash.it API に壁紙データを要求する呼び出しを行います。 しかし、すべての興味深い作業を開始する前に、行うべきいくつかの設定があります。
Switching To ES2015 Class Syntax
index.ios.js ファイルを開くと、いくつかの初期コードがすでに存在していることに気づくでしょう。 これは、シミュレーターでの出力を担うコードです (前の画像)。
index.ios.js 内で、var SplashWalls = React.createClass({ … })
というコードの行に注目してください。 これを修正することにします。 このチュートリアルでは、ES2015 の class
構文を使用します。
私たち開発者は好奇心が強いものです。 なぜ? なぜ class
構文に切り替えたのか?
それはすべて、個人の好みによるものです。 私は以前、オブジェクト指向言語で広範囲にプログラムを作成したことがありますが、class
は私にとってより身近なものに感じられました。 さらに、class
を使用すると、各メソッド宣言の後にカンマを追加する必要がないため、コードを少しすっきりさせることができます。
反面、class
を選択すると、自動バインディングやisMounted
メソッドへのアクセスなどの機能は得られませんが、これは全く悪いことではなく、これらを使用しないことで途方にくれることはあまりないでしょう。 私のアドバイスは、class
を使用することです。 新機能ですし、遅かれ早かれES2015を使うことになるでしょうから。 このチュートリアルに従うなら、class
を使用する必要があります。
必要な変更を行ったら、コードのブロックは次のようになります。
class SplashWalls extends Component{ render() { return ( . <View style={styles.container}> <Text style={styles.welcome}> Welcome to React Native! </Text> <Text style={styles.instructions}> To get started, edit index.ios.js </Text> <Text style={styles.instructions}> Press Cmd+R to reload,{'\n'} Cmd+D or shake for dev menu </Text> .</View> ); }};
React の初心者にとって、return
パレンの中のコードは少し奇妙に見えるかもしれませんが、ロケット科学ではなく、JSX という古き良き XML ライクの構文だけなのです。 詳細はこちらをご覧ください。
class
以前の実装と比較すると、var
構文がなくなっています。 また、render: function(){…
もrender(){…
だけになりました。
しかし、あなたが拡張しているComponent
は何でしょうか? という疑問は当然でしょう。 今Xcodeでプロジェクトを実行すると、Component
は定義されていないというエラーが表示されます。 ここでできることは2つあります。Component
をReact.Component
に置き換えるか、ファイルの先頭にあるブロック(下図)の中に新しい行を追加します。
このコードとそれ以降のコード例では、新しく追加した行を//
で囲み、ここに示されているコードとあなたが書いたコードを簡単に比較できるようにしました。 ただ、サンプルからコードをコピーする場合は、実際のコードと一緒に//
をコピーしてしまわないように注意してください。 JSX は /***/
コメントをサポートしていないので、これらを JSX コードに含めるとアプリがクラッシュしてしまいます。
var { AppRegistry, StyleSheet, Tex .t, View, /***/ Component /***/} = React;
上記のコードのブロックが行うことは、キーストロークをいくつか節約することだけです。 たとえば、これらの行を先頭に含めなかった場合、毎回 AppRegistry
ではなく React.AppRegistry
と記述する必要があります。 かなりクールだ。 そうでしょう? OK, not so much.
Xcode に戻り、プロジェクトをもう一度実行して、プロセスで何も壊していないことを確認します。
すべて良好ですか? 素晴らしい!
SplashWalls
クラスの内部で、私たちが最初に行う必要があるのは、コンストラクタを追加することです。 コンストラクタの内部では、状態変数を初期化します。 この時点で必要な状態変数は、API から取得したすべての JSON データを格納する予定の配列 wallsJSON
と、ブール変数である isLoading
の 2 つだけで、これは true または false のいずれかの値を保持することを意味します。
SplashWalls
クラスの内部に、以下に示すように constructor
を追加します。
class SplashWalls extends Component{/***/ constructor(props) { super(props); this.state = { wallsJSON: , isLoading: true }; }/***/...}
次に、fetchWallsJSON メソッドを定義します。 コンストラクタの閉じ中括弧の下に数行残し、次のコード行を追加します。
fetchWallsJSON() { console.log('Wallpapers will be fetched');}
コンポーネントが正常にマウントされると、この関数が起動するようにしたいです。 componentDidMount
メソッドを追加します。
componentDidMount
はライフサイクル メソッドで、最初のレンダリングが発生した直後に起動されます。
React コンポーネントのすべてのライフサイクル メソッドについて説明されています。 新しい class
構文を使用しているため、getInitialState
メソッドを省略できることだけは覚えておいてください。 これは、constructor
.
.
の this.state
変数宣言で代用されます。クラス内のメソッドをきれいに整理するのは良いアイデアです。 私は、すべてのカスタム メソッドをライフサイクル メソッドから分離しておくのが好きです。
componentDidMount
:
componentDidMount() { this.fetchWallsJSON();}
fetchWallsJSON
メソッドの中でコンソールにメッセージを記録していることに注目してください – しかし、コンソールはどこにあるのでしょうか。
Simulator ウィンドウが選択されていることを確認し、Cmd + Control + Z を押して、ポップアップするメニューから、Debug in Chrome を選択します。 これで新しいタブが開きます。 同じタブで、Dev Tools (Option + Cmd + J)に移動します。 コンソールに「壁紙が取得されます」というメッセージが表示されます。
とりあえずデバッガを開いたままにしておいてください。 新しいタブで unsplash.it/list にアクセスします。 ビューポート全体が JSON 配列で満たされているのがわかるはずです。 配列の各要素は、1つの壁紙のデータを保持するJavaScriptオブジェクトです。
fetchWallsJSON
がコンソールにメッセージをログ出力する以上のことを行うようにします。
fetchWallsJSON() { /***/ var url = 'http://unsplash.it/list'; fetch(url) .then( response => response.json() ) .then( jsonData => { console.log(jsonData); }) .catch( error => console.log('Fetch error ' + error) ); /***/ }
シミュレータを更新 (Cmd + R) するか、Cmd + Ctrl + Z を押してライブ リロードを有効にして、Enable live reload を選択すると、よりよいでしょう。 ライブ リロードを有効にすると、コードを変更するたびにシミュレータをリフレッシュする必要がなくなります。 IDE で保存するだけで、シミュレータは自動的にリフレッシュされます。 XcodeやAndroid Studioでアプリを開発したことがある人なら、変更を加えるたびに実行ボタンを押してアプリを再コンパイルする必要がないため、この機能が特に素晴らしいと感じるでしょう。
更新時に、数秒待つと、コンソールに次の出力が表示されます。
よろしい、これで API から壁紙の JSON データをフェッチできるようになりました。 お気づきのように、データがコンソールにログ記録されるまでに少し遅延があります。 これは、バックグラウンドでデータがサーバーからダウンロードされるためで、時間がかかります。
これは、ローディング画面を追加するのに最適なタイミングのように見えます。
Adding A Loading Screen
このセクションの終わりまでに、JSON データがダウンロードされている間にロード画面を表示させます。
最初に、SplashWall
クラスのrender
メソッド内からすべてを取り除き、次のコードのラインを追加します:
render() { var {isLoading} = this.state; if(isLoading) return this.renderLoadingMessage(); else return this.renderResults(); }
私たちは2つの新しいメソッドを持っています。 7732>
renderLoadingMessage() { return ( . <View style={styles.loadingContainer}> <ActivityIndicatorIOS animating={true} color={'#fff'} size={'small'} style={{margin: 15}} /> <Text style={{color: '#fff'}}>Contacting Unsplash</Text> .</View> ); } renderResults() { return ( . <View> <Text> Data loaded </Text> .</View> ); }
状態変数 isLoading
が保持する値に応じて、2 つの異なる View
コンポーネントがレンダリングされます。 isLoading
が true の場合は、ローディング スピナーに続いて「Unsplash に連絡」というテキストを表示し、isLoading
が false の場合は(データがロードされたことを示す)結果を表示し、現時点では「Data loaded」と表示された Text
コンポーネントが表示されているだけです。 では、そうしてみましょう。 fetchWallsJSON
メソッドに向かい、jsonData
をコンソールにログ出力する行の下に、isLoading
を更新する行を追加します。
fetchWallsJSON() { var url = 'http://unsplash.it/list'; fetch(url) .then( response => response.json() ) .then( jsonData => { console.log(jsonData); /***/ this.setState({isLoading: false}); //update isLoading /***/ }) .catch( error => console.log('Fetch error ' + error) ); }
setState は React の Component API メソッドの 1 つです。 これは、UI の更新をトリガーするために使用される主要なメソッドです。
Notice, in renderLoadingMessage
we have a new component: ActivityIndicatorIOS
(簡単に言うと、スピナー) です。 このコンポーネントを使用する前に、インポートする必要があります。 Component
をインポートしたときに、キーストロークをいくつか節約したのを覚えていますか?
var { AppRegistry, StyleSheet, Tex .t, View, Component,/***/ ActivityIndicatorIOS // Add new component/***/} = React;
結果を確認する前に、もう 1 つ必要なことがあります。 ActivityIndicatorIOS
を含む View
のスタイルが styles.loadingContainer
に設定されていることに注目してください。 これを定義する必要があります。 var styles = StyleSheet.create({…
と書いてある行を探します。 ここで、いくつかのスタイルがすでに定義されていることがわかります。 これらのスタイルは、シミュレータの最初の「React Native へようこそ」メッセージのスタイルを決める役割を担っています。 定義済みのスタイルをすべて取り除き、図のように loadingContainer
に 1 つだけ追加します。
var styles = StyleSheet.create({/***/ loadingContainer: { flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', backgroundColor: '#000' }/***/});
React Native でコンポーネントに適用するスタイルは、すべて上記のように宣言されています。 StyleSheet.create
はスタイルを含む JavaScript オブジェクトを引数として取り込み、dot
演算子を使ってスタイルにアクセスできるようになります。
<View style={styles.loadingContainer}/>
また、スタイルをインラインで宣言することもできます:
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', backgroundColor: '#000' }} />
ただし、これによってコードは少し雑然とします。 コンポーネントに適用される多数のスタイルがある場合、それらを変数に格納するのは常に良い考えです。
スタイルは CSS によく似ていますね。 なぜかわかりますか? そうなっているからです。何の違いもありません。 このため、React Native は Web 開発者にとってさらに手に取りやすくなっています。 専用のIDE(Xcodeなど)でアプリを構築する場合、ボタンやラベルなどのUI要素を画面上に直接ドラッグして配置するためのStoryBoardが提供されます。 React Native ではそれができません。
React Native では、画面上の要素を配置するためにフレックスボックスを多用しています。 フレックスボックスを使いこなすと、要素の配置が簡単になります。 私はどんなときでも、StoryBoard よりもフレックスボックス レイアウトを優先します。
変更を保存し、シミュレーターに移動して Cmd + R を押します。
数秒後に “Data loaded” というスクリーンが表示されます。
Filtering and Picking Random Wallpapers
このセクションでは、壁紙データにフィルターをかけ、指定数の壁紙をランダムに選びます。
このセクションでは、React NativeよりもJavaScriptに焦点を当てて説明します。 乱数生成を処理する新しいモジュール(ファイル)の作成を通して説明します。 JavaScript のモジュールは初めてという方は、Node.js modules docs を参照してください。
class
宣言の上の行に行き、選ぶべきランダムな壁紙の数をアプリに伝える新しい定数を宣言します(ここでは 5 とします)。 このモジュールは2つの関数をエクスポートします。 それぞれについて見てみましょう。
-
uniqueRandomNumbers
:この関数は3つの引数を取ります。 1つ目は返すべき乱数の数です。 次の2つの引数は乱数が返される範囲、すなわちlowerLimit
とupperLimit
を定義します。 -
randomNumberInRange
: この関数は二つの引数を取り、それぞれ一つの乱数が返される下限と上限の値を定義します。 例えば、randomNumberInRange(2, 10)
を呼び出すと、2から10の間の一意の乱数が返されます。
これらの関数を1つに統合することもできましたが、私は良質なコードの伝道者として、単一責任の原則に従います。 SRPは、多かれ少なかれ、各関数は1つのことをうまく行い、他のことは行わないべきだというものです。 優れたプログラミングの原則に従うことで、将来の頭痛の種からあなたを救います。
index.ios.js と同じディレクトリに新しいファイルを作成します。 しかし、この新しいファイルが提供する種類の目的のために、このファイルをコピーして、乱数の生成を必要とする新しいプロジェクトに貼り付けて、そこから使用することができることを考えてみてください。
このファイルを RandManager.js と呼ぶことにします。
module.exports = { uniqueRandomNumbers(numRandomNumbers, lowerLimit, upperLimit) { var uniqueNumbers = ; while( uniqueNumbers.length != numRandomNumbers ) { var currentRandomNumber = this.randomNumberInRange(lowerLimit, upperLimit); if( uniqueNumbers.indexOf(currentRandomNumber) === -1 ) uniqueNumbers.push(currentRandomNumber); } return uniqueNumbers; }, randomNumberInRange(lowerLimit, upperLimit) { return Math.floor( Math.random() * (1 + upperLimit - lowerLimit) ) + lowerLimit; }};
index.ios.js で RandManager
モジュールを要求することを忘れないでください。 追加するだけです。 use strict;
の下にvar RandManager = require('./RandManager.js');
を追加します。 RandManager
の準備ができたら、fetchWallsJSON
関数に次の変更を加えます。
fetchWallsJSON() { var url = 'http://unsplash.it/list'; fetch(url) .then( response => response.json() ) .then( jsonData => { /***/ var randomIds = RandManager.uniqueRandomNumbers(NUM_WALLPAPERS, 0, jsonData.length); var walls = ; randomIds.forEach(randomId => { walls.push(jsonData); }); this.setState({ isLoading: false, wallsJSON: .concat(walls) }); /***/ }) .catch( error => console.log('JSON Fetch error : ' + error) );}
jsonData
ができたら、RandManager
から固有の乱数を取得し、randomIds
配列に保存します。 次に、この配列をループして、特定のrandomId
地点に存在する壁紙データオブジェクトをピックアップし、walls
配列に格納します。
そして、状態変数を更新します。 isLoading
はデータがダウンロードされたので false に、wallsJSON
は walls
に更新します。
結果を見るには、renderResults
関数を次のように変更します。
renderResults() {/***/ var {wallsJSON, isLoading} = this.state; if( !isLoading ) { return ( . <View> {wallsJSON.map((wallpaper, index) => { return( <Text key={index}> {wallpaper.id} </Text> ); })} .</View> ); }/***/}
renderResults
内の最初の行では、構造化解除という ES2015 新機能を使用しています。
var wallsJSON = this.state.wallsJSON, isLoading = this.state.isLoading;
を
var {wallsJSON, isLoading} = this.state;
ES2015 はとてもクールです。
そして View
内では、取得した wallsJSON
データを map を使ってループさせています。
また、配列やコレクションをループしてコンポーネントをレンダリングする場合、React Native ではレンダリングする子コンポーネントにそれぞれ key
という一意の ID を与える必要があります。 そのため、
<Text key={index}>
Once the simulator refreshes…
The five different random wallpaper IDs are displayed.
<Text key={index}>
React Nativeのキープロパティを見ることができるのは、このためです。 renderResults
の {wallpaper.id}
を {wallpaper.author}
に変更すると、次のようになります。
すごい! 今、私たちは話しています。 これで、指定した数(この場合は5枚)のランダムな壁紙をAPIから取得し、フィルタリングできるようになりました。 このセクションは終了したようです。 High five!
Adding The Swiper Component
このセクションでは、アプリに Swiper コンポーネントを組み込みます。 このコンポーネントを使用すると、スワイプ可能なコンテナに壁紙を表示できます。
サードパーティの React Native コンポーネントをアプリに含める方法について説明します。 React Native には素晴らしいコミュニティ サポートがあり、GitHub にはあらゆる種類のさまざまなサードパーティ コンポーネントが豊富に集められています。
ターミナルでプロジェクト ディレクトリに移動し、次のコマンドを実行します。
npm install react-native-swiper --save
Now require the Swiper
component: add var Swiper = require('react-native-swiper');
below use strict
.
Let’s try out our newly included Swiper
component.
renderResults
methodに移動して、View
をSwiper
と置換します。
renderResults() { var {wallsJSON, isLoading} = this.state; if( !isLoading ) { return ( /***/ <Swiper> /***/ {wallsJSON.map((wallpaper, index) => { return( <Text key={index}> {wallpaper.author} </Text> ); })} /***/ </Swiper> /***/ ); }}
これを実行すると、次のようになります。
Swiper
コンポーネントに次の属性を追加します。
<Swiper/***/dot.{<View style={{backgroundColor:'rgba(255,255,255,.4)', width: 8, height: 8,borderRadius: 10, marginLeft: 3, marginRight: 3, marginTop: 3, marginBottom: 3,}} />}activeDot.{<View style={{backgroundColor: '#fff', width: 13, height: 13, borderRadius: 7, marginLeft: 7, marginRight: 7}} />}loop={false} {wallsJSON.map((wallpaper, index) => { return( <Text key={index}> {wallpaper.author} </Text> ); })} </Swiper>
これを行うことで、
- Styles the pagination dots (前の画像で下部に見える青い点を白く大きくする)
- Disables continuous swiping (
loop={false}
). つまり、最終ページに到達してさらにスワイプすると、最初の壁紙に戻されません。 - スワイプが終わるたびに
onMomentumScrollEnd
(チュートリアルの次のパートでさらに掘り下げます)を発射します。
これで、最初のパートが終了しました。 7732>
React Native チュートリアルをまとめると
- 最初のセクションでは、Xcode で空の React Native プロジェクトをセットアップする方法を学びました。
- 次のセクションでは ES2015 クラスと、状態変数の作成と API からの生のデータの取得とともに新しい構文を選択する理由について話しました。
- 第 4 章では、乱数生成を処理するまったく新しいモジュールを作成し、それをメイン ファイルに含めます。
- 最後のセクションでは、アプリに最初のサードパーティ製コンポーネントを追加しました。 そうですね。 次のパートでは、著者名だけでなく、実際の画像を追加する予定です。 それだけでなく、
PanHandler
API を使用してカスタム ダブルタップ検出器を作成するなど、高度なことも行う予定です。 Xcode でライブラリをリンクし、アプリにカメラロールへのアクセス権を付与する方法を学びます。 さらに、独自のコンポーネントを作成するなど、盛りだくさんの内容です。 面白そうですか?(da, ml, og, il)では、次のパートでお会いしましょう。
コメントを残す