詳解Swift 第5版 第2章まとめ -オーバーロード・タプル-


こんにちは、マっさんです!

この記事は筆者に必要な部分を切り出し、まとめたものです。
詳しい内容を知りたい方は、ご購入をおすすめします。
S

詳解 Swift 第5版

詳解 Swift 第5版

オーバーロード

オーバーロードとは

同じ関数名で、引数の個数が違ったり、型が違う別の関数を定義する事を言います。
これを関数のオーバーロードと言います。

//(1)引数が二つの関数
func mySwap(_ a: inout Int, _ b: inout Int){
    let t = a; a = b; b =t
}

//(2)引数が3つの関数
//同じ関数名で引数が異なる関数が定義できる
func mySwap(_ a: inout Int, _ b: inout Int, _ c: inout Int) {
     let t = a; a = b; b = c; c = t 
}

var s = 10, t = 20
var x =1, y = 2, z =3
mySwap(&s, &t) //(1)を呼び出し
print("s=\(s), t=\(t)")

mySwap(&x, &y, &z) //(2)を呼び出し
print("x=\(x), y=\(y), z=\(z)") 
// 実行結果
s=20, t=10
x=2, y=3, z=1

また、返り値の異なるオーバーロード関数を定義する事もできます。
ただし、返り値の型が明確になる様な使い方をしないと、コンパイラが混乱する為、あまり使ってはいけません。

引数ラベルを使ったオーバーロード

Swiftではさらに、引数ラベルとして異なる識別子を指定することにより、同名で別の関数を定義できます。
下記の例を使って、以下の様に定義できます。

func mySwap(_ a: inout String, _ b: inout String) {
    let t = a; a = b; b = t
}

var a = "Alcott", b = "Bodewig"
mySwap(&a, &b)
print("a=\(a), b=\(b)")

func mySwap(little a: inout Int, great b: inout Int) {
    if a > b {
        let t = a; a = b; b = t
    }
}

s = 10; t = 20
mySwap(little:&s, great:&t)
print("s=\(s), t=\(t)")
mySwap(little:&t, great:&s)
print("s=\(s), t=\(t)")
// 実行結果
a=Bodewig, b=Alcott
s=10, t=20
s=20, t=10

この様に、同名関数、別名ラベル・別型の引数なら使用することができます。
これが、オーバーロードです。

Apple社のドキュメントに記載されている関数について

オーバーロードの説明をしていますが、これを応用してAppleのドキュメントについて説明します。 まずこちらのAppleのDocumentをみてください。
f:id:MasayaStripes:20191204150033p:plain この記法は、Apple のドキュメントでよく見かける記法であります。
この記法の意味は、まず関数名が記載され、()内に引数ラベル「 _ 」と「 : 」を交互に書き並べています。
つまり、この関数absの呼び出し方としては、「 _ 」なので、「引数ラベルはなんでも良い」
と言うことになります。
もし指定されているのであれば、例として”mySwap(little:great:)”と言う風に書かれます。

タプル

タプルとは

タプルとは、
複数個のデータを組みにしてまとめたものです。
これは、一時的に保持したりするとうな用途で使うべきです。
複雑になる場合は、構造体や辞書型、もしくはクラスを使いましょう。

以下が使い方の例になります

let m = ("moneky.jpg", 161_022) // ファイル名とバイト数

// 型宣言した場合
let m : (string, Int) = ("moneky.jpg", 161_022)

二つだけでなく、複数の要素でも使えます。

let cat = ("cat .jpg", 1024, 768)
var img : (String, Int, Int) = cat // 代入可能

print("\(img.0): \(img.1) x \(img.2)")
img.2 = 800
print("\(img.1)x\(img.2)")
//実行結果
cat .jpg:1024x768
1024x800

タプルと代入操作

タプルの代入操作は以下の様に代入できます。

let photo = ("tiger.jpg", 640, 800)
let (file, width, height) = photo
print("\(file): \(width)x\(height)") 

// 実行結果
tiger.jpg: 640x800

ここでも、ワイルドカードの"_"を使うことができます。
ここでの意味は、
その値を明示的に使用しない
という意味です。

// ファイル名だけを使う
let (file, _, _) = photo

任意のインスタンスもタプルに入れることができます。
例えば、タプル内にタプルを入れるということもできます。

let pic = ("snake.jpg", (780, 1024))
let (file, (w, h)) = pic
let(name, _) = pic

このタプルを使えば初心者の方には比較的難しい、フィボナッチ数列も簡単に実装できます。

var fibo1 = 0, fibo2 = 1

print(fibo1, terminator: " ")
for _ in 0 ..< 50 {
    (fibo1, fibo2) = (fibo2, fibo1 + fibo2)
    print(fibo1, terminator:" ")
}
print()
//実行結果
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 14930352 24157817 39088169 63245986 102334155 165580141 267914296 433494437 701408733 1134903170 1836311903 2971215073 4807526976 7778742049 12586269025 

タプルを返す関数

タプルは関数の処理結果を返すこともできます。
利点としては、
複数の値を手早く受け取れる、処理できる
という点です。

func BMI(tall:Double, weight:Double) -> (Double, Double) {
    let ideal = 22.0
    let t2 = tall * tall / 10000.0
    let index = weight / t2
    return (index, ideal * t2)
}

let result = BMI(tall:177.0, weight:80.0)
print(result)
(25.535446391522232, 68.9238)

考察

今回はオーバーロードとタプルについて、まとめていきました。
特に私にとってタプルはすごく使いやすくて、個人プロジェクトや実装で使っています。
Swiftには他の言語では見られない、より賢く書く書き方があるイメージが多くある様に見受けれました。(まぁPerl とJavaしか本格的にやったことないんですがねw)

今回は以上!

詳解 Swift 第5版

詳解 Swift 第5版

Android 9 で WebViewから ERR_CLEARTEXT_NOT_PERMITTED が出てきたので、解決した

f:id:MasayaStripes:20191208163919p:plain

こんにちは。マっさんです。

今回は、開発途中でAndroid 8以前では出てこなかった、WebView上での”ERR_CLEARTEXT_NOT_PERMITTED”のエラーの解決策を記事にします。

解決方法

まずは解決方法です。"AndroidManifest.xml" ファイル の タグ内に以下を記載してください。

<application
        android:usesCleartextTraffic="true">
 ・・・
</application>

原因

Android 9 から 機密性の高いトラフィックを実現するため、デフォルトで、
cleartextTrafficPermitted="false"
になりました。その為、こちらで明示的に追記する必要が出てきました。

developer.android.com

懸念点

この解決方法の場合、暗号化されていない、HTTP通信を許可することにもなってしまいます。
もし必要なドメインからのみの、セキュアな通信を受け付ける様にしたい場合は、
"res/xml/network_security_config.xml"
を作成し、以下のソースコードを追記してください。

    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
        <domain-config cleartextTrafficPermitted="false">
            <domain includeSubdomains="true">secure.example.com(接続させたいドメイン名)</domain>
        </domain-config>
    </network-security-config>

以上です。

詳解Swift 第5版 第2章まとめ -関数定義における設定-


こんにちは、マっさんです!

この記事は筆者に必要な部分を切り出し、まとめたものです。
詳しい内容を知りたい方は、ご購入をおすすめします。

詳解 Swift 第5版

詳解 Swift 第5版

-関数定義における設定-

inout引数

関数内での処理によって呼び出し側の変数の値を書き換えたい場合は、
inout引数
を利用します。

func mySwap(_ a: inout Int, _ b: inout Int){

    // 二つの引数の値を入れ替える
    let t = a; a =b; b =t

}

inout引数を指定した関数を呼び出して使うために、"&"を付けた変数を指定する必要があります。

var x =100
var y =0
mySwap(&x, &y) //実行後、x =0, y =100 となる

関数の引数に既定値を指定する

関数の引数の中には、決まった値をが指定される引数が存在することがありますが、それを
既定値
として決まった値を割り当てておき、呼び出す際には実引数の指定を省略出来るようにしておけば、便利になります。
例としまして、

  • print(_:separator:terminator:)

の指定が挙げられます。
また、以下のプログラムが引数に既定値が指定された関数になります。

let fontSize: Float = 12.0
func setFont(name:String, size:Float = fontSize, bold:Boolean = false) {

    print("\(name)\(size)" + (bold ? " [B]" : ""))

}

func setGray(level:Int = 255, _ alpha:Float = 1.0) {

    print("Gray=\(level), Alpha=\(alpha)")

}


// 関数の呼び出し、及び結果
// この関数は第一引数意外を省略することができます
setFont(name:"RaglanPunch")            // RaglanPunch 12.0
setFont(name:"Courier", bold:true)    // Courier 12.0 [B]
setFont(name:"Times", size:16.0, bold:true) // Times 16.0 [B]

// この関数は二つの引数を省略できますが、引数の順番は固定されています
setGray()                 // Gray=255, Alpha=1.0
setGray(level:240)        // Gray=240, Alpha=1.0
setGray(level:128, 0.5) // Gray=128, Alpha=0.5

以下が指定された引数の定義と使い方に関するルールです。

  • 既定値を持つ引数は引数リストのどこにあっても構いません。しかし、その引数よりも後ろ(右)の既定値を持たない引数には必ず引数ラベルを付けてください。

  • 引数ラベルを持つ複数の引数に、既定値が指定されている場合、引数リストで定義されている順序が守られているかぎり、どれをラベル指定しても、省略しても構いません

  • 引数ラベルを持たない引数に既定値が指定されている場合、ある引数から後ろ(右)をまとめて省略できますが、途中の引数だけを省略することはできません

まとめるとこうです。

既定値が指定された引数の定義と使い方は、自由度は高いが、紛らわしい為、引数ラベルを必ずつけるようにすべきです。

引数の値は関数内で変更できない

Swiftでは、関数の仮引数に与えられた値は、基本的に処理中に変更はできません。 変更して使いたい場合には、以下のようにすれば良いです。

    var y = yy, m = mm

つまり、値を変更すれば良いのです。
この考えを用いたプログラムが以下です。

// このプログラムは日付から曜日を計算するツェラーの公式をプログラムにしたものです。

func daytOfWeek(_ y : Int, _ m : Int, _ d:Int) -> Int {

    var y = y, m = m     // !!変数y, m は仮引数とは違います!!!

    if m < 3 {             //1,2 月だったら
       m += 12; y -= 1  // 前年の13月、14月として計算する
    }

    let leap = y + y/4 - y/100 + y/400

    return (leap + (13 * m + 8) / 5 + d) % 7

}

print(dayOfWeek(1994, 2, 1))  // 1994.02.01  -> result:2(火曜日)
print(dayOfWeek(2019, 11, 30)) // result: 6(土曜日)

返り値を使わない場合を許す指定

Swiftの場合、関数呼び出しの結果の値が使われない場合、コンパイラが警告を出します。
本当に値を使う必要がないことを示すには、"_"に対する代入を記述すべきです。

ただし、必要な時だけ返り値を使えば十分で、本来なら無視して良い値の場合、定義の直前に
属性
を指定します。やり方は以下の通りです。

@discardableResult // 属性(attribute)
func sayHello(to n:String) -> Bool { ... }

このような書き方をすれば、コンパイラやインタプリタは特に警告を表示しません。

関数内の関数(ネスト関数)

ネスト関数とは、その関数だけが下請けとして使用できる関数定義を、自分自身の定義の中に含めることができます。
関数内で定義された関数は外部からはアクセスできません。
以下がプログラム例となります。

// ひと月のカレンダーを表示する関数

func printMonth(first fday:Int, days:Int) {
    var d = 1 - fday             // 月のはじまりの空白は負と0で表す
    func daystr() -> String {    // 関数内のローカルな関数
        if d <= 0 {              // 変数dは上で定義したもの
            return "    "        // 月初めの空白
        }else {
            return (d < 10 ? "   \(d)" : "  \(d)")
        }
    }

    while d <= days {
        var line = ""             // 一週間分の日付を並べる
        for _ in 0 ..< 7 {
            line += daystr()      // ネスト関数を使用
            d += 1
            if d > days { break } // 月末になったら抜ける
        }
        print(line)
    }
}

printMonth(first:1, days:31)

結果は以下のようになります。

       1   2   3   4   5   6
   7   8   9  10  11  12  13
  14  15  16  17  18  19  20
  21  22  23  24  25  26  27
  28  29  30  31

このネスト関数はクロージャーとしての性質も持ちます。(クロージャーに関しては後ほど。)

考察

今回は関数の定義についてまとめました。
Swiftの開発を初めて半年が過ぎた私にとって、こういった書き方をまとめられているのはありがたいですw
実際の開発を行い、文法レイヤーではわかりますが、なぜこの様な書き方になっているのか?なぜこの書き方ができるのか?というところ はどの様に調べたら良いかいまいち掴めていませんでした。
ここでは、引数ラベルの部分や、ネスト関数に当たります。
引数にラベルつけること自体初めて見ましたし、ネスト関数は基本的に他の言語では使ったことはありませんでした。
やはり現場レベルでの実装経験や、その様な知識をつけることは必要と感じたこの頃でした。

今回は以上!

詳解 Swift 第5版

詳解 Swift 第5版

詳解Swift 第5版 第2章まとめ -関数定義の基本-


こんにちは、マっさんです!

この記事は筆者に必要な部分を切り出し、まとめたものです。
詳しい内容を知りたい方は、ご購入をおすすめします。

詳解 Swift 第5版

詳解 Swift 第5版

-関数定義の基本-

関数定義の基本

基本的な関数の書き方は以下のようになります。

// 仮引数は複数指定可能
func 関数名(仮引数: 型) ->  型 {
  文・・・ 
        return   // 値を返す関数では、文中に必ず"return"が必要
}

以下が具体例な関数の記載方法と呼び出し方法になります。

var total = 0

func count(n: Int) -> {   // 整数の引数をとり、整数を返す
    total += n
    return total
}

func reset() { total = 0 } //引数も返り値もない
reset()
let a  = 10
let b = count(n: a - 5)  // 実引数の値は5
print("\(b)")       // 5 を表示

上記のコメントで書かれている通り、返り値を返す関数では必ず "return"で値を返してください。 しかし、関数本体が"return"だけの場合、"return"を省略して式だけ記述することができます。

func messageA() -> string {
    return "テストテスト"
}

func messageB() -> String { "テストテスト" } // return 無し関数


引数ラベルについて

関数定義で使われる引数のラベリングは、出来るだけ分かりやすい名前にした方が、可読性が上がります。

func buy(product:Int, price:Int, quantity:Int){
    print("Product:\(product), amount = \(price * quantity)")
}

// 関数の呼び出し
buy(product:2000, price:200, quantity:1) 
// buy(2000, 200, 1) よりも分かりやすいですよね


引数ラベルの省略

関数定義を記述する際に、例えば長い名前をつけたくない場合があります。 そう言った場合には、引数のラベリングを "_" で省略することができます。

func area( _ h:Double,  _ w:Double) -> Double {
     return h * w
}

let a = area(10.0, 5.0) // ここで引数のラベルを書く必要はありません。


"_" の特殊な使われ方

この "_" は識別子の一部として使うこともできますが、ワイルドカードとしても使うことができます。

_ = myGreatProcess(10, 20) // 関数の呼び出して得られた結果の無視をする

for _ in 1 ... 10 {
    // 繰り返しの処理(10回繰り返される)
}

考察

基本的な関数定義をここでは記載されていました。しかし、関数の引数に対するラベル付けは私のエンジニア生活で初めて出てきたものでした。(なんせ、対話式言語やJavaしかしてこなかったのでw) これがあると値の意味付けとしてすごく読みやすいと感じました。
また、

  • Swiftでは同じ名前の関数を複数個定義することが可能

  • 異なる引数ラベルをもつ関数はそれぞれ別のものとして扱うこともできます。(「オーバーロード」で解説)
    そのため、

  • 引数ラベルは引数の意味付けと同時に関数の違いを表す手段となっている
    そうです。
    いや〜勉強になるわ。

では今回は以上!

詳解 Swift 第5版

詳解 Swift 第5版

詳解Swift 第5版 第1章まとめ -データ型と変数-


こんにちは、マっさんです!

この記事は筆者に必要な部分を切り出し、まとめたものです。
詳しい内容を知りたい方は、ご購入をおすすめします。
詳解 Swift 第5版

1.1 データ型の変数

Swiftのデータ型はクラスから作られた実態他、整数、構造体などのデータ型を含めて型の実態を全て ”インスタンス”と呼ぶ。

Swiftの型には値型(value type)と参照型(reference type)がある

大文字開始のキャメルケース:
 型名、クラス名(example : Int, AnyObject, CustomStringConvertible)
小文字開始のキャメルケース:
 メソッド名、変数名(example : message, totalCount, nextPartialResult)

コンパイル方法
 $swiftc -o brain Rand.swift Analyzer.swift

考察

第一章に関しては、基礎的な内容でした。
もし基礎的なことが分からなければ、以下の本がおすすめです。
絶対に挫折しないiPhoneアプリ開発「超」入門 第7版 【Xcode 10 & iOS 12】 完全対応 (Informatics&IDEA)

私も初めてiOSアプリを学んだ際に使用しました。基礎的な文法の書き方から、サンプルアプリまで総合的に載っているのでおすすめです。

では今回は以上!!

【Swift】Stringで取得したHTMLやJavaScriptをWebViewに表示させる方法


こんにちは。マっさんです。
タイトル通り、HTMLやJavaScriptのソースコードの文字列をWebViewに表示させる方法を書きます。 またこの方法はWebViewだけではなく、WebKit Viewでも動作します。

今回は以下の様な Twitter の画面を表示させる事をゴールとします。

以下がソースコードとなっています。

import UIKit
import WebKit

class ViewController: UIViewController, UIWebViewDelegate {
     // StoryBoard で接続されている事
    @IBOutlet weak var webView: UIWebView!

    let htmlTwitterString = """
    <blockquote class="twitter-tweet tw-align-center"><p lang="en" dir="ltr"><a href="https://twitter.com/hashtag/Turkey?src=hash&amp;ref_src=twsrc%5Etfw">#Turkey</a> hints at pulling access to <a href="https://twitter.com/hashtag/Incirlik?src=hash&amp;ref_src=twsrc%5Etfw">#Incirlik</a> ABand if US acts over <a href="https://twitter.com/hashtag/Russian?src=hash&amp;ref_src=twsrc%5Etfw">#Russian</a> weapons purchase <a href="https://t.co/tp7Oa5w0zO">https://t.co/tp7Oa5w0zO</a></p>&mdash; Michael Abrams (@stripes_photog) <a href="https://twitter.com/stripes_photog/status/1153671797843398657?ref_src=twsrc%5Etfw">July 23, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script><br/>
"""

    override func viewDidLoad() {

        super.viewDidLoad()

        // htmlTwitterString変数を渡す
        webView.loadHTMLString(htmlTwitterString, baseURL: nil)

    }

}

このloadHTMLStringメソッドにHTMLのCode、もしくはURLを引数として渡すと、UIWebViewに表示させることができます。

・補足

もし、Twitterでタイムラインを取得したい場合は、以下のリンクへ飛んでください。

What would you like to embed?
https://publish.twitter.com

そして以下の様に、埋め込みたいタイムラインのURLを貼り、画面を進むと・・・ f:id:MasayaStripes:20191115152344p:plain
f:id:MasayaStripes:20191115152509p:plain

上記の写真の様に埋め込み様のCodeを取得する事ができます。 取得したURLをHTMLに記載したら、指定したタイムラインを埋め込むことができます。

以上です!今日はこの辺で!

自己紹介

初めまして、マっさんと申します。

 コツコツと?このブログをやっております。

 経歴(社会人経験6年目)

  • 長崎県出身
  • とある国立大学 情報工学部 バイオインフォマティック系学科 入学
  • 情報工学の基礎、生物学の基礎を学ぶ
  • テニスや麻雀、ダーツ、バイトに明け暮れる
  • 同大学 卒業
  • 同大学 大学院 入学
  • 1年間休学中にワーキングホリデーでカナダへ 渡加
  • ボランティアやインターンシップを通じて、英語力を身に付ける
  • 帰国後、学会発表、修士論文を執筆
  • 同大学 大学院 情報科学専攻 大学院 卒業
  • 独立系SIer企業に新卒入社
  • バックエンド向け(バッチの開発等)のプログラミングスキルの基礎を身に付ける
  • 今後の社会情勢と年齢を考えると、この時期に外資に転職をすべきだと判断
  • 3年と10ヶ月就業後、幸運な事にとある外資系企業に転職する
  • IT Developer としてスマホ向けアプリの開発・運用・保守を担当
  • Firebase のアプリへの適用や、他社のSubscription サービスをアプリで適用するなど、新しい技術に触れ悪戦苦闘中
  • アプリリニューアルに伴い、Flutterで開発するかという流れになり、Flutterを勉強中

使えるもの

  • 言語系:Java、Perl、ShellScript、MySQL、Swift、Dart
  • 環境系:RedHat、Ubuntu、Apatch、Firebase
  • MS系:Microsoft Office 全般
  • VC系:GitHub、SVN
  • 英語系:ビジネスレベル英語(英検準1級レベル)

やりたいこと・達成したいこと

  • 個人アプリ開発(Swift, Kotlin, Flutter)
  • 副業でのアプリ開発
  • 読書
  • 英語力の向上

以上です。

 

新しい言語や技術へのキャッチアップは可能です。(時間はいりますが…)

簡単なお仕事でも良いので、副業案件待ってます!