デバイスのディスプレイの大きさによってポイント数、画像サイズ、スケールなどが異なる
MakeAppIconで1枚の画像からアイコンを自動生成してくる
MyJanken/Assets.xcassets/AppIcon.appiconset にコピー&ペーストする
アイコンが追加されている
なんかiPhoneに派生して凄いことになってるな
ソフトウェアエンジニアの技術ブログ:Software engineer tech blog
随机应变 ABCD: Always Be Coding and … : хороший
デバイスのディスプレイの大きさによってポイント数、画像サイズ、スケールなどが異なる
MakeAppIconで1枚の画像からアイコンを自動生成してくる
MyJanken/Assets.xcassets/AppIcon.appiconset にコピー&ペーストする
アイコンが追加されている
なんかiPhoneに派生して凄いことになってるな
変数では通常値を変更できないが、@Stateで値を更新できるようになる
swiftは型推論を実装している
swift基本型: int, Uint(符号なし), Float, Double, String, Bool
初期値をnullとして、タップされたらグーに変わる
VStack { if answerNumber == 0 { Text("これからじゃんけんをします") } else if answerNumber == 1 { Image("gu") .resizable() .aspectRatio(contentMode: .fit) Text("グー") } else if answerNumber == 2 { } else { } Button(action: { print("タップされたよ!") answerNumber = Int.random(in: 1...3) }) { Text("じゃんけんする!") } }
数値をランダムに算出するものを関数(function)と呼ぶ
同じジャンケンが続かないようにする
repeat {} while で繰り返し処理する
Button(action: { answerNumber = Int.random(in: 1...3) var newAnswerNumber = 0 repeat { newAnswerNumber = Int.random(in: 1...3) } while answerNumber == newAnswerNumber answerNumber = newAnswerNumber }) { Text("じゃんけんする!") }
スタイリング
Text("じゃんけんする!") .frame(maxWidth: .infinity) .frame(height: 100) .font(.title) .background(Color.pink) .foregroundColor(Color.white)
こちらで完成
var body: some View { VStack { if answerNumber == 0 { Spacer() Text("これからじゃんけんをします") .padding(.bottom) } else if answerNumber == 1 { Image("gu") .resizable() .aspectRatio(contentMode: .fit) Text("グー") Spacer() } else if answerNumber == 2 { Image("choki") .resizable() .aspectRatio(contentMode: .fit) Text("チョキ") .padding(.bottom) Spacer() } else { Image("pa") .resizable() .aspectRatio(contentMode: .fit) Text("パー") .padding(.bottom) Spacer() } Button(action: { answerNumber = Int.random(in: 1...3) var newAnswerNumber = 0 repeat { newAnswerNumber = Int.random(in: 1...3) } while answerNumber == newAnswerNumber answerNumber = newAnswerNumber }) { Text("じゃんけんする!") .frame(maxWidth: .infinity) .frame(height: 100) .font(.title) .background(Color.pink) .foregroundColor(Color.white) } } }
なるほど、感どころはわかったような気がする
swift独特の書き方は覚えないといかんね。
Image, Text, Buttonを配置する
TextとButtonに背景、文字色、文字サイズを設定
Imageにじゃんけん画像を切り替える
ファイルの役割
– MyJankenApp.swift: アプリケーションのエントリーポイント
– ContentView.swift: アプリの基本的な画面
– Assets.xcassets: 画像、音楽ファイル、アイコン、色などのリソース
– Preview Asset: Preview用のアセットカタログ
### 画像ファイルの取り込み
Assets.xcassetsに画像をドラッグする
### レイアウト構成
VStack(垂直)、HStack(水平)、ZStack(奥行き)があり、組み合わせで親ビュー、子ビューにもなる
レイアウト: ContentView – VStack – Image, Text, Button – Text
### UIパーツの配置
struct ContentView: View { var body: some View { Image("gu") } }
Image(“gu”).resizable()でサイズを自動調整
struct ContentView: View { var body: some View { Image("gu") .resizable() .aspectRatio(contentMode: .fit) } }
struct: 構造体、 swiftは構造体推奨
ContentView: 構造体名、 swiftはViewプロトコルに準拠
View: プロトコル、 resizableやaspectRatioを利用できる
var: 変数、 後から値の変更が可能。定数は不可
body: 変数名
some: 型 具体的な戻り値を隠すことができる
{}: クロージャー
swiftでは、名前付き型(プロトコル型、クラス型、構造体型、数字文字文字列などのデータ型)と複合型(名前のない型で関数型とタプル型)の2種類がある
returnは省略される
「shift」 + 「command」 + 「L」でLibraryを表示し、VStackを表示
縦のカーソルを確認する
struct ContentView: View { var body: some View { VStack { Image("gu") .resizable() .aspectRatio(contentMode: .fit) Text("グー") Button(action: { print("タップされたよ!") }) { Text("じゃんけんする!") } } } }
ボタンをクリックするとテキストが表示される
ここからif文などを使っていくのね
xcodeは大分使い易くなった^^
「shift」 + 「command」 + 「L」でLibraryを表示
VStackでまとめる
VStack { Text("Hello, world!") .font(.largeTitle) .padding() Button(/*@START_MENU_TOKEN@*/"Button"/*@END_MENU_TOKEN@*/) { /*@START_MENU_TOKEN@*//*@PLACEHOLDER=Action@*/ /*@END_MENU_TOKEN@*/ } }
VStackの他にHStackやZStackもある
Add Modifierでbackgroundを追加する
– textをwhiteにしてpaddingを追加する
– @State var outputText = “Hello, World!” で変数を宣言する
– outputText = “Hi, Swift!” を定義
struct ContentView: View { @State var outputText = "Hello, World!" var body: some View { VStack { Text(outputText) .font(.largeTitle) .padding() Button(action: { outputText = "Hi, Swift!" }) { Text("切り替えボタン") .foregroundColor(Color.white) .padding(.all) .background(Color.blue) } } } }
Canvas: Static Mode, Live Preview
シミュレータ: Xodeツールの一部としてインストールされている
実機: 全ての機能を確認
Canvasのライブプレビューでテストできるので、シミュレータを起動しなくても確認できる
iPhone12以外でもiPadなど様々なデバイスで確認できる
コードでcanvasのpreviewを変更
struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() .previewDevice("iPhone 8") } }
複数デバイスのプレビュー
struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() .previewDevice("iPhone 8") ContentView() .previewDevice("iPad Pro (9.7-inch)") } }
PinPreviewで表示を固定
### シミュレータの起動
Runを押す
シミュレータは時間がかかる、カメラは閲覧できない
シミュレータは停止してから画面を閉じる
なるほど、前のストーリーボードから大分仕様が変わったなwww
Webviewとは?
-> HTMLコンテンツをアプリ内で見れるようにすること
-> SafariやChromeで見られる枠組みをアプリ内に作ることができる
-> HTMLの更新をすれば良いので、アプリストアへの申請や審査、アップデートは必要ない
-> iOS, AndroidともにWebviewに対応している
-> ユーザ体験、操作性はネイティブアプリの方が優れている
-> 全てをWebviewにするのではなく、ヘッダ、フッタの調整などを行うことが多い
-> Webブラウザのレンダリングエンジンを呼び出しているが、ブラウザ自体を起動している訳ではない。そのため、設定やCookieなどは別で管理される
アプリ(Webview)のメリット・デメリット
– push通知を送信できる
– ネイティブを開発するよりも開発・運用コストを抑制できる
– Webとの違いを出しずらい
### Android
– Android System Webview
1.GUIコンポーネントのWebviewを使用する
<WebView android:id=”@+id/webView″ android:layout_width=”match_parent” android:layout_height=”match_parent” android:layout_alignParentLeft=”true” />
2. マニュフェストにインターネットアクセスを許可するパーミッション追加
3. インクをクリックしたときに標準ブラウザを起動しないようにする
WebView myWebView = (WebView) findViewById(R.id.webView); myWebView.setWebViewClient(new WebViewClient()); myWebView.loadUrl(“https://www.google.com/”);
### iOS
– SFSafariView、WKWebView、(UIWebView(非推奨))などを使う
UIApplication classを使う
import UIKit class ViewController: UIViewController , UIWebViewDelegate { override func viewDidLoad() { super.viewDidLoad() let url = URL(string: "https://hoge.com/")! if #available(iOS 10.0, *) { UIApplication.shared.open(url, options: [:], completionHandler: nil) } else { UIApplication.shared.openURL(url) } } }
SFSafariViewController
import UIKit import SafariServices class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() } override func viewDidAppear(_ animated: Bool) { let webPage = "https://hoge.com/" let safariVC = SFSafariViewController(url: NSURL(string: webPage)! as URL) present(safariVC, animated: true, completion: nil) } }
What is a crash report?
When an error occurs in the application, it may be terminated, but the terminal stores the information inside the terminated application at that time.
The screen will be displayed at the end, but if you tap the report, the development team can use the information for defect correction.
The crash report contains the following information, but does not contain personally identifying information.
– App version
– Android version
– Device type
– Error occurrence time
– Error occurrence point
– Number of occurrences
– Message you entered
ドコモの「アプリクラッシュポート」についてを見てみましょう
アプリクラッシュレポート
作ってもらった。
alamofirをimportしている。
import UIKit import Alamofire class ViewController: UIViewController { @IBOutlet weak var categoryLbl: UILabel! @IBOutlet weak var brandLbl: UILabel! @IBOutlet weak var nameLbl: UILabel! @IBOutlet weak var priceLbl: UILabel! @IBOutlet weak var conditionLbl: UILabel! @IBOutlet weak var timeleftLbl: UILabel! @IBOutlet weak var bitLbl: UILabel! @IBOutlet weak var topImg: UIImageView! @IBOutlet weak var tittleLbl: UILabel! let URL = "http://hpscript.com/xcode/" override func viewDidLoad() { super.viewDidLoad() //making a post request Alamofire.request(URL, method: .get, parameters: nil).responseJSON { response in //printing response //getting the json value from the server if let result = response.result.value { let jsonData = result as! NSDictionary print(jsonData) self.tittleLbl.text = jsonData.value(forKey: "name") as? String self.bitLbl.text = jsonData.value(forKey: "bit") as? String self.brandLbl.text = jsonData.value(forKey: "brand") as? String self.categoryLbl.text = jsonData.value(forKey: "category") as? String self.conditionLbl.text = jsonData.value(forKey: "condition") as? String self.nameLbl.text = jsonData.value(forKey: "name") as? String self.priceLbl.text = jsonData.value(forKey: "price") as? String self.timeleftLbl.text = jsonData.value(forKey: "timeleft") as? String //if there is no error } } // Do any additional setup after loading the view, typically from a nib. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
Alamofire.request(URL, method: .get, parameters: nil).responseJSON か。
alamofireのframe workを入れるところと、getだから、postの場合どうするかだね。
sudo rm -rf ~/Library/Developer/Xcode/iOS\ DeviceSupport/*
DispatchQueue.main.asyncでjsonを参照する。
override func viewDidLoad() { super.viewDidLoad() let stringUrl = "http://hpscript.com/swift/index.php" do { guard let url = URL(string: stringUrl) else { return } URLSession.shared.dataTask(with: url){(data, response, error) in if error != nil { print(error!.localizedDescription) } guard let data = data else { return } let json = try! JSONDecoder().decode([JsonSample].self, from: data) DispatchQueue.main.async { self.label.text = json[0].name //←ここでjsonを参照する } }.resume() } catch{ } }
jsonはcodableを使う。
なるほど!行けるか???行ければandroidへ直ぐにGo
どうしてもやりたい
表示したいこと
Category: Audio Player
Brand: AKG
Name:AKG K77 PERCEPT
Price: 40
condition: 30
Left: 300
Bit : 1
まず、mysqlのテーブルを作っていく
create table product( category varchar(255), brand varchar(255), name varchar(255), price int, condition varchar(255), timeleft int, bit int, );
データを入れる。
INSERT INTO `product` (`category`, `brand`, `name`, `price`, `con`, `tleft`, `bit`) VALUES ('Audio Player', 'AKG', 'AKG K77 PERCEPT', '40', 'new', '300', '1');