2019年12月26日 星期四

Ubuntu 18.04 apache2+mysql+php-fpm

hdd
/                16G
/var/www   60G
/Mysql       40G

sudo apt update
sudo apt upgrade

sudo apt install htop iotop iftop mytop
sudo apt install samba

sudo vim /etc/samba/smb.conf
[TMP]
        path = /tmp
        read only = no
        guest ok = yes
sudo service smbd restart

sudo tzselect
sudo cp /usr/share/zoneinfo/Asia/Taipei  /etc/localtime

sudo apt install mysql-server
sudo mysql_secure_installation

In Ubuntu systems running MySQL 5.7 (and later versions), the root MySQL user is set to authenticate using the auth_socket plugin by default rather than with a password.

sudo mysql -u root -p
mysql> SELECT user,authentication_string,plugin,host FROM mysql.user;

mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

mysql> FLUSH PRIVILEGES;

mysql> SELECT user,authentication_string,plugin,host FROM mysql.user;

新增使用者
mysql>create user 'demo'@'%' identified by '1qaz2wsx';
mysql>grant all privileges on *.* to 'demo'@'%' with grant option;

sudo apt install apache2 libapache2-mod-fcgid
sudo apt install php7.2-fpm
sudo a2enmod proxy_fcgi
sudo a2enconf php7.2-fpm
sudo apt install phpmyadmin
編輯apache 站台定檔,在
<VirtualHost *:80>
.........
</VirtualHost>
內加上以下這段
<FilesMatch \.php$>
        SetHandler "proxy:unix:/var/run/php/php7.2-fpm.sock|fcgi://localhost"
</FilesMatch>
存檔離開後重新啟動apache2
sudo service apache2 restart

php-fpm開機自動啟動
systemctl enable php7.2-fpm

2019年12月20日 星期五

Ubuntu 18.04 禁用ipv6

修改/etc/default/grub
將內容

GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX=""
修改為

GRUB_CMDLINE_LINUX_DEFAULT="ipv6.disable=1"
GRUB_CMDLINE_LINUX="ipv6.disable=1"
存檔離開後,執行以下指令套用

sudo update-grub
接著重新啟動系統即可!

================
禁用ipv6後,與dovecot的預設設定值會衝突(預設會啟動)ipv6,造成dovecot無法啟動!需修改/etc/dovecot/dovecot.conf,修改
listen = *, ::
改成
listen = *

存檔離開後重新啟動dovecot即可!

2019年10月7日 星期一

Nginx Reverse Proxy 自訂error頁面

在設定檔的httpserver或location中設定
proxy_intercept_errors on;
說明:Determines whether proxied responses with codes greater than or equal to 300 should be passed to a client or be intercepted and redirected to nginx for processing with the error_page directive.

接著在需要處理的server段落內,加上要自訂的錯誤碼
error_page 500 502 503 504 /50x.html;
說明:Defines the URI that will be shown for the specified errors. A uri value can contain variables.
如果需要,可以指定自訂的錯誤頁面位置
location /50x.html {
                root /var/www/html;
                }
存檔後,重新啟動nginx即可!

2019年10月4日 星期五

nginx 禁止使用ip連結網站

方法一:
在server區段內新增如下
server_name  www.demo.com.tw
if ($host != 'www.demo.com.tw'){
   return 403;
}


方法二:
新增一個server的區段
server {
  listen 80 default;
  server_name _;
  return 403;
}

並在其於server區段(如果有多台虛擬機設定)都加入網域名稱,比如:
server_nam www.demo.com.tw;

2019年9月4日 星期三

Roundcube SMTP Error (250): Authentication failed.

修改 config.inc.php內容如下:

$config['smtp_auth_type'] = 'LOGIN';
$config['smtp_user'] = '';
$config['smtp_pass'] = '';

2019年8月2日 星期五

新增vpn連線並允許其他使用者使用

用系統管理員身份執行power shell,並輸入以下指令:
Add-VpnConnection -Name MY_VPN_NAME -ServerAddress MY_VPN_SERVER -AllUserConnection $true -SplitTunneling $true -AuthenticationMethod MSChapv2 -TunnelType Automatic -EncryptionLevel Required -PassThru

2019年7月10日 星期三

Class Inheritance and Initialization

指定初始化
designated initializer:一個class至少一個
語法:
init(parameters){

}
便利初始化
convenience initializer:可有可無
語法:
convenience init(parameters){

}

import UIKit

class Vehicle {
    var numberOfWheels = 0;
    var description: String {
        return "\(numberOfWheels) wheel(s)";
    }
}
let vehicle = Vehicle();
print(vehicle.description);

class Bicycle:Vehicle{
    override init(){
        super.init();
        numberOfWheels = 2;
    }
}
let bicycle = Bicycle();
print("Bicycle:\(bicycle.description)");

class Hoverboard:Vehicle{
    var color:String;
    init(color:String) {
        self.color = color;
        super.init();
    }
    override var description: String{
        return "\(super.description) in a beautiful \(color)";
    }
}
let hoverboard = Hoverboard(color: "silver");
print("Hoverboard:\(hoverboard.description)");

//自動繼承
class Food{
    var name:String;
    init(name:String) {
        self.name = name;
    }
    convenience init(){
        self.init(name:"[noName]");
    }
}
let nameMeat = Food(name: "Bacon");
let mysteryMeat = Food();
class RecipeIngredient:Food{
    var quantity:Int;
    init(name:String, quantity:Int){
        self.quantity = quantity;
        super.init(name: name);
    }
    override convenience init(name: String) {
        self.init(name:name, quantity:1);
    }
}
let oneMySteryItem = RecipeIngredient();
let oneBacon = RecipeIngredient(name: "Bancon");

let sixEggs = RecipeIngredient(name: "Eggs", quantity: 6);

2019年7月3日 星期三

Initialization


import UIKit

//structure 有default init和memberwise init
/*
 struct Faherenheit{
 var temperature:Double
 init(){
 temperature = 32.0
 }

 }
 */
struct Faherenheit{
    var temperature = 32.0;
}

var f = Faherenheit();
f.temperature;


struct Celsius{
    var temperatureInCelsius:Double;
    init(fromFahrenheit fahrenheit:Double){
        temperatureInCelsius = (fahrenheit - 32.0) / 1.8
    }
    
    init(fromKelvin kelvin:Double){
        temperatureInCelsius = kelvin - 273.15;
    }
    
    //使用取消引數名稱的定義
    init(_ celsius:Double){
        temperatureInCelsius = celsius;
    }
}

let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
print(boilingPointOfWater.temperatureInCelsius);

let freezingPointOfWater = Celsius(fromKelvin: 273.15)
print(freezingPointOfWater.temperatureInCelsius);

struct Color{
    let red, green, blue:Double;
    init(red:Double, green:Double, blue:Double){
        self.red = red
        self.green = green
        self.blue = blue
    }
    
    init(white:Double){
        red = white
        green = white
        blue = white
    }
}
let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)
let halfGraf = Color(white: 0.5)

//let veryGreen = Color(0.0, 1.0, 0.0)
let bodyTemperature = Celsius(37.0)

class SurveyQuestion{
    let text:String
    var response:String?
    init(text:String){
        self.text = text;
    }
    
    func ask(){
        print(text)
    }
}

let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")
cheeseQuestion.response = "Yes, I do like cheese."

//default Initializers
class ShoppingListItem{
    var name:String?
    var quantity = 1
    var purchased = false
}

var item = ShoppingListItem();

//struct
struct Size{
    var width = 0.0, height = 0.0
}
//memberwise init
let twoByTwo = Size(width: 2.0, height: 2.0)

struct Point{
    var x = 0.0, y = 0.0
}

struct Rect{
    var origin = Point();
    var size = Size();
    //呼叫default的init
    init(){
    }
    //自訂的init
    init(origin:Point, size:Size){
        self.origin = origin
        self.size = size
    }
    
    init(center:Point, size:Size){
        let originX = center.x - (size.width/2)
        let originY = center.y - (size.height/2)
        self.init(origin: Point.init(x: originX, y: originY), size: size)
    }
}

//let basicRect = Rect(origin: Point.init(x: 2.0, y: 2.0), size: Size.init(width: 5.0, height: 5.0))
let originRect = Rect(center: Point.init(x: 2.0, y: 2.0), size: Size.init(width: 5.0, height: 5.0))
originRect.origin.x
originRect.origin.y
originRect.size.width
originRect.size.height

centos 變更 HDD uuid

查看hdd uuid
ls -al /dev/disk/by-id

改變 UUID
tune2fs -U XXXXXXXXXX /dev/sda1

亂數產生 UUID
tune2fs -U random /dev/sda1

使用當下時間作 UUID
tune2fs -U time /dev/sda1

清除 UUID
tune2fs -U clear /dev/sda1



2019年6月26日 星期三

inheritance


import UIKit

class Vehicle {
    var currentSpeed = 0.0;
    //每呼叫一次就會被執行一次
    var description:String {
        return "現在的速度是每小時\(currentSpeed)";
    }
    func makeNoice() {
        //發出聲音
        
    }
}
//Bicycle 繼承 Vehicle
class Bicycle:Vehicle{
    var hasBasket = false;
}

let someVehicle = Vehicle();
let bicycle = Bicycle();
bicycle.currentSpeed = 15.0;
print("Bicycle:\(bicycle.description)");

class Tandem:Bicycle {
    var currentNumberOfPassengers = 0;
}
let tandem = Tandem();
tandem.hasBasket = true;
tandem.currentNumberOfPassengers = 2;
tandem.currentSpeed = 22.0;
//override
//Train 繼承 Vehicle,override method
class Train:Vehicle {
    override func makeNoice() {
        print("Choo Choo");
    }
}
let train = Train();
train.makeNoice();
//Car 繼承 Vehicle,override computed property
class Car:Vehicle{
    var gear = 1;
    override var description: String {
//        return "現在的速度是每小時\(currentSpeed)公里," + "目前是\(gear)檔";
        return super.description + ",目前是\(gear)檔";
    }
}
let car = Car();
car.currentSpeed = 25.0;
car.gear = 3;
print("Car:\(car.description)");
//override property with observer
class AutomaticCar:Car {
    override var currentSpeed: Double{
        didSet{
            gear = Int(currentSpeed / 10.0) + 1
        }
    }
}
let automatic = AutomaticCar();
automatic.currentSpeed = 35.0;
print("automaticCar.\(automatic.description)");

Nginx限速

編輯站台設定檔,在Server區段內增加如下設定:
limit_rate 1024k;

重新啟動nginx

apache 限速

啟用mod_bw模組,並編輯mod_bw.conf,加入如下設定:
BandWidth    all 2621440

重新啟動apache

2019年6月23日 星期日

subscript


import UIKit
//subscript 快速存取實體的資料
/*語法:
 subscript(index:Int) -> Int{
    get{
        return Int;
    }

    set(newValue){

    }
 }

*/
struct TimesTable{
    let multiplier:Int;
    subscript(index:Int) -> Int{
        //只有get時,可以省略get語法
        return index * multiplier;
    }
}
let threeTimesTable = TimesTable(multiplier: 3);
print("6次的3是:\(threeTimesTable[6])");

var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4];
//如果沒指定的key,就是新增
numberOfLegs["bird"] = 2;

struct Matrix{
    let rows:Int, columns:Int;
    var grid:[Double];
    
    init(rows:Int, columns:Int){
        self.rows = rows;
        self.columns = columns;
        grid = Array(repeating: 0.0, count: rows * columns);
    }
    func indexIsValid(row:Int, column:Int) -> Bool{
        return row >= 0 && row < rows && column >= 0 && column < columns;
    }
    subscript(row:Int, column:Int) -> Double{
        get{
            assert(indexIsValid(row: row, column: column),"Index out of range")
            return grid[(row * columns) + column]
        }
        
        set{
            assert(indexIsValid(row: row, column: column),"Index out of range")
            grid[(row * columns) + column] = newValue
        }
    }
}
var matrix = Matrix(rows: 2, columns: 3)
matrix[1,2] = 50.0
matrix[1,1] = 40.0
matrix[0,0] = 10.0
print(matrix.grid)
//print(matrix[20,20])
print(matrix[1,2]);
print(matrix[1,1]);
print(matrix[0,0]);


2019年6月19日 星期三

method


import UIKit
//習慣上class名稱第一個字母大謝,屬性名稱第一個字母小寫
class Counter{
    var count = 0;
    //實體的method,只有實體才可以執行
    func increment(){
        count += 1;
    }
    func increment(by amount:Int){
        count += amount;
    }
    func reset(){
        count = 0;
    }
}
let counter = Counter();
counter.increment();
print(counter.count);
counter.increment(by: 5);
print(counter.count);
counter.reset();
print(counter.count);

//使用self的時機
/*
struct Point{
    var x = 0.0, y = 0.0;
    func isToTheRightOf(x:Double) -> Bool {
        return self.x > x;
    }
}
let SomePoint = Point(x: 4.0, y: 5.0);
if SomePoint.isToTheRightOf(x: 1.0) {
    print("比較大!");
}
*/
/*
struct Point{
    var x = 0.0, y = 0.0;
    //method要去改變store property的值時,必須加上mutating
   mutating func moveBy(x deltaX:Double, y deltaY:Double){
        x += deltaX
        y += deltaY
    }
}
*/
struct Point{
    var x = 0.0, y = 0.0;
    mutating func moveBy(x deltaX:Double, y deltaY:Double){
        self = Point(x: x+deltaX, y: y+deltaY);
    }
}
var somePoint = Point(x: 1.0, y: 1.0);
somePoint.moveBy(x: 2.0, y: 3.0);

enum TriStatsSwitch{
    case off, low, heigh
    mutating func next(){
        switch self {
        case .off:
            self = .low;
        case .low:
            self = .heigh;
        case .heigh:
            self = .off;
        }
    }
}
var openLight = TriStatsSwitch.low;
openLight.next();

struct levelTracker{
    static var highestUnlockedLevel = 1;
    var currentLevel = 1;
    
    static func unlock(_ level:Int){
        if level > highestUnlockedLevel {
            highestUnlockedLevel = level;
        }
    }
}

2019年6月17日 星期一

property


import UIKit

struct FixedLengthRange{
    var firstValue:Int;
    let length:Int;
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
rangeOfThreeItems.firstValue = 6;

let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4);
//需內外都是var才可變更值
//rangeOfFourItems.firstValue = 6;

//lazy store property
class DataImporter{
    var filename = "data.txt"
}
class DataManager{
    lazy var importer = DataImporter();
    var data = [String]()
}
let manager = DataManager();
manager.data.append("Some Data");
manager.data.append("Some more data");
print(manager.importer.filename);

//computed property
struct Student{
    let name:String;
    var math:Int;
    var chinese:Int;
    var english:Int;
    //computed property語法,一定要給資料類型,每呼叫一次sum,就get math + chinese + english
    var sum:Int{
        get{
            return math + chinese + english
        }
    }
    //computed property語法,一定要給資料類型,每呼叫一次average就get Double(sum) / 3.0
    var average:Double{
        get{
            return Double(sum) / 3.0
        }
    }
}
var stu1 = Student(name: "Robert", math: 78, chinese: 67, english: 90);
print("stu1 的 sum 是:\(stu1.sum)");
print("stu1 的 average 是:\(stu1.average)");

//computed property,set
struct Point{
    var _x = 0;
    var _y = 0;
    var x:Int{
        get{
            print("取出x");
            return _x;
        }
        set(newV){
            print("存入值:\(newV)");
            _x = newV;
        }
    }
    var y:Int{
        get{
            print("取出y");
            return _y;
        }
        set(newV){
            print("存入值:\(newV)");
            _y = newV;
        }
    }
}
var point1 = Point(_x: 3, _y: 5);
print("\(point1.x)");
point1.x = 10;
print("\(point1.x)");

2019年6月16日 星期日

Class And Structrue


struct SomeStructure{
    
}

class SomeClass{
    
}

struct Resolution{
    //在struct內用var定義的稱為property
    var width = 0;
    var height = 0;
}
class VideoMode{
    var resolution = Resolution();
    var interlaced = false;
    var frameRate = 0.0;
    var name:String?;
}
//default初始化Resolution,width = 0,height = 0 
let someResolution = Resolution();
print(someResolution.width);
print(someResolution.height);

let someVideoMode = VideoMode();
someVideoMode.resolution.width = 1280
someVideoMode.resolution.height

let vga = Resolution(width: 640, height: 480)
vga.width;
vga.height;

let hd = Resolution(width: 1920, height: 1080);
var cinema = hd
cinema.width = 2048
hd.width

enum CompassPoiont{
    case north, south, east, west
    mutating func turnNorth(){
        self = .north;
    }
}
var currentDirection = CompassPoiont.west
//rememberedDirection = currentDirection = west
let rememberedDirection = currentDirection
currentDirection.turnNorth();

//rememberedDirection.turnNorth()會出錯!因為rememberedDirection設定為let,值不可改!
print(currentDirection);
print(rememberedDirection);

//referenct
let tenEighty = VideoMode();
tenEighty.resolution = hd;
tenEighty.interlaced = true;
tenEighty.name = "1080i";
tenEighty.frameRate = 25.0;

let alsoTenEighty = tenEighty;
alsoTenEighty.frameRate = 30.0;
print(tenEighty.frameRate);
//識別運算子
//===
//!===
//是不是指向同一個實體
if tenEighty === alsoTenEighty {
    print("遙控同一個實體!");
}

2019年6月10日 星期一

Enumeration 列舉

enum SomeEnumeration{
    //成員
}
//定義enum
enum CompassPoint{
    case north
    case south
    case east
    case west
}
//定義enum時,指定資料類型Int,會給予成員rawValue,從0開始
enum Planet:Int{
    case mercury, venus, earth, mars, jupiter, ssturn, uranus, neptuneㄤ;
}
print(Planet.earth.rawValue)
//實作
var directionToHead:CompassPoint = CompassPoint.west
directionToHead = .east
//directionToHead = .south
//利用switch檢查
switch directionToHead {
case .north:
    print("north");
case .south:
    print("south");
case .east:
    print("east");
case .west:
    print("west");
}
//let button = UIButton(type:UIButton.ButtonType.infoLight);
let button = UIButton(type: .infoLight);
//建立可以被for in的列舉,一定要有CaseIterable,CaseIterable:可重複使用
enum Beverage:CaseIterable{
    case coffee, tea, juice
}
//allCases:Enumeration內的所有case
print(Beverage.allCases.count)
for beverage in Beverage.allCases{
    print(beverage)
}

2019年6月3日 星期一

fuction

定義function
func 自訂func名稱(參數1:資料類型, 參數2:資料類型, 參數3:資料類型) -> 傳出值資料類型{
    code
    return type
}
參數可以省略,return type也可空白!
呼叫function
let 接收物 = 自訂func名稱(引數1, 引數2, 引數3)

func greet(person:String) -> String {
    let greeting = "Hello, " + person + "!";
    return greeting
}
print(greet(person: "Anna"));
print(greet(person:"Brian"));

func greetAgain(person: String) -> String {
    return "Hello again, " + person + "!"
}

print(greetAgain(person: "Anna"));

global Function:
apple 定義,使用者只呼叫

func greet(person:String) -> String{
    let greeting = "Hello, " + person +"!";
    return greeting;
}
func greetAgain(person:String) -> String{
    return "Hello again, " + person +"!";
}
//function 沒有參數
//function 有傳出,就一定要有return!
func sayHelloWorld() -> String {
    return "Hello, World";
}
//function 有多個參數
//function名稱相同,但參數名稱不同,或參數名稱相同,但參數的數量不同,皆視為不同的function
func greet(person:String, alreadyGreeted:Bool) -> Stringh{
    if alreadyGreeted {
        return greetAgain(person: String);
    }
}
print(greet(person: "Tim", alreadyGreeted: true));

//function 沒有return值
//func greet(person:String) -> Void { },-> Void:表示沒有傳出值!
func greet(person1:String){
    print("Hello, \(person1)");
}
func printAndCount(string:String) -> Int{
    print(string);
    return string.count;
}
func printWithoutCounting(string:String){
    let _ = printAndCount(string:string);
}
printWithoutCountin(string: "Hello, World!");

//利用tuple傳出多個值
func minMax(array:[Int]) -> (min:Int,max:Int){
    var currentMin = array[0];
    var currentMax = array[0];
    for value in array[1..<array.count]{
        if value < currentMin{
            currentMin = value;
        } else if value > currentMax{
            currentMax = value;
        }
    }
    return (currentmin,currentMax);
}
let bounds = minMax(array: [8, -6, 2, 109, 3, 71]);
bounds.max
bounds.min

//optional的寫法
func minMax(array:[Int]) -> (min:Int,max:Int)?{
    if array.isEmpty {
    return nil;
    }
    var currentMin = array[0];
    var currentMax = array[0];
    for value in array[1..<array.count]{
        if value < currentMin{
            currentMin = value;
        } else if value > currentMax{
            currentMax = value;
        }
    }
    return (currentmin,currentMax);
}
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]){
    bounds.max;
    bounds.min;
}
//function的引數與參數名稱,
func someFunction(firstParameterName:Int, secondParameterName:Int){
 
}
someFunction(firstParameterName: 3, secondParameterName:2)
//自訂引數名稱 argumentLabel ,parameterName是參數名稱
func someFunction(argumentLabel parameterName:Int){
 
}

someFunction(argumentLabel: 54);

func greet(person:String, from hometown:String) -> String{
    return "Hello \(person)! Glad you could visit from \(hometown)"
}
greet(person: "Bill", form: "Cupertino");

//省略引數名稱
func someFunction(_ firstParameterName:Int, secondParamaterName:Int){

}
someFunction(5, secondParamaterName:3)

//default parameter value,有default value的參數要寫在後面!
func someFunction(parameterWithoutDefault:Int,patameterWithDefault:Int = 12){
 
}
someFunction(parameterWithoutDefault: 3, patameterWithDefault: 6)
someFunction(parameterWithoutDefault: 5)

//不限參數數量,這時引述名稱大多省略!參數內容則為陣列!
func arithmeticMean(_ numbers:Double...) -> Double{
    var total:Double = 0;
    for number in numbers{
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1,2,3,4,5,6)
arithmeticMean(1.4,6,8,4.6,7.8)

//inout parameter,參數值為常數(let),無法變更!要在function內變更已設定的參數值,需用inout!
func swapTwoInt(_ a:inout Int, _ b:inout Int){
    let temporaryA = a;
    a = b;
    b = temporaryA;
}

var someInt = 3;
var anotherInt = 107;
//inout參數的呼叫,名稱前會多&
swap(&someInt, &anotherInt);
someInt;
anotherInt;

//function type,不管function名稱,只管參數和return值
//function type可以被存在變數,可以當作引數,可以當return type
func addTwoInts(_ a:Int, _ b:Int) -> Int{
    return a + b;
}

func mutiplyTwoInts(_ a:Int, _ b:Int) -> Int{
    return a * b;
}

func printHelloWorld(){
    print("hello, world");
}
//func printHelloWorld()的function type表示法:() -> Void

//將func addTwoInts指定給變數mathFunction,mathFunction的資料類型是function type:(Int, Int) -> Int
var mathFunction:(Int, Int) -> Int = addTwoInts;
print("result:\(mathFunction(2,3))");
mathFunction = mutiplyTwoInts
print("result:\(mathFunction(2, 3))");

//把function當作參數
func printMathResult(_ mathFunction:(Int, Int) -> Int, _ a:Int, _ b:Int) {
    print("Result:\(mathFunction(a,b))")
}
printMathResult(addTwoInts, 3, 5);

Nested Function
//Nested Function
//傳出function
func chooseStepFunction(backward:Bool) -> (Int) -> Int{
    func stepForward(input:Int) -> Int{
        return input + 1
    }
   
    func stepBackward(input:Int) -> Int{
        return input - 1
    }
    //三元運算式 Bool ?true的運算:false的運算
    //下列只是傳出function,不是執行function,所以只輸入function名稱,沒有()!
    return backward ? stepBackward : stepForward
}

var currentValue = -4;
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)

while currentValue != 0 {
    print("\(currentValue)...");
    currentValue = moveNearerToZero(currentValue)
}

Closure(閉鎖)--> 匿名的Function
用在當一個function的參數需求是一個function時,可以直接closure的方式給予。
Closure呼叫時語法:
mainFunction({
    (參數名:資料類型,參數名:資料類型) -> return typr in
    coding................
    coding................
})

let names:[String] = ["Chris", "Alex", "Ewa", "Barry", "Daniella"];
let sotrdNames = names.sorted();
//定義一個function,省略參數名稱
func backward(_ s1:String,_ s2:String) -> Bool{
    return s1 > s2;
}
//func sorted(by: (Element, Element) -> Bool) -> [Element]
//Returns the elements of the sequence, sorted using the given predicate as the comparison between elements.
var reverseNames = names.sorted(by: backward)
//closure 標準寫法
reverseNames = names.sorted(by: {
    (s1:String, s2:String) -> Bool in
    return s1 < s2;
})
//closure 的所有資料類型,可以省略,因為透過推測
reverseNames = names.sorted(by: {
    (s1,s2) in
    return s1 < s2
})

//如果只有一行,可以省略return
reverseNames = names.sorted(by: {
    (s1,s2) in  s1 < s2
})

//s1,s2也可以省略去定義,用$0,$1替代
reverseNames = names.sorted(by: { $0 < $1 })
//連$0,$1都省略
reverseNames = names.sorted(by: < )

//trailing closure,在最後一 個參數
reverseNames = names.sorted(){
    $0 < $1;
}
//trailing closure,在最後一 個參數,連()都省略!
reverseNames = names.sorted{
    $0 < $1;
}
let numbers = [16, 58, 510];
let numberStrings = numbers.map({
    (n:Int) -> String in
    return String(n*2)
})
































2019年5月29日 星期三

control Flow

判斷
if...
else if ...
else...

switch

guard ... else

迴圈
(明確知道要執行的次數)
for in

(不知道要執行的次數)
while

(不知道要執行的次數)
repead
while

let names = ["Anna", "Alex", "Brian", "Jack"];
for name in names {
    print("Hello!\(name)");
}
let numberOfLegs = ["spider":8, "ant":6, "cat":4];
for (animalName, legCount) in numberOfLegs {
    print("\(animalName)s have \(legCount) legs");
}

for index in 1..<5{
    print(index);
}
let base = 3;
let power = 10;
var answer = 1;

for _ in 1...power {
    answer *= base;
}

let minutes = 60
let minuteInterval = 5
//從0開始,每次+5,到60(不包含60)
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
    print(tickMark);
}

//從0開始,每次+5,到60(包含60)
for tickMark in stride(from: 0, through: minutes, by: minuteInterval) {
    print(tickMark);
}

while  判斷 {
 
}
//相當於C的for(int i=25,i>=0;i--)
var finalSquare = 25
while finalSquare >=0 {
    print(finalSquare);
    finalSquare -= 1;
}

finalSquare = 25;
repeat {
    finalSquare -= 1;
} while finalSquare >=0

單向式
if 判斷式 {

}

雙向式 (一定執行其中一個)
if 判斷式 {

} else {

}

多向式(一定執行其中一個)
if 判斷式 {

} else if 判斷式{

} else if 判斷式{

} else {

}

var temperatureInFahrenheit = 30;
if temperatureInFahrenheit <= 32 {
    print("非常冷");
}
temperatureInFahrenheit = 35;
if temperatureInFahrenheit <= 32 {
    print("非常冷");
} else {
    print("不會冷");
}
 temperatureInFahrenheit = 90;
if temperatureInFahrenheit <= 32 {
    print("非常冷");
} else if temperatureInFahrenheit >= 86{
    print("非常熱");
} else {
    print("舒適!")
}
//siwft的switch只會執行其中一個區段,執行完跳出switch!
let someCharacter:Character = "z";
switch someCharacter {
    case "a":
        print("a");
    case "z":
        print("z");
    default:
        print("b~y");
}

let anotherCharacter:Character = "a";
switch anotherCharacter {
    case "a","A":
        print("a,A");
    case "b","B":
        print("b,B");
    default:
        print("其他");
}

//interval Matching
let approximateCount = 62
switch approximateCount {
    case 0:
        print("0");
    case 1..<5:
        print("1~4");
    case 5..<12:
        print("5..11");
    case 12..<100:
        print("12..99");
    case 100..<1000;
        print("100..999");
    default:
        print(">1000");
}
//範圍多值比對
let somePoint = (x:1,y:1);
switch    somePoint {
    case (0,0):
        print("0,0");
    case (_,0):
        print("y=0");
    case (0,_):
        print("x=0");
    case (-2...2,-2...2):
        print("-2...2,-2...2");
    default:
        print("其他");
}
//switch value binding
let anotherPoint = (2,0);
switch anotherPoint {
    case (let x, 0):
        print("y是0,x是\(x)");
    case (0, let y):
        print("x是0,y是\(y)");
    case let (x, y):
        print("x是\(x),y是\(y)");
    //因為一定會執行上方三個區塊其中一個,所以default可以省略!
    /*
    default:
        break;
    */
}
//switch value binding + where
let yetAnotherPoint = (1, -1);
switch yetAnotherPoint {
    //where 後面一定接bool
    case let (x, y) where x == y:
        print("x==y");
    case let (x, y) where x == -y:
        print("x==-y");
    case let (x, y):
        print("x=\(x), y=\(y)");
}

提早離開function
guard ... else,只執行false區段,true時不動作!
guard (false) else {
    false 區段
}
//guard else
func greet(person:[String:String]) {
    guard let name = person["name"] else {
        print("key沒有name");
        return;
    }
    print("Hello!\(name)!");

    gurade let location = person["location"] else {
        print("key沒有location");
        return;
    }
    print("name=\(name),location=\(location)");
}
greet(person: ["name":"John", "location":"Cupertino"]);


collection type

collection type(集合物件)
Array:有順序
Dictionary:沒有順序,key(必須是可以比較大小的(hashable))對應value
set:沒有順序,成員不會重複!hashable(可以比較大小的),Int,Double,Float,Bool,String


資料類型表示法:
陣列:
標準: Array<Int>
簡化:[Int]
var someInts = [Int]();
print(someInts.count); <----0
SomeInts.append(3);
SomeInts.append(4);
SomeInts.append(5);
print(someInts.count); <----3

objective-c
NSMutableArray:可變動(內容)的array
NSArray:不可變動(內容)的array

swift
var Array:可變動
let array:不可變動

var threeDoubles = Array(repeating: 0.0, count:30);
var anotherThreeDouble = Array(repesting: 2.5, count: 3);
var dixDoubles = threeDoubles + anotherThreeDouble;
var shoppingList:[String] = ["Effs", "Milk"];
if shoppingList.isEmpty {
    print("is empty");
} else {
    print("不是空的!有\(shoppingList.count)");
}
shoppingList.append("Flour");
shoppingList += ["Baking Powdwe"];
shoppingList += ["Chocolate Spread", "Cheese","Butter"];
shoppingList[0] = "Six eggs";
shoppingList[4...6];
shoppingList.insert("Maple Syrup", at: 0);
let mapleSyrup = shoppingList.remove(at: 0);

for item in shoppingList {
    print(item);
}

shoppingList.enumerated 傳出tuple (index,item)
for (index,item) in shoppingList.enumerated() {
    print("這個索引編號是\(index),內容是\(item)");
}

資料類型表示法:
Set<Int>
//建立一個空的Set,資料型態是Character,並初始化
var letters = Set<Character>();
print("letters is of type Set<Character> with \(letters.count)");
letters.insert("a");
//清空
letters = [];
//利用陣列值的表示法
var favoriteGenres:Set = ["Rock", "Classical", "Hip hop"];
favoriteGenres.count
favoriteGenres.insert("Jazz");
if favoriteGenres.remove("Rock") == nil {
    print("移除失敗!");
}
if favoriteGenres.contains("Funk") {
    print("有Funk這個值!");
} else {
    print("沒有Funk這個值!");
}
for genre in favoriteGenres {
    print("\(genre)");
}
//一般Set會轉成陣列使用
let sortedGenres = favoriteGenres.sorted();

資料類型表示法:
標準:
Dictionary<String,String>
簡易:
[String:String]
值表示法 ["tw":"Taiwan"];

var namesOfIntegers = [Int:String]();
namesOfIntegers[16] = "sixteen";
//清空
namesOfIntegers = [:];
var airports = [
    "YYZ": "Toronto pearson",
    "DUB": "Dublin"
]
//如果沒有該值,就新增;如果有,就修改!
airports["LHR"] = "London"
airports["LHR"] = "London Heathrow"

//一般的更新法(update())
if let _ =  airports.updateValue("Dublin Airport", forkey: "DUB"){
    //true區段,表示有值
    print("成功!");
} else {
    //false區段得到nil
    print("失敗!");
}
//透過key取出值,會傳出optional type
if let airportName = airports["DUB"] {
    print("DUB的名字是\(airportName)");
} else {
    print("key有錯!");
}
//如果沒有該值,就新增;如果有,就修改!
airports["APL"] = "Apple Internation"
//刪除
airports["APL"] = nil;

for (airportCode, airportName) in airports {
    print("\(airportCode),\(airportName)");
}

for airportCode in airports.keys {
    print(airportCode);
}

for airportName in airports.values {
    print(airportName);
}
//轉陣列
let airportsCodes = [String](airports.keys)
let airportValues = [String](airports.values)