オプショナル型のアンラップについて Swift4

オプショナル型=変数にnilの代入を許すデータ型
宣言方法:変数のデータ型の最後に”?”か”!”をつける

var name: String?
var age: Int!

※オプショナル型の変数は宣言をしただけで初期化をしなかった場合、nilが入っている

暗黙的アンラップ型”!” =使用する際に自動でアンラップされる
オプショナル型の宣言には”?”か”!”を用いますが、”!”を用いて宣言したオプショナル型(暗黙的アンラップ型)は下記のように使用する際に自動でアンラップされます。

"?"で宣言したオプショナル型の場合、非オプショナル型とは計算できない
var x: Int  = 5 // 非オプショナル型
var y: Int? = 10 // "?"で宣言したオプショナル型
x + y
# => エラー

"!"で宣言したオプショナル型の場合、自動でアンラップされるため非オプショナル型と計算できる
var x: Int  = 5 // 非オプショナル型
var y: Int! = 10 // "!"で宣言したオプショナル型(暗黙的アンラップ型)
x + y
# => 15

暗黙的アンラップ型は、

最初はnilで宣言⇒使用時には絶対に値が入っている(nilではない)

という使い方の際に使用します。
そのため、使用するときに変数の値がnilのときにはエラーとなりますので要注意です。

 

アンラップ=オプショナル型から値を取りだす

アンラップの方法は下記3通り

1. Forced Unwrapping (強制的アンラップ)
オプショナル型を強制的にアンラップする方法で、
オプショナル型の後ろに”!”をつける

2. Optional Binding (オプショナルバインディング)
オプショナル型の変数に値が入ってる⇒アンラップ⇒処理{}を実行
オプショナル型の変数に値がない(=nil)⇒処理{}を行わない、もしくはelse{}の処理を実行

var test: String? // オプショナル型

if let testUnwrapped = test {
println(testUnwrapped)
}
else {
println("テストはありません")
}

if let 変数2 = 変数1{} はSwiftでよく使われるnilチェックの方法
if let hogehoge = hogehogeValue {
//nilでない場合実行される処理
}

※他にもあるエラーハンドリング
if let 変数2 = try? 変数1 {}
try?はエラーが発生するとnilを返すオプショナル型変数、この組み合わせでエラーにならないようにしています

3. Optional Chaining(オプショナルチェイニング)
オプショナル型の変数に続けてプロパティを取得したり、メソッドを呼び出す場合に使用する、戻り値はオプショナル型になる
戻り値がオプショナル型となるため、オプショナル型の変数の中身がnilの可能性があってもプロパティを取得したり、メソッドを呼び出せる。

使用方法:オプショナル型の変数のあとに”?”をつける
オプショナル型の変数?.プロパティ
オプショナル型の変数?.メソッド()

【例1】

var animal1: Animal? = Animal()
var animal2: Animal?

// nilでないためプロパティが取得できる
animal1?.type
// => "Optional(ねこ)"

// nilでないためメソッドを呼び出せる
animal2?.call()
// => "Optional(わんわん)"
var animal1: Animal? = Animal()
var animal2: Animal?

// animal1がnilの場合、nilが返る
animal1?.type
// => nil

// animal2がnilの場合、nilが返る
animal2?.call()
// => nil

【例2】

var x: String?
Var y = x?.uppercased()
// => nil

 

メソッドのラベル 名前付き引数 Swift4

ラベル:名前付き引数

メソッドの呼び出し側で、引数をよりわかりやすくするためにラベルを使います。

例えば、引数名が”ct” だったとして、意味するものが国だったとしたら、ラベルに”country”をつけるとメソッドの呼び出し側でコード書く際に分かりやすい、という感じです。

// 総重量:数量×重さ
func calcSum(quantity qt: Int, weight wt: Int) -> Int {
    return qt * wt //メソッド内では引数名を使う
}

//メソッドを呼び出す際は第一引数にquantity、第二引数にweightとして呼び出す
calcSum(quantity: 20, weight: 100)

引数の前に”_”(アンダースコア)を付けてラベルを省略する場合もある

String(describing: Subject) について Swift4

Swift3 ⇒ Swift4 で同じプログラムでもprint()にオプショナル型を放り込むと下記エラーが出るようになったみたい、swift3では自動解釈してくれていたような。。←未確認

expression implicitly coerced from ‘string ‘ to any

これはアンラップすればだいたいが解決する

アンラップはデータ型の最後に「!」をつける ⇒  (String!)

 

次にStringのinit(describing instance: Subject)について

string interpolation produces a debug description for an optional value

これはStringのイニシャライザについてのエラー

String(describing:)と書き直せば解消する。ちなみに意味は
String(describing:)にインスタンスを渡すことで、そのインスタンスの情報を文字列で取得することができる
というもの。

これもprint文にオプショナル型で入れてしまった際によくでるエラー

Swift3⇒Swift4で@objc推論が廃止

Swift3⇒Swift4で@objc推論が廃止になり、

Objective-CのクラスとかをSwiftで扱う時には、メソッドの頭に「@objc」と明示しなくてはいけなくなりました。

#selectorを使用した例

timer = Timer.scheduledTimer(timeInterval: 1.0,
                target: self,
                selector: #selector(self.timeInterrupt(_:)),
                userInfo: nil,
                repeats: true)

@objc func timerInterrupt(_ timer:Timer) {
    ・・・・・・・
}

 

 

Swift3.0からは今までのようなfor文が使えない

Swift3.0から今まで使用していたC言語スタイルのfor文が使えません。

なかなか大きな変更で衝撃を受けたのでメモ

例.

【従来のfor文】
for (var i = 0; i < 10; i++) {
print("現在\(i + 1)回目の繰り返し!")
}

↓これが下記のようなスタイルで書くようになりました

【for-inを使用】
for i in 0..<10 {            //範囲の表記方法は0...9 でもOK
    print("現在\(i + 1)回目の繰り返し!")
}
【forEachを使用】
Array(0..<10).forEach {
    print("現在\($0 + 1)回目の繰り返し!")
}

ちなみにfor-in文の文法は下記

for 変数 in 範囲演算 {
    繰り返しを記述したステートメント
}

i++のようなインクリメントの書き方ができなくなっているので

while文などでインクリメントを書く際には下記のように書く

i+=1

i=i+1

i–のようなデクリメントについては

i-=1

i=i-1

 

ここまで全部Swift version4.0.3で確認済み

rbenv(Rubyのバージョン管理),Ruby2.3.6のインストール libcurlのアップデート CentOS 6.7(Final) 32bit

CentOSにrbenvをインストールした際に実行ユーザーでないと
「コマンドが見つかりません」
となったので、全ユーザーで使えるようにした手順を、
Rubyをrbenvを使ってインストールする最初のところから書いてみました。
まず、

①Ruby をビルドする環境を構築

# yum install -y gcc bzip2 openssl-devel libyaml-devel libffi-devel readline-devel zlib-devel gdbm-devel ncurses-devel

②rbenv + ruby-build のインストール
rbenv で Ruby のインストールを行うので rbenv のプラグイン「 ruby-build 」を併せてインストールする。

# git clone git://github.com/sstephenson/rbenv.git ~/.rbenv
# git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
# echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
# echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
# source ~/.bash_profile
# rbenv --version
rbenv 1.1.1-28-gb943955

③Ruby のインストール
「 rbenv install 」コマンドを用いて Ruby をインストールする。
「 –list 」オプション指定で、インストール可能な Ruby のバージョンがリスト表示される。

# rbenv install –list
# rbenv install 2.3.0

ここまでの方法だと、実行ユーザーでないと下記のように「コマンドがありません」になります。

[root@localhost ~]# rbenv -v
-bash: rbenv: コマンドが見つかりません

この原因は ~/.bash_profile に書込んでいるからで、PATHが通っていないから。
実際にどこのRubyが呼ばれているかを確認すると、
# which ruby
/usr/bin/ruby
となっていて、rbenvのrubyを使う時の
/Users/ユーザ名/.rbenv/shims/ruby

CentOSでは全ユーザーに/etc/profile.d/が読み込まれるので、
/etc/profile.d/以下にrbenvをインストールして、設定も書込むようにすれば解決する。

# sudo su -
# git clone git://github.com/sstephenson/rbenv.git /usr/local/src/rbenv
# git clone git://github.com/sstephenson/ruby-build.git /usr/local/src/rbenv/plugins/ruby-build
# echo 'export RBENV_ROOT="/usr/local/src/rbenv"' >> /etc/profile.d/rbenv.sh
# echo 'export PATH="${RBENV_ROOT}/bin:${PATH}"' >> /etc/profile.d/rbenv.sh
# echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh
# source /etc/profile.d/rbenv.sh
# rbenv -v
rbenv 1.1.1-28-gb943955

 

インストールできるリストを表示してみる
# rbenv install -l

その中にあるバージョンを選んでインストールする
# rbenv install -v 2.3.6

 

がしかし、CentOS6.7だと思わぬトラブルがさらに発生する
libcurlのバージョンが古すぎてダウンロードエラーを起こすのだ。

sudo rpm -Uvh http://www.city-fan.org/ftp/contrib/yum-repo/city-fan.org-release-1-13.rhel6.noarch.rpm

デフォルトでenabled=1になっているので0にしておきましょう。

$ sudo vi /etc/yum.repos.d/city-fan.org.repo

[city-fan.org]
name=city-fan.org repository for Red Hat Enterprise Linux (and clones) $releasever ($basearch)
#baseurl=http://mirror.city-fan.org/ftp/contrib/yum-repo/rhel$releasever/$basearch
mirrorlist=http://mirror.city-fan.org/ftp/contrib/yum-repo/mirrorlist-rhel$releasever
#enabled=1
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-city-fan.org

 

–enablerepo=city-fan.org,epel をつけてlibcurlをアップデートします。
※依存関係でlibnghttp2.so.14不足が出るのを防ぐために
epel
も追加して、いざアップデート。

[root@localhost ~]$ sudo yum update –enablerepo=city-fan.org,epel libcurl

完了

バージョン確認すると
$yum info libcurl

i686
バージョン:7.57.0
になっていたので、アップデート成功

中断していたrbenvでRubyインストール
# rbenv install -v 2.3.6
けっこう時間かかりますがインストール終了

再読み込み⇒
$ rbenv rehash

インストールされているrubyを確認⇒
$ rbenv versions
system *2.3.6 (set by /usr/local/src/rbenv/version)

先ほどインストールしたRubyに設定⇒
$ rbenv global 2.3.6

Rubyインストールされたかを確認⇒
$ ruby -v
ruby 2.3.6p384 (2017-12-14 revision 61254) [i686-linux]

CentOS6.7でRailsにMysqlを導入するとき

【開発環境】
CentOS 6.7 (Final)
Ruby 2.3.0
Rails 4.2.6
MySQL 5.6.29

RailsデフォルトのSqlite3ではなくMySQL使いたい場合、

$ rails new 名前 –skip-bundle -d mysql

Gemfileを見てみる。

$ cd 名前
$ vi Gemfile

デフォルトだとsqliteになっている箇所が、mysqlに変更されています。

ついでに、下記のコメントを外します。
# gem ‘therubyracer’

gem ‘therubyracer’
(※javascriptのruntime不足エラー防止)

保存して、
$ bundle install

$ rake db:create
で、エラーが出て、かつ

$ gem install mysql2 -v 0.4.4
してもエラーが出る場合

$ yum install mysql-devel

$ gem install mysql2
ここまで順調に進めばOKで、DB作成してみてください
rake db:create

DB作成できれば成功です。

CentOS6.7 しかも32bit(i686)版へのEPEL、Remi、RPMforgeリポジトリインストール

EPEL、Remi、RPMforgeとは、サードパーティ製の中でメジャーなリポジトリです。
CentOS標準リポジトリで提供されていないパッケージ、例えばPHP, MySQLなどの最新版をインストールできたりします。

ただ、安定していないバージョンを最新版としてインストールしてしまいハマることもあるので、これは安心の安定版だなというときに利用するのがいいかも。

ネット上では64bit版(x86_64)情報が主流なので、あえて32bit版について。

まず、現在インストールしているリポジトリの確認
# rpm -qa | grep epel
# rpm -qa | grep remi
もし、既にインストールしている古いリポジトリあれば、epelはremiに依存しているので、remiから削除
# rpm -e remi-release-5-8.el5.remi.noarch
# rpm -e epel-release-5-4.noarch
# rpm -e rpmforge-release-0.5.5-2.el5.rf.i386

【EPELリポジトリインストール】
# rpm –import http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEYY-EPEL-6
# rpm -ivh http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm

【Remiリポジトリインストール】
# rpm –import http://rpms.famillecollet.com/RPM-GPG-KEY-remi
# rpm -ivh http://rpms.famillecollet.com/enterprise/6/remi/i386/remi-release-6.6-2.el6.remi.noarch.rpm

【RPMforgeリポジトリインストール】
# rpm –import http://apt.sw.be/RPM-GPG-KEY.dag.txt
# rpm -ivh http://apt.sw.be/redhat/el6/en/i386/rpmforge/RPMS/rpmforge-release-0.5.3-1.el6.rf.i686.rpm

リポジトリのデフォルト無効(enabled=0)に修正する
vi /etc/yum.repos.d/remi.repo ←remiは最初からenabled=0になってるので、特に何も変更しなくてOK
vi /etc/yum.repos.d/epel.repo
vi /etc/yum.repos.d/rpmforge.repo

完了。

試にPHPの最新情報調べてみる場合は下記という感じ
# yum –enablerepo=epel,remi,rpmforge info php

目当ての更新インストールなど終わったら、上記の3個のリポジトリをenabled=1に戻しておけば、
標準リポジトリ以外でのyum更新してしまうミスが防げるのでお勧め

CentOS 6.7 でのvsftpd設定 とFFFTPクライアントの設定

サーバー管理にSSHを利用する方が多いので、
ファイル転送にはSCP、もしくはHTTPといったところでしょうか。

一昔前はファイル転送にはFTPがメジャーでしたが、
HTTP、SCPに押され使用頻度が落ちているかな?と感じます。

ですが、SCPは暗号化を行うため、暗号化を行わないFTPと比べると
転送速度は半分以下(4分の1程度のことも)になることがほとんどです。

なので、特に暗号化の必要のない多くのデータを一度に転送する際には、まだまだFTPは使えます。

ということで、、下記の要件を仮定して、CentOS6.7で、FTPサーバー(vsftpd)を立ててみます。

■ 外部からのアクセスを許可しない社内サーバーでの運用(LANのみ)
■ アクティブモード接続(20番、21番ポート開放のみでOK)
※パッシブモード(PASVモード)の場合にはTCP 1024以上でけっこう広いレンジのファイアウォールを開放する必要があります

# rpm -q vsftpd <-- vsftpdがインストールされているか調べる
# パッケージvsftpdはインストールされていません

vsftpdが入っていなかったので入れます。

# yum -y install vsftpd  <-- vsftpdのインストール

# netstat -antu  <-- ポート確認
# iptables -vnL でもOK)

20,21番ポートが空いていない場合には次のようにiptablesに追加

# vi /etc/sysconfig/iptables
-A INPUT -m state –state NEW -m tcp -p tcp –dport 20 -j ACCEPT
-A INPUT -m state –state NEW -m tcp -p tcp –dport 21 -j ACCEPT
(viエディタは”i”押せば書きこめるようになって、記録して終わるときは”ESC”で抜けてから “:wq” ですよ!)

vsftpdの設定ファイルに以下のように設定をします。

# vi /etc/vsftpd/vsftpd.conf

vsftpd.conf内の設定変更したとこだけ抜粋
anonymous_enable=NO <--匿名ログイン禁止(デフォルトはYES)

ascii_upload_enable=YES <--コメント削除して有効にする ( アスキーモードでのアップロードを許可 )
ascii_download_enable=YES <--コメント削除して有効にする(アスキーモードでのダウンロードを許可)

ftpd_banner=Welcome to blah FTP service. <--コメント削除して有効にする。別にしなくてもOK(FTPログイン時にソフト名とバージョンが表示されないようになる)

chroot_local_user=YES <--コメント削除して有効にする ( chroot有効 )。デフォルトでホームディレクトリより上層へのアクセスを禁止
chroot_list_enable=YES <--コメント削除して有効にする。ホームディレクトリより上層へのアクセスを許可するユーザリストの有効化
chroot_list_file=/etc/vsftpd/chroot_list <--コメント削除して有効にする ( chroot リストファイル指定 )
※管理者や、自身のホームディレクトリ以外へアクセスできるようにしておく必要があるユーザのみ登録することを推奨。管理者はSCPでいいやというような場合は特に有効にしなくてOK。もしくはchroot_listを作成時に何も書き込まない。ちなみにchrootを有効にした場合にはchroot_listファイルがないとエラーになるので、作成を忘れないように。

ls_recurse_enable=YES <--コメント削除して有効にする ( ディレクトリごと一括での転送有効 )

最終行へ下記の4行を追記
userlist_deny=NO
userlist_file=/etc/vsftpd/user_list
local_root=public_html <--ルートディレクトリ指定 (指定しない場合はホームディレクトリがルートディレクトリとなる)
use_localtime=YES <--ローカルタイムを使う
※userlist_enable=YES、userlist_deny=NOで/etc/vsftpd/user_list がFTPログインできるユーザーのリスト(ホワイトリスト)となります。
userlist_deny=YES もしくは削除で、/etc/vsftpd/user_list がFTPログイン禁止ユーザーのリスト(ブラックリスト)となります。

vsftpdの設定ファイルの修正はこれで終わり。

user_listにFTPログインを許可するユーザー名を書き込む
# vi /etc/vsftpd/user_list
hogehoge

FTPログインのルールはftpusersにも指定されていて、
/etc/vsftpd/ftpusers
に記されたユーザーはFTPログインできません。これは上記のホワイトリスト設定を行っても有効です。

# chkconfig vsftpd on  <-- 次回のブート時からは自動起動の設定
# service vsftpd start  <-- vsftpdを起動

ここで、FTPクライアントからアクセスすると、
500 OOPS: cannot change directory:/home/hogehoge
500 OOPS: priv_sock_get_cmd
となり、接続できないと思うので、さらに下記1か2のどちらかを行えばOK.

1. SELinuxの停止
# getenforce <-- SELinuxが動いているかの確認
Enforcing <-- 動いている。動いていない場合はDiabledと出る

# vi /etc/sysconfig/selinux
SELINUX=enforcing
SELINUX=disabled
と変更する。

# reboot <--OS再起動

2. SELinuxの設定を変更する
/usr/sbin/getsebool -a | grep ftp
で確認する。
ftp_home_dir –> off
になっていれば、これをONに変えるために
# /usr/sbin/setsebool -P ftp_home_dir 1 ←(けっこう時間かかる)

終了したら、念のために
# /usr/sbin/getsebool -a | grep ftp
ftp_home_dir –> on になっていればOK

今回ユーザーアカウントのhomeに設定したpublic_htmlディレクトリどうやって作るの?って人に
$ cd /home/hogehoge
$ mkdir public_html
$ cd public_html
$ echo ‘TEST FILE’ > index.html index.html <-- 試しにファイル作ってみただけで、ネット公開しないので別に必要ないです。

ここまでで、CentOS側への設定は完了です。

FFFTPソフトでアクセスする際の設定を一応書いておきます。
①[設定変更]→[文字コード]→[ファイル名の漢字コード]を「UTF-8N」へ変更
②[設定変更]→[拡張]→「PASVモードを使う」のチェックを外す

vsftpdをちゃんと設定したはずなのに、FTPクライアントで接続できないときは、
chroot_list,user_listが存在するか、設定ファイルに書き込んだパスなどにスペルミスがないかチェックしてみましょう。

windowsのmcd(コマンドプロンプト)でftp接続して、問題を発見できたりもします。

C:\Users\ユーザー名>ftp 192.168.**.***  ←サーバーのIPアドレス指定する
192.168.**.*** に接続しました。
500 OOPS: cannot read user list file:/etc/vsftpd/userlist
500 OOPS: priv_sock_get_cmd
接続がリモート ホストによって閉じられました。

これは、userlist⇒user_listのスペルミスということがわかります。
なので、
# vi /etc/vsftpd/vsftpd.conf
で該当箇所のスペルを修正すればOK

C:\Users\ユーザー名>ftp 192.168.**.***
192.168.**.*** に接続しました。
220 Welcome to blah FTP service.
ユーザー (192.168.**.***:(none)):hogehoge
331 Please specify the password.
パスワード:****
Login successful.
↑これでユーザー名:hogehogeでFTP接続ができたことを確認できました。
ログインできなかったら、user_listにユーザーアカウントを記載していない可能性があります。チェックしてみましょう。