20190512のSwiftに関する記事は15件です。

iterator pattern

iterator pattern

ケース

集約オブジェクトの内部構造を知ることなくアクセスできるようにしたいとき

結果

pro

アクセス方法を局所化できる
複数のアクセス方法を容易に提供できる
同時に複数からアクセスできうる

con

ない

実装対象

集約インターフェイス
集約クラス
Iteratorインターフェイス
Iterator class

種類

内部イテレーターと外部イテレーターがある。

クライアントがイテレーションを制御する -> 外部イテレーター

while let element = iterator.next {
    // do something
}

Iteratorがイテレーションを制御する -> 内部イテレーター

iterator.traverse()

example

protocol AggregateProtocol {
    associatedtype Item
    func createIterator() -> IteratorProtocol
    func get(for index: Int) -> Item
    func count() -> Int
}

protocol IteratorProtocol {
    associatedtype Item
    var next: Item? { get }
}

class Apartment: AggregateProtocol {
    typealias Item = Room
    private let rooms: [Room]

    func createIterator() -> IteratorProtocol {
        return RoomIterator()
    }

    func get(for index: Int) {
        return rooms[index] // TODO: care out of range
    }

    func count() -> Int { return rooms.count }
}

class RoomIterator: IteratorProtocol {
    typealias Item = Room
    private let index: Int = 0
    private let apartment: Apartment

    var next: Room? {
        let room = apartment.get(for: index)
        index += 1
        return room
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【iOS】画面遷移方法まとめ

画面遷移の方法についてまとめます。

プッシュ遷移とモーダル遷移

まずiOSアプリには、2種類の画面遷移方法があります。

  • プッシュ遷移
  • モーダル遷移

実装方法は後に書きますが、まずは両者の使い分けについて整理します。

プッシュ遷移

雑に説明すると、普通の画面遷移のことです。
プッシュと呼ばれているのは、NavigationContollerが画面のスタックを持っていて、
そのスタックにpushしながら遷移するからだと思われます。
具体的なユースケースとしては、モーダル遷移にすべきじゃないとき全部という感じですが、挙げるとすれば下記でしょうか。

  • NavigationBarの戻る・進むボタンで移動することが想定される画面

モーダル遷移

「モーダル」(modal)という言葉をどう訳せばいいのか、色々調べてもわからなかったのです。
よく下からニュッと出てくる画面、とか説明されます。
単に、下から次の画面を出すのが目的ではありません。

Modalityという単語の意味は、いくつか意味があるのですが、

2.(生理学)視覚、聴覚、触覚などの五感や感覚。また、それらを用いて外界を知覚する手段のこと。また、それらの感覚に働きかける人工的な情報伝達手段。
モダリティ - ウィクショナリー日本語版

多分ここでは「五感に訴えかける人工的な情報伝達手段」の意味なのだと思われます。
なんかいくつか検索して出てきた日本語記事見ましたが、上手い訳語をあててる例があまりないですね。。。
意味を考えると、この場では「応答待ち」とかがいいんだと思います。

Human Interface Guidelinesから該当箇所を丸々引用すると、

(拙訳)
Modality(応答待ち)は、ユーザーがタスクを完了させるか、メッセージorビューを却下するまで、他の動作をさせないためのものです。アクションシート(?)、アラート、アクションビュー(?)で応答待ち処理を実装できます。応答待ちのビューが画面に表示されたら、ユーザーはボタンをタップするか、応答待ち処理から抜けるかを選ばなければいけません。
Modality creates focus by preventing people from doing other things until they complete a task or dismiss a message or view. Action sheets, alerts, and activity views provide modal experiences. When a modal view appears onscreen, the user must make a choice by tapping a button or otherwise exiting the modal experience.
Human Interface Guidelines

つまりユーザーに絶対に入力させたい情報がある場合に、一時的に画面遷移を発生させる処理がモーダル遷移です。
Human Interface Guidelinesでも書かれていますが、多用すべき方法ではありません。
基本的に何かメインの処理をしたいユーザーを、別の操作をさせて妨害することになるので、多用するとUXが低下するので、本当に必要なケース以外で使うべきではありません。
たとえば動画アプリを入れたのに、動画を再生するまでにアラート画面が何個も出て、そのたびに「OK」を押さなければいけないのはうっとうしいですよね?

具体例は下記のようなケースです。

  • デバイスへのアクセス許可(カメラ、アルバム、位置情報など。これは最低限やらないと、App Storeに公開できません)
  • ユーザーID/パスワードの入力画面
  • テーブルビューの各アイテムへのアクセス(たとえばメーラーの個別のメール閲覧など)

Interface Builderか、コードか

さて、具体的な実装方法についてまとめていきたいのですが、
単純な画面遷移であれば、Interface Builderを使って、StoryBoardを編集すれば、プログラミングなしで実装可能です。
たとえばユーザーが画面のボタンを押したら画面が動く処理であれば、GUIで簡単に作れます。
ただもっと複雑な条件をつけたいのであれば、コードを書く必要があります。

Interface Builder

Interface Builderを使った方法を説明します。

Interface Builderでプッシュ遷移する

ノンプログラミングで、画面遷移を実装する方法を書きます。
image.png
完成形としてはこんな感じです。

下記の手順でいけます。

  1. 「Single Page Application」として新しいプロジェクトをつくる
  2. 「Main.storyboard」を選択
  3. 表示されているView Controllerを選択
  4. 「Editor」→「Embed In」 →「Navigation Controller」を選択
  5. 新たなView Controller(遷移先の画面)を追加する
  6. 一枚目のView ControllerにButtonを追加
  7. Controlを押しながら、追加したButtonを二枚目の画面へドラッグアンドドロップ ※わかりやすいように、一枚目の背景を赤、二枚目の背景を青に変えています。

ここまでやると、下記のような表示が出ると思います。
ちなみに、この矢印をSegue(セグウェイ)と呼びます。

image.png
「Show」を選択すると、プッシュ遷移ができます。

シミュレータで起動すると、こんな画面です。
image.png
Buttonを押してみましょう。

image.png
二枚目に遷移しましたね。
Navigation BarのBackを押すと前の画面に戻れます。

Interface Builderでモーダル遷移する

モーダル遷移も、プッシュ遷移と途中まで同じ方法で実装できます。

image.png
このとき、「Present Modally」を選択しましょう。
モーダル遷移に設定できます。

モーダルで遷移させた際は、Navigation Barが表示されません。
ここがプッシュ遷移との大きな違いです。
現在説明しているアプリの例だと、モーダル遷移にすると戻れなくなります。
モーダル遷移先の画面を閉じる処理は、何かしら開発者が実装する必要があります。

用語の整理

Interface Builderで画面と画面を結んでいる矢印をSegue(セグウェイ)と呼びます。
また、画面をSceneと呼びます。
Storyboard上で、SceneとSceneを結ぶのがSegueです。

コード

コードで画面遷移します。
Interface Builderは細かいUIを直感的に調整できるので、基本的には使うべきです。
ただ、エンジニアからすると、コードの外でUIの設定を持つので、ちょっと扱いづらいところがあるので、
原理主義的な人だと、Interface Builderは一切使わず、すべてコードでやってしまいます。
それはちょっと過激派ですが、Interface Builderでどこまでやるかはチームによるみたいです。
コードで画面遷移を実装する場合、Segueを使うか、使わないかが焦点になると思います。
やり方としては、どっちでもできます。

Segueを使ったプッシュ遷移

厳密に言うと、最初に紹介したInterface Builderを使って遷移する方法もSegueを使ったものです。
ただそのSegueの発動ポイントを、コード中に書くか書かないかの違いです。
Interface Builder上で、遷移元のViewControllerをControlを押しながらドラッグして遷移先のViewまでドロップしてください。
ドロップする際に、先程と同様に「Show」とか「Present Modally」とかを選ぶことになると思いますので、「Show」を選択してください。
すると2つのViewの間に矢印が出来たと思います。

image.png
この矢印がSegueをあらわしています。
Segueのidentifierに名前を入れましょう。
なんでもいいですが、ここでは例としてSegueNameと入れています。

そして、遷移元のViewController中で、画面遷移させたい場面に、下記のコードを入れてください。

//SegueNameはInterfaceBuilder上で自分がつけた名前にしてね
    performSegue(withIdentifier: "SegueName", sender: nil)

senderに変数を指定すると、値が受け渡せるので、全部Interface Buiderで行った例よりも、動作の幅が広がります。
ググると、selfをつけている例もありますが、ViewController内であれば、省略可能だと思います。

Segueを使ったモーダル遷移  

Interface Builder上でSegueを作成するとき、「Show」ではなく、「Present Modally」を選んでください。
あとはプッシュ遷移と同じです。

Segueを使わないプッシュ遷移

Segueを使わないでコーディングすると、どうなるのでしょうか。
ここでは、Storyboardをコードで呼び出して、そこから遷移先のViewControllerを指定し、プッシュ遷移する方法を紹介します。
まず遷移先のViewControllerのStoryboard IDに名前を入れてください。
image.png
ここではnextViewとしました。
あとは遷移させたいところに、下記のコードを書いてください。

let storyboard: UIStoryboard = self.storyboard!
let nextView = storyboard.instantiateViewController(withIdentifier: "nextView")
navigationController?.pushViewController(nextView, animated: true)

Segueを使わないモーダル遷移

遷移先のViewControllerのStoryboard IDに名前を入れるところまでは一緒です。

let storyboard: UIStoryboard = self.storyboard!
let nextView = storyboard.instantiateViewController(withIdentifier: "nextView")
//ここがpushとは違う
self.present(nextView, animated: true, completion: nil)

戻りたいときはdismissを使います。

ちなみに

遷移先のView / ViewControllerの生成とかやろうと思えばコードで記述できるので、Interface Builderをまったく使わないで画面遷移を書くこともできます。
まあでも、UIを細かく調整するのであれば、素直にInterface Builder使うが吉と思われます。

おまけ

Twitterやってます。エンジニアの知り合いが全然いないので、積極的につながりたいです!
よろしければフォローお願いします。

https://twitter.com/eg_19_

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

【iOS】波アニメーションが簡単に実装できるUIライブラリ「WaveAnimationView」を作りました!

どうもみなさま初めまして、mani(@mani_transm)と申します。

Swiftを触り始めてもうすぐ1年というまだまだiOSはルーキーな大学3年生ですが、この度OSSライブラリを開発、公開するところまで辿り着けました!?

開発自体はそんなに時間はかからなかったのですが、壁に当たっては乗り越えを何回も繰り返して体力が持ってかれたので、開発記はまた後日書こうと思います()

なので今回は、「こういうの作ったよー!」っていうのを書いていこうと思います!

iOSデベロッパーの方々に「良いなコレ〜」って思って頂けたら幸いです!(スターください)

WaveAnimationView is a library to install wave progress-animation for iOS.
GitHub: WaveAnimationView - A library to install wave progress-animation for iOS

Waveアニメーションを簡単に実装できるUIライブラリ

今回作ったのがこちらの「WaveAnimationView」。
波のアニメーションを簡単に実装できる、いわゆるUIライブラリですね。
WaveAnimationView-header-min.png
以前から個人でアプリ開発やってて、アニメーションとかこだわるタイプだったので、
「Waveアニメーションのライブラリとかないかなー」と思って調べたら全く無かったっていうのが今回このWaveAnimationViewを作るに至ったきっかけです。

「WaveAnimationView」で出来ること

気になるWaveAnimationViewで出来る事ですが、

主にProgressViewやLoading,背景のアニメーションで波形アニメーションを実装することができます!

Demoとして作ってみたものが下です↓

Progress Loading Background
sample_1.gif sample_2.gif sample_3.gif

使い方

※導入方法はCocoaPods、Carthageに対応してます。詳しくはGitHubをご参照のほど。

WaveAnimationViewは、

1. インスタンス生成
2. startAnimation()を呼ぶ
3. stopAnimation()を呼ぶ(ViewControllerが解放される時点で)

の、この3行だけ書けばアプリに導入できます。

import UIKit
import WaveAnimationView

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // 1
        let wave = WaveAnimationView(frame: CGRect, color: UIColor)

        //superView.addSubView(WaveAnimationView)

        // 2
        wave.startAnimation()

    }

    override func viewDidDisAppear() {
        super.viewDidDisAppear(animated)

        // 3 - Be sure to read the following Attension!
        wave.stopAnimation()

    }
}

またDemoのように、WaveのfillColorを前面・背面で別々に変えたり、
好きな画像を用意するだけでマスク処理ができたり
などオプションもあります。

Front/Back FillColor

let wave = WaveAnimationView(frame: CGRect, frontColor: UIColor, backColor: UIColor)

maskImage

wave.maskImage = UIImage(named: "image name")

Set/Get Progress

//get progress
wave.progress = 1.0 //0.0 .. 1.0, default is 0.5

//set progress - Example: UISlider
@IBAction func slide(_ sender: UISlider) {
     self.wave.setProgress(to: sender.value //0.0 .. 1.0)
}

「UIProgressViewと基本的には同じ機能を持ちつつ、好きな形でWaveアニメーションを組み込める」というのがWaveAnimationViewを開発する上で意識した利点です。

GitHubリポジトリはこちら

最後にリポジトリへのURLを貼っておきます。

初めてのライブラリ制作なので、「全然コードがなってない!」とか「ここもっと良い感じに改良できるよ」っていうのがありましたら是非是非Twitterでも大丈夫なのでフィードバックをお願いします!?Twitter: @mani_transm

※READMEが結構ガバガバ英語かもしれないのでご容赦ください(白目)

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

PENGELUARAN HK

pengeluaran hk adalah situs terpercaya untuk semua hasil keluaran result HK dan pengeluaran togel hongkong,dan semua sejarah togel honkong.
Bagi para pencita togel kami menyediakan situs terpercaya di dunia,dan menyediakan pengeluaran Hk yg ada di dunia.
Kami juga menajikan data-data togel bergengsi lainnya seperti Togel Sidney,Togel Singapore,dan Togel Macau yang pastinya terpercaya dan terbaik di dunia.

pengeluaran hk juga menyajikan prediksi togel yang bergengsi di dunia, terpercaya bagi pecinta togel dan terlengkap di dunia.

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

iOSでAVと向き合う Vol.1 基本編

はじめに

Appleプラットフォーム(iOS/macOS/tvOS)ではオーディオビジュアル(AV)の再生と作成をAVFoundation1 2AVKit3というFrameworkで実現しています 。

今回からドキュメントの内容を翻訳・写経したり、先駆者の記事を読み解きつつこれらのFrameworkについてまとめていきたいと思います。

本シリーズのゴール

読者の皆様にiOSでAVの再生と作成を行うための基礎と取っ掛かりをインプットし、アプリケーションの開発時に困らなくなることをゴールとします。

この回でのゴール

次回以降の説明に備え、AVFoundationやAVKitの概要を知ること

本シリーズの対象者

本シリーズの対象者は以下のスキルセットを持ち、iOSでAVを再生したり作成したりについて興味がある方が対象です。
- iOSアプリの開発を行ったことがある
- Swift/Objective-Cがある程度分かる人

注意

  • 本シリーズでは主にiOSに限定して話を展開します。
  • 本シリーズで出てくる単語 AVとは = オーディオビジュアル = ビデオ、音声・音楽のことです

iOS上でAVを取り扱うためには

iOSでは以下のようなアーキテクチャでAVを取り扱います。それぞれの四角形がFrameworkとなっています。
AVFoundationではCore Audio、Core Media、Core AnnimationのFrameworkを活用してAVの各種操作を可能にしています。

Core ~~ Framework

Core ~~~ と名前の付いたFrameworkでそれぞれメディアの低レベルレイヤでの処理(映像や音声へのバイトデータ操作など)や処理で利用するデータ型を提供しています。

Core Media

AV処理で欠かせない各種パイプライン処理と処理で利用するデータ型を定義しています4。具体的には、Core Media でAVの各フレームでのピクセルデータ、音声の波形データなどを参照・操作することが可能になります。

Core Audio

音声を処理するために必要なデータ型を定義し、それらはオーディオ関係の処理でハードウェアとのやり取りに使用することができる5

Core Animation

Viewやその他の画面に表示されるような要素をアニメーションさせるために使われるグラフィックの描画やそれに必要なデータ型を定義したFrameworkになります6

つまり、AVの再生時においてCore Mediaで処理した各ピクセルデータを端末内のオンボードグラフィックスハードウェア(いわゆるGPU部分)に渡されてアニメーションとしてView内に表示します。

AVFoundationとは

AVFoundationは、AVの再生と作成に使用できるフレームワークで、AVに関する作業を細かいレベルで行うためのインタフェースを提供してくれます。たとえば、メディアファイルの再生、検査、作成、編集、再エンコードなどができます。他にも、デバイスから入力ストリームを取得して、リアルタイムでキャプチャ中 および再生中のビデオを操作することもできます。

ざっくり言ってしまうと、iMovieの各種機能がプログラムから呼び出せるイメージです。

AVKit

AVFoundationの機能にUIKit内で定義されているコンポーネントをもとにUIを与え、それらを呼び出せるようにしているFrameworkです。AVを再生したい、UIの用意は自分でしなくでもOSデフォルトのUIが与えられれば良いといった方のためのものです。

ユーザーコントロール、チャプター操作、字幕やクローズドキャプションのサポート、再生ルート選択機能を備えたメディア再生用のUIを提供してくれます。AVの操作や編集は未対応です。加えて、再生時のUIは決まったものが提供される関係上カスタマイズできる余地も少ないです。

avplayercontroller.png7
8
9

まとめ

基本的にはiOS上でAVを取り扱っていく際は、AVFoundationを学んでいくのが最初は良いと思います。

AVを再生したいだけで、UIのカスタマイズはあまり考えてない、その他の機能も要件的に必要ない場合はAVKitを勉強して利用すると簡単で良いかと思います。

次回はAVメディアの再生に重きを置き、サンプルプログラムを実装しつつ理解を深めていきましょう。
その2(まだ未投稿)へつづく

参考文献

iosの動画再生周りの基礎を調べた
AVPlayerについて調べた

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

state pattern

state pattern

状態に依存する処理を状態オブジェクトへ委ねる

ケース

振る舞いを状態によって変えたいとき

結果

pro

状態に依存してる処理をきりだせる。

con

実装対象

Contextクラス 状態Stateオブジェクトを保つクラス
Stateインターフェイス
ConcreteStateの実装

example

class Connection {
    private let state: StateProtocol

    init() {
        self.state = CloseState()
    }

    func open() { state.open() }

    func close() { state.close() }

    func setState(state: StateProtocol) {
        self.state = state
    }
}

protocol StateProtocol {
    func open(connection: Connection)
    func close(connection: Connection)
}

class OpenState: StateProtocol {
    func open(connection: Connection) {} // open の時openは何もしない
    func close(connection: Connection) {
        connection.setState(state: CloseState())
    }
}

class CloseState: StateProtocol {
    func open(connection: Connection) {
        connection.setState(state: OpenState())
    }
    func close(connection: Connection) {} // close の時closeは何もしない
}

stateオブジェクトはContextオブジェクトのオペレーションを呼び出すことがメイン業務

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

template method pattern

template method pattern

ケース

アルゴリズムの部分部分を置き換え可能にしたいとき。

結果

pro

デフォルト挙動から部分のみを容易に変更できる。

con

実装をオーバーライドしないといけない。(継承する必要が高い)

実装対象

AbstractClass テンプレートメソッドとオーバーライドされうるメソッドの実装
ConcreteClass 必要なオーバーライド実装

おまけ

hook operationを定義してサブクラスに拡張を許すことも可能
AbstractClassは何もしない名前だけのオペレーションを定義し、
テンプレートメソッドはそれを呼び出す。
こうすることで、AbstractClassはConcreteClassに任意の処理を挟み込むことを許す。

example

class AbstractOrder {
    // template method
    func order(input: Input) {
        validate()
        pay()
        payHookOperation() // hook operation
        updateStock()
        notify()
    }

    func validate() { // do something }
    func pay() { // do something }
    func payHookOperation() {} // do nothing!!
    func updateStock() { // do something }
    func notify() { // do something }
}

class DegitalOrder: AbstractOrder {
    // 必要なもののみオーバーライド
    func updateStock() { // 在庫管理してない、デジタル商品を扱う }
}

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

strategy pattern

strategy pattern

ケース

あるクラス(Context)の振る舞いのみを変えたいとき イコール 振る舞いだけが違う似たクラスがたくさんあるとき
あるクラスの内部アルゴリズムを交換可能にしたいとき
実行条件によって振る舞いが多岐にわたるとき=処理を固定して注入する
クライアントが振る舞いの種類を知っているとき

逆にそうじゃないケースは単なるコンポジションと移譲のケース。

結果

pro

継承無しで振る舞いのみを変えられる。

con

クライアントが、振る舞いを決定する必要がある。当然決定するために、知っている必要もある。
状況によってはContextとStrategyの結合度が高まる。

実装対象

振る舞いを変えたいクラス(Context)。これがStrategyオブジェクトを保持する。
Strategyクラスのインタ=フェイス
具体的なStrategyインターフェイスの実装

難しさ

結果のcons で述べたが、ContextとStrategy間のインターフェイスに注意しなければならない。

ContextオブジェクトはStrategyにパラメータを渡すケースがある。(多くの場合そう)
方針は2つ
1. Strategy インターフェイスがContextオブジェクト自体を受け取る。
2. Strategy インターフェイスが各Strategyの最大公約数な引数を受け取る。

1のメリット
新しい種類のStrategyの追加が容易になる。(デメリットでもあるが)

1のデメリット
結合度が高くなる。

2のメリット
結合度が低く保てる。

2のデメリット
あるStrategyは必要のないデータを受け取ることになる。 イコール あるConcreteStrategyクラスだけを見たとき依存が不透明になる。

example

// Strategy
protocol PaymentStrategy {
    func pay(input: PaymentInput) -> Bool
}

// 最大公約数なinput
protocol PaymentInput {
    var address: String
    var name: String
    // etc
}

// Context
class  Order {
    let paymentStrategy: PaymentStrategy

    init(paymentStrategy: PaymentStrategy) {
        self.paymentStrategy = paymentStrategy
    }

    func doOrder(input: OrderInput) {
        // exec validation
        // some process

        let isSuccess = pay(input: input) // OrderInputは PaymentInputも満たすとする。

        // some process
    }
}

let paymentStrategy = CreditCardPaymentStrategy() // PaymentStrategyインターフェイスを満たすもの
let order = Order(paymentStrategy: paymentStrategy) // PaymentStrategyインターフェイスを満たすもの
order.doOrder(input: OrderInput)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Swift5.0チートシート ~Swift 5.0を爆速でキャッチアップしよう!~

この記事について

「Swift5.0のキャッチアップをまだできてない...! 」という方に向けて、Swift5.0のアップデートについてまとめたチートシートを作りました。

今回23個もの項目があるので、なるべくスマート✨かつ爆速?でキャッチアップしちゃいましょう!

なるべくシンプルな説明になるよう心がけています。内容の詳細については、公式ドキュメントを参考にするのが良いと思います。
今回載せる画像自体の転用は自由ですのでご自由にご利用ください。

全体の内容がまとまったスライドはこちらです
筆者の理解も完全ではないので、訂正がありましたらご指摘いただけると幸いです。mm

目次

  1. 全体的なアップデート
  2. 標準ライブラリのアップデート
  3. 言語仕様/コンパイラのアップデート

1. 全体的なアップデート

ABI Stability

Swift5 Cheet Sheet

2. 標準ライブラリのアップデート

1. Stringの特殊文字

Swift5 Cheet Sheet (1)

2. Unicode Property

Swift5 Cheet Sheet (2)

3. 型名の変更 (DictionayLiteral -> KeyValuePairs)

Swift5 Cheet Sheet (3)

4. Never型のプロトコル準拠

Swift5 Cheet Sheet (4)

5. ContactValueMapの追加

Swift5 Cheet Sheet (5)

6. Character Propertiesの追加

Swift5 Cheet Sheet (6)

7. isMultipleの追加

Swift5 Cheet Sheet (7)

8. 文字列補間のカスタマイズ

Swift5 Cheet Sheet (8)

9. SIMD Vectorsの追加

Swift5 Cheet Sheet (9)

10. カスタマイゼーションポイントの除外

Swift5 Cheet Sheet (10)

11. Numericプロトコルの修正

Swift5 Cheet Sheet (11)

12. Sequence.SubSequenceの消去

Swift5 Cheet Sheet (12)

13. Result型の追加

Swift5 Cheet Sheet (13)

14. withContiguous{Mutable}StorageIfAvailableの追加

Swift5 Cheet Sheet (14)

15. RangeのCodableへの準拠

Swift5 Cheet Sheet (15)

16. StringのencodedOffsetの廃止

Swift5 Cheet Sheet (16)

3. 言語仕様/コンパイラのアップデート

17. Enumへのunknown詞の追加

Swift5 Cheet Sheet (17)

18. リテラルを使った強制init

Swift5 Cheet Sheet (18)

19. Dynamically callable

Swift5 Cheet Sheet (19)

20. compilation conditionsの未満オプション

Swift5 Cheet Sheet (20)

21. Identity keypath

Swift5 Cheet Sheet (21)

22. try?のオプショナル構造の簡略化

Swift5 Cheet Sheet (22)

あとがき

いかがでしたでしょうか?
Swiftの最新バージョンに触れてみることは、自分のコードの品質チェックのきっかけになるのはもちろん、今まで触ったこともない仕様との出会いがあったりして非常に楽しいものです。Swift5.0はxcode10.2以上で動かすことができるので、皆さんもぜひ一度ご自身でコードを書いて見てください。

参考にした記事

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

AtCoderにSwiftで挑戦するときの標準入出力

AtCoderにSwiftで挑戦しようとしました。
まだAtCoderのことよくわかっていないのですが、とりあえずSwiftのバージョンは未だに2.2みたいです。
Swiftは今バージョン5まで来たので、2.2なのは結構キツイです。
僕は今年からSwift勉強しはじめて、入り口はバージョン4なので、過去のバージョンアップで変更された部分はよく把握していないのですが、
ざっと見る限りバージョン2から3に上がったときの変更が結構エグかったのかな、という印象で、
メンテされてないSwiftコードは軒並みそのままだと動かなくなってるように見えます。
なので、Swift 2.2でやるとなると、その古い書き方を調べないといけなくて、しんどいです。
C++勉強しろや、ってことなんですかね。。。

詰まった部分

標準入力を受け取って、ブランクで値を分割するところですが、下記のコードだとコンパイルエラーになります。

components(separatedBy)
let input_line: String = readLine()!
let split: [String] = input_line.components(separatedBy: " ") //ブランクで区切られている場合

これはSwift2.2にはcomponents(separatedBy:)ではなかったからです。

サンプルコード

練習問題を解いた例を載せます。

practice contest

practice_contest
import Foundation

var input_lines = [String]()
let row = 3
for i in 0..<row {
    input_lines.append(readLine()!)
}

let a = Int(input_lines[0])!

let split = input_lines[1].componentsSeparatedByString(" ") //components(separatedBy:)と実質同じ
let b = Int(split[0])!
let c = Int(split[1])!

let s = input_lines[2]

print((a + b + c), s)

splitでやる

charactersに対して、splitメソッドを使ってやる方法もあります。

AtCoder に登録したら解くべき精選過去問 10 問を Swift で解いてみた

こちらもSwift2.2では記法が若干違うので、辛さ的にはあまり変わりませんね。

関連

Swift3.0以降はこちらが参考になるかと。
paizaの問題をSwiftで挑戦するときの標準入出力

おまけ

Twitterやってます。エンジニアの知り合いが全然いないので、積極的につながりたいです!
よろしければフォローお願いします。

https://twitter.com/eg_19_

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

composite pattern

composite pattern

swift の uiview

ケース

部分の集まりで全体が構成されてるとき
部分と全体を表現して、クライアントからは同一として扱いたいとき

結果

pros

クライアントは複雑な構成のオブジェクトも簡単に扱える。
扱う種類が簡単に増やせる。

cons

全体にとけ込めない特別な要素は増やしにくい。
ので事前の洞察が大切。

実装対象

要素(component)のinterface
Component interfaceを満たす子を保持できるCompositeの実装
(Component interfaceを満たす子を保持できないLeafの実装)
子がないcompositeをleafとすればleafは必要ない。

難しさ

Leafを作るとすると、addやremoveといった子を操作するインターフェイスを
componentかcompositeのどちらに持たせるかが分岐。
componentに持たせるならLeafはadd, removeを空のメソッドとして実装する必要がある。
シンプルに無駄である。
compositeに持たせるなら、Leafに対してadd, removeを呼び出せないので、部分と全体を同一に扱えなくなる。interfaceが異なるため。
この場合、子を扱う前にcomposite型への変換を試み、確認しなければならない。

Leafを作らない場合は例えば、Compositeがコンポジションとして、ノードとしての要素を別に保持するとか。UIViewとCGRectみたいな

あとは子供の順番に意味を持たせるかの分岐もある。

example

UIviewの例があるので省略

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

未経験がSwift言語で簡易的なtodoアプリを作ってみた

背景

  • Todoするフレームワーク
  • スポーツtodoアプリを実装する前の段階の環境構築

前提

  • 特にライブラリを使用しない。

今回のOutPut

  • Todoアプリを追加、表示
  • 削除機能はない

(図1.1 出力結果)


(図1.2 出力結果)

import UIKit
import FSCalendar
import CalculateCalendarLogic

class ViewController: UIViewController,FSCalendarDelegate,FSCalendarDataSource,FSCalendarDelegateAppearance{

    @IBOutlet weak var calendar: FSCalendar!


    override func viewDidLoad() {
        super.viewDidLoad()
        // デリゲートの設定
        //self.calendar.dataSource = self
        //self.calendar.delegate = self

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    fileprivate let gregorian: Calendar = Calendar(identifier: .gregorian)
    fileprivate lazy var dateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter
    }()

    // 祝日判定を行い結果を返すメソッド(True:祝日)
    func judgeHoliday(_ date : Date) -> Bool {
        //祝日判定用のカレンダークラスのインスタンス
        let tmpCalendar = Calendar(identifier: .gregorian)

        // 祝日判定を行う日にちの年、月、日を取得
        let year = tmpCalendar.component(.year, from: date)
        let month = tmpCalendar.component(.month, from: date)
        let day = tmpCalendar.component(.day, from: date)

        // CalculateCalendarLogic():祝日判定のインスタンスの生成
        let holiday = CalculateCalendarLogic()

        return holiday.judgeJapaneseHoliday(year: year, month: month, day: day)
    }
    // date -> 年月日をIntで取得
    func getDay(_ date:Date) -> (Int,Int,Int){
        let tmpCalendar = Calendar(identifier: .gregorian)
        let year = tmpCalendar.component(.year, from: date)
        let month = tmpCalendar.component(.month, from: date)
        let day = tmpCalendar.component(.day, from: date)
        return (year,month,day)
    }

    //曜日判定(日曜日:1  土曜日:7)
    func getWeekIdx(_ date: Date) -> Int{
        let tmpCalendar = Calendar(identifier: .gregorian)
        return tmpCalendar.component(.weekday, from: date)
    }


    // 土日や祝日の日の文字色を変える
    func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, titleDefaultColorFor date: Date) -> UIColor? {

        //let selectDay = getDay(date)

        //祝日判定をする(祝日は赤色で表示する)
        if self.judgeHoliday(date){
            return UIColor.red
        }

        //土日の判定を行う(土曜日は青色、日曜日は赤色で表示する)
        let weekday = self.getWeekIdx(date)
        if weekday == 1 {   //日曜日
            return UIColor.red
        }
        else if weekday == 7 {  //土曜日
            return UIColor.blue
        }

        return nil
    }

}

次回やりたいこと

  • カレンダーアプリと組み合わせたい
  • 機能追加
  • メイン画面に日付をタップしたら、予定を画面下半分に表示
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【学習記録22】2019/5/12(日)

学習時間

4.0H

使用教材

改訂新版Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 WEB+DB PRESS plus

学習分野

第6章型の種類
第7章プロトコルの基本

コメント

学習開始からの期間:22日目
今日までの合計時間:68.0H

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

builder pattern

builder pattern

obejectのセットアップ過程を切り出す。

ケース

オブジェクトの内部表現が
多岐にわたるときや
構造が複雑なとき。

結果

pros

生成したいオブジェクトの内部表現が切り出され、変更が容易になる。

cons

ない。

実装対象

生成したいオブジェクト(product)の内部表現を変更するインターフェイス(Builder)
生成したいオブジェクト(product)の内部表現を変更するオペレーション(ConcreteBuilder)
Builderインターフェイスの使い方を実装するクラス(Director)

example

Roomを作る例。

protocol RoomBuilderProtocol {
    // sideCount 角形の床を設置する
    func buildFloor(at story: Int, sideCount: Int)
    func buildWall(for side: Int)
}

class RoomBuilder: RoomBuilderProtocol {
    func buildFloor(sideCount: Int) {
        room.floor = Floor(sideCount: sideCount)
    }

    func buildWall(for side: Int) {
        let wall = Wall()
        room.walls.append(wall)
        room.floor.setWall(wall, for: side)
    }

    var room = Room()
}

class Director {
    func constructNormalRoom(builder: RoomBuilderProtocol) {
        // 四角形の床
        builder.buildFloor(sideCount: 4)
        // 全面に壁を設置
        builder.buildWall(for: 0)
        builder.buildWall(for: 1)
        builder.buildWall(for: 2)
        builder.buildWall(for: 3)
    }

    func constructStrangeRoom(builder: RoomBuilderProtocol) {
        // 5角形の床
        builder.buildFloor(sideCount: 5)
        // 1面にだけ壁を設置
        builder.buildWall(for: 0)
    }
}

let builder = RoomBuilder()
let director = Director()
director.constructNormalRoom(builder: builder)
let normalRoom = builder.room

let builder2 = RoomBuilder()
director.constructStrangeRoom(builder: builder2)
let strangeRoom = builder2.room

Directorクラスはbuilderのインターフェイスを利用するだけに留まっている。
最終成果物はdirectorから取得するのではなく、builderから取得することに注意。

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

vapor xcode実行ができなくてハマった件

下記の記事を参考にVaporでサーバーサイドSwiftの環境構築を行った時に、以下のエラーが出てハマった話。
https://qiita.com/toshi586014/items/9f763f9ce6a4793d7c8b

結果から書くと、プロジェクト内のcloud.ymlで定義していた
swift_version: "4.1.0"
とインストールされているswiftのバージョンの不一致が原因だった。

以下のコマンドでインストールされているswiftのバージョン確認
$ swift -version

※自分の場合swift_version: "5.0.1"に修正して、再度vapor xcodeを実行したら成功した。

以下、出力されたエラー↓

$ vapor xcode
Generating Xcode Project [Failed]
/Users/~/Hello: error: manifest parse error(s):
:5:9: note: in file included from :5:
¥#import "copyfile.h"
^
~~~

:0: error: could not build Objective-C module 'Darwin'

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