攻Swift一个月总

说从曲面电视,在家门公司中TCL可谓无与伦比积极的品牌,相比同行而言,TCL最曲面电视的加大以及投入是任何小所远不可知于的,因为曲面电视能带非常之玩味体验,特别是临场感体验越来越突出。

个人感悟:一个月的上学,学了成百上千内容,但是并无能够充分好的克,所以说现在头脑里还是同等切开混乱,不能够很好的将修了之物用在编写程序上,所以说得要一致满整个的去敲代码练习,fighting!

图片 1

语言基础

先后是命令的汇,写程序即使是描摹一层层之指令去决定电脑做我们怀念做的事务。
编译:将顺序设计语言转换成计算机能够理解的机器语言或者某种中间代码的经过。

冯诺依曼体系布局的处理器:
1.使用二进制
2.序存储执行

当年TCL推出了新一代的X、C和P等多个系列新品,不过它的稳非常高,并无可知算是平易近人。为了吃再多顾客享受及曲面的奇异功能,TCL在今年春生产了全新的N3层层电视,并于中原尽人皆知家电销售广电商城和片基本门店专售。

变量和常量

概念变量和常量是以保存数据,变量和常量就是某种类型的价值的囤积空间。

var a: Int = 10
a = 100
var b: Int
b = 1000
var c = 10000

let d: Int = 10
// d = 100    // compiler error 编译时出错
let e = 1000

说明:1.Swift有那个强的类型推断,所以定义变量或常量时要可以的语应该一直使用类推断不用手动指定项目;2.若看可以的说话应该尽可能采取常量而非是变量。

PChome收到的马上款N3电视也55英寸,其以TCL主打的4000R黄金曲率,内置腾讯视频、同步院线、并支持多屏互动、微信互联等功用。在屏幕及用3840×2160之4K屏幕,刷新率60hz,响应速度仅为6.5毫秒。

语言元素

var a: Int = 10

重大字:有特别意义的单词
标识符:给变量、常量、函数、类、结构、协议、枚举、方法、属性等由的讳

1.字母(Unicode字符)、数字、下划线,数字不克起
2.大小写敏感(区分轻重缓急写)
3.请勿克采取要字做标识符
4.施用驼峰命名法(命名变量、常量、函数、方法、属性第一个单词小写,从第二单单词开始每个单词首配母大写;命名类、结构、协议、枚举每个单词首假名都使大写)
5.见称作知意
6.命名私有的性与道时以下划线开头

运算符:Swift中之演算符其实都是函数

1.赋值运算符:=、 +=、 -=、 ……
2.终于术运算符:+、 -、 *、 /、 %
3.较运算符:==、 !=、 <、 <=、 >、 >=
4.逻辑运算符:&&、||、 !
5.条件(三元)运算符:? :
6.其他运算符:[]、 .、 ??、 ?、 !、

字面(常)量:

1.整数字面量:10、1_234_567、0x10、0o10、0b10、
2.多少数字面量:123.45、1.2345e2、0xab.cdp2
3.字符字面量:”c”、”\n”、”\u{41}”、”\u{9a86}、”\t”
4.字符串字面量:”Hello”、”caf\u{e9}”
5.布尔字面量:true、false
6.空值字面量:nil
7.类型字面量:String.self、UILabel.self

相隔符:将不同的言语元素符号分开

说明:Swift中每个语句后面的支行是只是写不过免写,写代码时尽可能确保一行就来平等长条告句这样虽好看略掉分号。

图片 2

分层和循环

外观设计 经典曲面超薄

分支

  • if…else…

// 分段函数
let x = 3.2
let y: Double
if x < -1 {
   y = 3 * x + 5
}
else if x <= 1 {
   y = 5 * x - 3
}
else {
   y = 7 * x + 1
}
print("f(\(x))=\(y)")
  • switch…case…default

// IT从业人员等级评定
print("请输入你的月薪: ", terminator: "")
let salary = inputInt()
if salary >= 0 {
    switch salary {
    case 0:
        print("你是一个无业游民")
    case 1...30000:
        print("你是一个小码畜")
    case 30001...60000:
        print("你是一个小码奴")
    case 60001...100000:
        print("你是一个大码农")
    case 100001...200000:
        print("你是一个光荣的IT民工")
    case 200001...500000:
        print("你是一个优秀的IT工程师")
    case 500001..<10000000:
        print("你是IT精英")
    case 10000000..<100000000:
        print("你是IT大哥, 我服")
    default:
        print("你是头上有光环的IT领袖, 求带")
    }
}
else {
    print("你丫有病!!!")
}

于外观设计及TCL
55N3延续沿用了金属窄边框设计,通过先进的磨砂阳亢氧化工艺和8道精密加工工序,将航天级铝材与电视屏幕完美融合,并带坚固耐用的金属机身,同时也越来越提升了电视机外观的质感。

循环

  • while

// 求和1-100
var sum = 0
var i = 1
while i <= 100 {
    sum += i
    i += 1
}
print(sum)
  • repeat…while

// 求和1-100
var sum = 0
var i = 1
repeat {
    sum += i
    i += 1
} while i <= 100
print(sum)
  • for

// 求和1-100

var sum = 0
for i in 1...100 {
        sum += i
}
print(sum)

// 冒泡排序:两两比较,前面的元素比后面的元素大就交换位置

var array = [98, 29, 35, 12, 47, 66, 53, 79]

for i in 0..<array.count - 1 {
    var swapped = false
    for j in 0..<array.count - 1 - i {
        if array[j] > array[j + 1] {
            (array[j], array[j + 1]) = (array[j + 1], array[j])
        }
    }
    if !swapped {
        break
    }
}

print(array)

// 简单选择排序:每次从剩下的元素中找最小的元素放到对应位置

var array = [98, 29, 35, 12, 47, 66, 53, 79]
for i in 0..<array.count - 1 {//比较次数
    var minIndex = i
    for j in i + 1..<array.count {
        if array[j] < array[minIndex] {
            minIndex = j
        }
    }
    (array[i], array[minIndex]) = (array[minIndex], array[i])
}

print(array)

//1-10000之间所有的完美数
func cube(n: Int) -> Int {
    return n * n * n
}
for i in 100...999 {
    let a = i % 10          // 个位
    let b = i / 10 % 10     // 十位
    let c = i / 100         // 百位
    if i == cube(a) + cube(b) + cube(c) {
        print(i)
    }
}

穷举法:穷尽所有可能性直到找到科学答案。

下的程序实现了”百钱百鸡”

for x in 0...20 {
    for y in 0...33 {
        let z = 100 - x - y
        if 5 * x + y * 3 + z / 3 == 100 && z % 3 == 0 {
        print("公鸡:\(x), 母鸡:\(y), 小鸡:\(z)")
        }
    }
}

说明:在循环中可以应用break关键字来提前停止循环,也得采用continue关键字使循环直接进去下一样车轮,但是当尽量减少对break和continue的应用,因为她们无见面让你的程序变得更好

综合案例:Craps赌博游戏

游戏规则:玩家摇色子,如果第一涂鸦摇出了7点或11沾,玩家大;如果摇来了2点、3要么12接触,庄家胜;其他点数游戏继续。再持续的过程中玩家再摇色子,如果摇来了7点,庄家胜;如果摇起了第一次摇的罗列,玩家大;否则玩家继续摇色子直到分出胜负。

func roll () -> Int {
    return Int(arc4random_uniform(6)) + 1
}
var money = 1000
var needsGoOn = false
repeat{
    print("资产:\(money)元")
    var debt: Int
    repeat{
        print("请下注:", terminator: "")
        debt = inputInt()
        } while debt <= 0 || debt > money
    let firstPoint = roll() + roll()
    print("玩家摇出了\(firstPoint)点")
    switch firstPoint {
    case 7, 11:
        money += debt
        print("玩家胜")
    case 2, 3, 12:
        money -= debt
        print("庄家胜")
    default:
        needsGoOn = true
    }
    while needsGoOn {
        let currentPoint = roll() + roll()
        print("玩家摇出了\(currentPoint)点")
        if currentPoint == 7 {
            money -= debt
            print("庄家胜")
            needsGoOn = false
        }
        else if currentPoint == firstPoint {
            money += debt
            print("玩家胜")
            needsGoOn = false
        }
}
} while money > 0
print("你boom了")

图片 3

容器

民俗概念里曲面电视的厚度未会见太薄,不过这2年就工艺技术的敏捷提升,曲面电视的厚度大幅度回落。TCL
55N3尽管是这样同样慢慢悠悠产品,机身最薄的处只有为10.91毫米,要明了该用得是直下式背光,厚度比侧入式背光复杂的大多,所以说TCL的工业设计与制力还是蛮高的。

数组

数组是使连续的内存空间保存多只同品种的要素的器皿,因为数组中的元素在内存中是连续的,所以可以运用下标

  • 创造数组

var array1: [Int] = []
var array2: Array<Int> = []
var array3 = [1, 2, 3, 4, 5]
var array4 = [Int](count: 5, repeatedValue: 0)
var array5 = Array<Int>(count: 5, repeatedValue: 0)
  • 补给加元素

array1.append(2)
array1.append(3)
array1.insert(1, atIndex: 0)
array1.insert(4, atIndex: array1.count)
array1 += [5]
array1 += [6, 7, 8]
  • 去除元素

array1.removeAtIndex(2)
array1.removeFirst()
array1.removeFirst(2)
array1.removeLast()
array1.removeRange(1...2)
array1.removeAll()
  • 改元素

array3[0] = 100
array3[array3.count - 1] = 500
  • 遍历数组
    1.方式1:

for i in 0..<array3.count {
    print(array3[i])
}

2.方式2:

for temp in array3 {
    print(temp)
}
for temp in array3[1...3] {
    print(temp)
}

说明:for-in循环是一个才读循环,这也就表示当循环的长河被无能够针对数组中的元素进行修改

3.方式3:

for (i, temp) in array3.enumerate() {
    if i == 0 {
        array3[i] = 1
    }
    print("\(i). \(temp)")
}

提醒:操作数组时最重大之仪式不要越界访问元素。数组对象的count属性表明了数组中出微个因素,那么实用之目录(下标)范围是0交count-1

数组中的因素也得是多次组,因此我们得组织多维数组。最广的是二维数组,它一定给是一个发出实行有列的再三组,数组中之每个元素代表一行,该数组中之每个元素代表行里面的排。二维数组可以效仿现实世界中的报表、数学及之矩阵、棋牌类游戏的棋盘、格子类游戏的地图(植物大战僵尸),所以于实际付出被,使用十分普遍。

下的程序是用二维数组模拟表格的例子。

func randomInt(min: UInt32, max: UInt32) -> Int {
    return Int(arc4random_uniform(max - min + 1) + min)
}

let namesArray = ["关羽", "张飞", "赵云", "马超", "黄忠"]
let coursesArray = ["语文", "数学", "英语"]

var scoresArray = [[Double]](count: namesArray.count, repeatedValue: [Double](count: coursesArray.count, repeatedValue: 0))

for i in 0..<scoresArray.count {
    for j in 0..<scoresArray[i].count {
        scoresArray[i][j] = Double(randomInt(50, max: 100))
    }
}

for (index, array) in scoresArray.enumerate() {
    var sum = 0.0
    for score in array {
        sum += score
    }
    let avg = sum / Double(coursesArray.count)
    print("\(namesArray[index])的平均成绩为: \(avg)")
}

for i in 0..<coursesArray.count {
    var sum = 0.0
    for row in 0..<scoresArray.count {
        sum += scoresArray[row][i]
    }
    let avg = sum / Double(namesArray.count)
    print("\(coursesArray[i])课的平均成绩为: \(avg)")
}

于底盘的计划性上选用时尚美观的倒V字底座,经过组织力学设计后底究竟不仅结实可靠,在外观及为显示简洁大方,没有尽多花哨的地方。

集合

聚拢在内存中是离散的,集合中的因素通过测算Hash
Code(哈希码或免除列码)来决定存放在内存中的哎位置,集合中莫允有再次元素。

  • 创立集合

var set: Set<Int> = [1, 2, 1, 2, 3, 5]
  • 增长跟去元素

set.insert(100)

set.remove(5)
set.removeFirst()
set.removeAll()
  • 集结运算(交集、并集、差集)

var set1: Set<Int> = [1, 2, 1, 2, 3, 4, 5]
var set2: Set<Int> = [1, 3, 5, 7]

set1.intersect(set2)
set1.union(set2)
set1.subtract(set2)
  • 混合(a和b都有些元素):

print(a.intersect(b)) // 输出为:[5, 3]
  • 并集(a和b的有因素):

print(a.union(b)) // 输出为:[2, 9, 5, 7, 3, 1, 11]
  • 差集(a有b没有的元素):

print(a.subtract(b)) // 输出为:[2, 1]

图片 4

字典

字典是为键值对的措施保存数据的容器,字典中之每个元素还是键值对成,通过键可以查找到对应的价值。

  • 创造字典

let dict: [Int: String] = [
    1:"hello"
    2:"good"
    3:"wonderful"
    5:"delicious"
]
  • 丰富、删除、修改元素

dict[3] = "terrible"
dict[4] = "shit"
dict[5] = nil
  • 遍历元素

for key in dict.keys {
    print("\(key) ---> \(dict[key])")
}

for value in dict.values {
    print(value)
}

for (key, value) in dict {
    print("\(key) ---> \(value)")
}

电视机里设计于短小,所有接口都集中在机身边缘。

根本操作

  • 排序
    1.sort
    2.sortInPlace

说明:排序方法的参数是一个闭包(closure),该闭包的来意是比数组中少单因素的大小。

let array = [23, 45, 12, 89, 98, 55, 7]

array.sort({(one: Int, two: Int) -> Bool in
    return one < two
})
array.sort({(one, two) in one < two})
array.sort({one, two in one < two})
array.sort({$0 < $1})
array.sort{$0 < $1}
array.sort(<)
  • 过滤

let array = [23, 45, 12, 89, 98, 55, 7]
// 筛选掉不满足条件的数据
let newArray1 = array.filter {$0 > 50}
print(newArray) // [89, 98, 55]
  • 映射

let array = [23, 45, 12, 89, 98, 55, 7]
// 通过映射对数据进行变换处理
let newArray = array.map { $0 % 10 }
print(newArray)
  • 归约

let array = [23, 45, 12, 89, 98, 55, 7]
let result = array.reduce(0, combine: +)
print(result)

图片 5

函数和闭包

函数是独的只是重复使用的功能模块,如果程序中起了大量的重复代码,通常还好以立即一部分效果封装成一个独门的函数。在Swift中,函数&quot;一对等萌&quot;函数可以作为项目来使用,也就是说函数可以赋值给一个变量或常量,可以拿函数作为函数的参数或者返回值,还可应用高阶函数。

func  函数名([参数1:类型, 参数2: 类型,...]) [throws | rethrows] [-> 返回类型] {
    函数的执行体
    [return 表达式]
}
  • 函数称(外部参数名 内部参数曰: 类型, 外部参数名 内部参数称作: 类型)

  • 标参数号称

func myMin(a x: Int, b y: Int) -> Int {
    return x < y ? x : y
  • inout参数
    ~inout – 输入输出参数(不仅以数据传函数还要从函数中取出数据)
    ~inout类型的参数前使增长&符号

func swap(inout a: Int, inout _ b: Int) -> Void {
    (a, b) = (b, a)
//    let temp = a
//    a = b
//    b = temp
}

var a = 300, b = 500
swap(&a, &b)
print("a = \(a)")      // 输出为:a = 500
print("b = \(b)")      // 输出为:b = 300

func createX(inout x: Int) {
    x = 1000
}
var x = 1
createX(&x)
print(x)       // 输出为: 1000
  • 但变换参数列表

func sum(nums: Int...) -> Int {
    var total = 0
    for num in nums {
        total += num
    }
    return total
}

print(sum())                           // 输出为: 0
print(sum(999))                        // 输出为:999
print(sum(1, 2, 3))                    // 输出为:6
print(sum(90, 82, 37, 68, 55, 11, 99)) // 输出为:442

闭包就是从未名字的函数或者叫做函数表达式(Lambda表达式),Objectiv-C中同的相应之概念叫block。如果一个函数的参数类型是函数我们得传一个闭包;如果一个函数的回来路是函数我们可返回一个闭包;如果一个看似的有属性是函数我们啊堪说话一个闭包表达式赋值给她。

{([参数列表]) [-> 返回类型] in 代码 }

接口及提供USB2.0通人数2单,HDMI 2.0接口3只,其他诸如AV IN
网络接口、RF输入、音频输出、S/PDIF也是包罗万象。

面向对象编程(OOP)

图片 6

基本概念

目标:接收信息之单元,对象是一个切实的的概念。

类似:对象的蓝图和模板,累世一个抽象概念。

信息:对象中通信的法,通过为目标发信息可以叫对象执行相应的操作来缓解问题。

遥控器采用传统数字按键结合互联网电视的风格,回退、主页和菜单都是必要的,此外还提供设置以及信号源选择按键。相比X系列的遥控器,这款55N3电视遥控器手感更加舒畅,主要是握感较好,不爱打滑。此外要搭配语音遥控器还只是匹配讯飞语音5.0实现智能语音操控。

季不行柱子

虚幻:定义类的历程尽管是一个抽象的过程,需要开数据抽象和行事抽象,数据抽象找到对象的属性(保存对象状态的贮存属性),行为抽象找到对象的法门(可以于目标发信息)。

封装:

  • 意1:我们当类似吃写方法其实就算是以封装API,方法的内部贯彻可能会见那个复杂,但是这些对调用者来说是不可见的,调用只能看方法发生一个大概清晰的接口。
  • 观2:将目标的属性与操作这些性的法子绑定在协同。
  • 理念3:隐藏一切可以隐藏的兑现细节,只供简清晰的接口(界面)。

继往开来:从曾经部分类创建新类的经过叫继承

多态:同样的对象类型接收相同的音讯(调用相同之计),但是举行了不同的事体
这就是多态(polymorphism)

  • 贯彻多态的关键步骤:
    ①方式重写(子类在延续父类的过程被针对父类已有些艺术开展重写,
    而且不同的子类给有个别不同之落实版本)
    ②目标造型(将子类对象正是父类型来利用)
    ~可以经过if+as?将父类型安全的变换成子类型然后又调用子类特有点子

图片 7

老三单步骤

  1. 定义类

  2. 数据抽象

    • 存储属性
  3. 行抽象
    • 方(写及类似中的函数就是方法或者说与对象绑定的作为)
      • 靶方法:给对象法的消息而先创建对象才会调用,与目标状态有关
      • 恍如方式:给类法的音信所以不用创建对象直接通过类名调用,与目标的状态无关的法门
        方法前加 static或class,作用一样
  4. 构造器

    • 凭借派构造器
    • 就利构造器(convenience)
    • 必备构造器(required)
  5. 创建对象

  6. 被目标发消息

class Triangle {
    var a: Double
    var b: Double
    var c: Double

    init(a: Double, b: Double, c: Double) {
        self.a = a
        self.b = b
        self.c = c
    }

    // 类方法(发给类的消息与对象状态无关)
    // 此处的static也可以换成class作用相同
    static func isValid(a: Double, _ b: Double, _ c: Double) -> Bool {
        return a + b > c && b + c > a && c + a > b
    }
    // 对象方法(发给对象的消息与对象状态有关)
    func perimeter() -> Double {
        return a + b + c
    }
}

let a = 1.0
let b = 2.0
let c = 3.0
// 在创建对象前先调用类方法判定给定的三条边能否构成三角形
// 类方法是发给类的消息所以不用创建对象直接通过类名调用
if Triangle.isValid(a, b, c) {
    let t = Triangle(a: a, b: b, c: c)
    // 对象方法是发给对象的消息要先创建对象才能调用
    print(t.perimeter())
}
else {
    print("无法创建三角形")
}

面板画质测试 色彩准控光强

相关内容

  • 枚举

~枚举是概念符号常量的极品方式
~符号常量总是优于字面常量
~示例(枚举和文档注释的采用):

/**
 花色的枚举

 - Spade:   黑桃
 - Heart:   红心
 - Club:    草花
 - Diamond: 方块
 */
enum Suite: String {
    case Spade = "♠️"
    case Heart = "❤️"
    case Club = "♣️"
    case Diamond = "♦️"
}

/// 一张牌
class Card {
    var suite: Suite
    var face: Int

    /**
     初始化方法
     - parameter suite: 花色
     - parameter face:  点数
     */
    init(suite: Suite, face: Int) {
        self.suite = suite
        self.face = face
    }

    /// 牌的信息
    var info: String {
        get {
            var str = suite.rawValue
            switch face {
            case 1: str += "A"
            case 11: str += "J"
            case 12: str += "Q"
            case 13: str += "K"
            default: str += "\(face)"
            }
            return str
        }
    }
}
  • 结构(体)
    区分1: 结构的目标是值类型, 类的靶子是援类型
    值类型在赋值的早晚会当内存中开展对象的正片
    引用类型在赋值的时不会见进展对象拷贝只是多了一个引用
    敲定:
    我们从定义新类型时事先考虑采用类设非是组织除非我们如果定义的凡同一种底层的数据结构(保存其他数的门类)
    分别2: 结构会自动生成初始化方法
    别3:
    结构面临之办法以默认情况下是匪允许修改结构中之习性除非加上mutating关键字

总结:类以及结构的分到底有哪些?什么时候理应利用结构?什么时该利用类似?

  • 扩展(extension)
    ~如果当有特定的利用场景被而意识现有的类似缺少了某个项职能
    那好由此类似扩展(extension)的方式当场加上这项功能
  • 运算符重载 (要描绘于接近的外界)(为打定义之类型定义运算符)

class Fraction {
    private var _num: Int
    private var _den: Int

    var info: String {
        get {
            return _num == 0 || _den == 1 ? "\(_num)" : "\(_num)/\(_den)"
        }
    }

    init(num: Int, den: Int) {
        _num = num
        _den = den
        simplify()
        normalize()
    }

    func add(other: Fraction) -> Fraction {
        return Fraction(num: _num * other._den + other._num * _den, den: _den * other._den)
    }

    func sub(other: Fraction) -> Fraction {
        return Fraction(num: _num * other._den - other._num * _den, den: _den * other._den)
    }

    func mul(other: Fraction) -> Fraction {
        return Fraction(num: _num * other._num, den: _den * other._den)
    }

    func div(other: Fraction) -> Fraction {
        return Fraction(num: _num * other._den, den: _den * other._num)
    }

    func normalize() -> Fraction {
        if _den < 0 {
            _num = -_num
            _den = -_den
        }
        return self
    }

    func simplify() -> Fraction {
        if _num == 0 {
            _den = 1
        }
        else {
            let x = abs(_num)
            let y = abs(_den)
            let g = gcd(x, y)
            _num /= g
            _den /= g
        }
        return self
    }
}

// 运算符重载(为自定义的类型定义运算符)

func +(one: Fraction, two: Fraction) -> Fraction {
    return one.add(two)
}

func -(one: Fraction, two: Fraction) -> Fraction {
    return one.sub(two)
}

func *(one: Fraction, two: Fraction) -> Fraction {
    return one.mul(two)
}

func /(one: Fraction, two: Fraction) -> Fraction {
    return one.div(two)
}
  • 下标运算(subscript)

  • 访修饰符

    • private
    • internal
    • public

经仪器测试可看来,TCL
55N3电视机的色域水平并无是甚高,sRGB接近标称的100%,NTSC大约72%横。在亮度上实测最高亮度242.4尼特,静态对比度最高27960比1,50%亮度下对比度高臻1720比较1。

面向协议编程(POP)

图片 8

协议

protocol 协议名[:父协议1,父协议2,...] {
    // 方法的集合(计算属性相当于就是方法)
}

1.能力: 遵循了协商便表示有了某种能力
2.预约: 遵循了协议就必定要是落实协议被之主意
3.角色: 一个好像可以多独协议, 一个共谋得以叫多个像样以,
遵循协议就表示扮演了某种角色, 遵循多只商量便代表可以装扮多种角色

注意:Swift中之存续是纯继承(一个看似只能发出一个父类),
如果希望让一个像样具有多再次力量可以协议来贯彻(C++里面是透过多重复继承来促成的,
这是均等栽死狗血之做法)

亮度均匀性方面,顶部两侧的偏差值多少大,中间段亮度区别较小。不过对直下式背光电视来说,这点距离对视觉影响并无殊。

乘反原则

仗反原则(面向协议编程)

  1. 声明变量的种时应尽可能用协议项目
  2. 宣示方法参数类型时应有尽量使用协议项目
  3. 声明方法返回路时该尽量采取协议项目

图片 9

因而协议落实委托回调

一个目标想做有项事而我没有能力做就档子事,就可以用委托回调,具体步骤是:

  1. 规划一个商,让让委托方遵循协议并落实协议被的不二法门
  2. 委托方有一个性是协商项目的,通过该属性可以调用协议中之办法
    示例:五子棋App

import UIKitA

// RenjuBoard.swift

/**
 棋盘交叉点的状态

 - Space: 空格
 - Black: 黑棋
 - White: 白棋
 */
enum PointState {
    case Space, Black, White
}

/// 棋盘
class RenjuBoard {
    var board: [[PointState]]
    var isBlackTurn = true
    var isGameOver = false

    init() {
        board = [[PointState]](count: 15, repeatedValue: [PointState](count: 15, repeatedValue: .Space))
    }

    // 索引器语法 - 可以直接对棋盘对象做下标运算来放置棋子
    subscript(row: Int, col: Int) -> Bool {
        get { return board[row][col] == .Space }
        set(isBlack) {
            if board[row][col] == .Space {
                board[row][col] = isBlack ? .Black : .White
                isBlackTurn = !isBlackTurn
            }
        }
    }

    func reset() {
        isGameOver = false
        isBlackTurn = true
        for i in 0..<board.count {
            for j in 0..<board[i].count {
                board[i][j] = .Space
            }
        }
    }

    func judge(row: Int, _ col: Int) -> Bool {
        return _judgeH(row, col) || _judgeV(row, col) || _judgeX1(row, col) || _judgeX2(row, col)
    }

    private func _judgeH(row: Int, _ col: Int) -> Bool {
        var counter = 1
        var currentCol = col - 1
        while currentCol >= 0 {
            if board[row][currentCol] == board[row][col] {
                counter += 1
                currentCol -= 1
            }
            else {
                break
            }
        }
        currentCol = col + 1
        while currentCol < board.count {
            if board[row][currentCol] == board[row][col] {
                counter += 1
                currentCol += 1
            }
            else {
                break
            }
        }
        return counter >= 5
    }

    private func _judgeV(row: Int, _ col: Int) -> Bool {
        var counter = 1
        var currentRow = row - 1
        while currentRow >= 0 {
            if board[currentRow][col] == board[row][col] {
                counter += 1
                currentRow -= 1
            }
            else {
                break
            }
        }
        currentRow = row + 1
        while currentRow < board.count {
            if board[currentRow][col] == board[row][col] {
                counter += 1
                currentRow += 1
            }
            else {
                break
            }
        }
        return counter >= 5
    }

    private func _judgeX1(row: Int, _ col: Int) -> Bool {
        var counter = 1
        var currentRow = row - 1
        var currentCol = col - 1
        while currentRow >= 0 && currentCol > 0 {
            if board[currentRow][currentCol] == board[row][col] {
                counter += 1
                currentRow -= 1
                currentCol -= 1
            }
            else {
                break
            }
        }
        currentRow = row + 1
        currentCol = col + 1
        while currentRow < board.count && currentCol < board.count {
            if board[currentRow][currentCol] == board[row][col] {
                counter += 1
                currentRow += 1
                currentCol += 1
            }
            else {
                break
            }
        }
        return counter >= 5
    }

    private func _judgeX2(row: Int, _ col: Int) -> Bool {
        var counter = 1
        var currentRow = row - 1
        var currentCol = col + 1
        while currentRow >= 0 && currentCol < board.count {
            if board[currentRow][currentCol] == board[row][col] {
                counter += 1
                currentRow -= 1
                currentCol += 1
            }
            else {
                break
            }
        }
        currentRow = row + 1
        currentCol = col - 1
        while currentRow < board.count && currentCol >= 0 {
            if board[currentRow][currentCol] == board[row][col] {
                counter += 1
                currentRow += 1
                currentCol -= 1
            }
            else {
                break
            }
        }
        return counter >= 5
    }

    func draw() {
        let lineBP = UIBezierPath()

        // 绘制15条横线和15条竖线来构造一个棋盘
        for i in 0..<board.count {
            lineBP.moveToPoint(CGPointMake(10, 10 + 50 * CGFloat(i)))
            lineBP.addLineToPoint(CGPointMake(710, 10 + 50 * CGFloat(i)))
            lineBP.moveToPoint(CGPointMake(10 + 50 * CGFloat(i), 10))
            lineBP.addLineToPoint(CGPointMake(10 + 50 * CGFloat(i), 710))
        }
        lineBP.stroke()

        // 绘制棋盘的边框
        let rectBP = UIBezierPath(rect: CGRectMake(3, 3, 714, 714))
        rectBP.lineWidth = 6
        rectBP.stroke()

        // 绘制天元和星
        let starsRectArray = [
            CGRectMake(155, 155, 10, 10),
            CGRectMake(555, 155, 10, 10),
            CGRectMake(155, 555, 10, 10),
            CGRectMake(555, 555, 10, 10),
            CGRectMake(355, 355, 10, 10)
        ]
        for starRect in starsRectArray {
            let ovalBP = UIBezierPath(ovalInRect: starRect)
            ovalBP.fill()
        }

        // 绘制棋盘上的棋子
        for i in 0..<board.count {
            for j in 0..<board[i].count {
                if board[i][j] != .Space {
                    let ovalBP = UIBezierPath(ovalInRect: CGRectMake(-10 + CGFloat(j) * 50, -10 + CGFloat(i) * 50, 40, 40))
                    (board[i][j] == .Black ? UIColor.blackColor() : UIColor.whiteColor()).set()
                    ovalBP.fill()
                }
            }
        }
    }
}

// Canvas.swift

// 有的时候某个对象要做某件事情但其自身又没有能力做这件事情
// 这个时候就可以使用委托回调的编程模式让别的对象来做这件事情
// 实现委托回调的编程模式有以下几个步骤:
//  1. 设计一个协议(被委托方必须要遵循协议才能给别的对象当委托)
protocol CanvasDelegate: class {

    // 协议里面的方法就是要委托其他对象做的事情
    func showMessage(canvas: Canvas, message: String)
}

class Canvas: UIView {
    // 2. 委托方添加一个属性其类型是遵循了协议的被委托方
    weak var delegate: CanvasDelegate?

    var renjuBoard = RenjuBoard()
    var isAutoMode = false

    func clearBoard() {
        renjuBoard.reset()
        setNeedsDisplay()
    }

    func randomMove() {
        let row = Int(arc4random_uniform(15))
        let col = Int(arc4random_uniform(15))
        if renjuBoard[row, col] {
            renjuBoard[row, col] = renjuBoard.isBlackTurn
            setNeedsDisplay()
        }
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        // Swift 2中的guard大法, Swift 3中据说要废掉
        guard !isAutoMode else { return }
        // guard !renjuBoard.isGameOver else { return }

        if !renjuBoard.isGameOver {
            if let touch = touches.first {
                let point = touch.locationInView(self)
                let row = lround(Double(point.y - 10) / 50)
                let col = lround(Double(point.x - 10) / 50)
                if renjuBoard[row, col] {
                    renjuBoard[row, col] = renjuBoard.isBlackTurn
                    setNeedsDisplay()
                    if renjuBoard.judge(row, col) {
                        renjuBoard.isGameOver = true
                        // 3. 自己做不了的事情委托给别的对象来做
                        delegate?.showMessage(self, message: renjuBoard.isBlackTurn ? "白棋胜" : "黑棋胜")
                    }
                }
            }
        }
    }

    override func drawRect(rect: CGRect) {
        renjuBoard.draw()
    }

}

// ViewController.swift

//  4. 让视图控制器遵循协议成为被委托方(协议表能力)
class ViewController: UIViewController, CanvasDelegate {

    var timer: NSTimer?
    var canvas: Canvas!

    override func viewDidLoad() {
        super.viewDidLoad()

        canvas = Canvas(frame: CGRectMake(0, 0, 720, 720))
        // canvas.isAutoMode = true
        //  6. 给画布对象绑定委托(self就是视图控制器对象它遵循了协议所以有充当委托的能力也就是说可以扮演被委托方的角色)
        canvas.delegate = self
        canvas.center = self.view.center
        canvas.backgroundColor = UIColor(red: 254.0 / 255.0, green: 209.0 / 255.0, blue: 46.0 / 255.0, alpha: 1)
        self.view.addSubview(canvas)

        // timer = NSTimer.scheduledTimerWithTimeInterval(0.2, target: canvas, selector: "randomMove", userInfo: nil, repeats: true)
    }

    //  5. 遵循协议就必须要实现协议中的方法(协议表约定)
    func showMessage(canvas: Canvas, message: String) {
        let alertController = UIAlertController(title: message, message: "", preferredStyle: .Alert)
        let okAction = UIAlertAction(title: "确定", style: .Default) { action in
            // 此处通过尾随闭包来定义点击确定按钮后要做什么
            canvas.clearBoard()
        }
        alertController.addAction(okAction)
        self.presentViewController(alertController, animated: true, completion: nil)
    }

    // deinit在销毁对象的时候调用
    deinit {
        // 销毁计时器
        timer?.invalidate()
    }
}

注意:委托方的商谈项目的属性通常是不过空类型,因为一旦描绘成永诀引用(weak)。

情调精确性方面表现是,最可怜不是的凡湛蓝在,Delta
E值8.34,平均偏差值仅为3.47,表现很精彩。

其他

  • 说道组合: protocol<协议1, 协议2, …>
  • 可选方法
  • 商事扩展:对商中之方法被起默认实现,也就是说要某类以了协和而从未落实此法就是一直用默认实现,那么这艺术也就是一定给是一个可选方法(可以实现吗足以免实现)
  • 说道被全都是抽象概念(只有声明没有兑现)
    遵循协议的接近可以分级对协议被之测算属性与措施为来团结的实现版本
    这样当我们面向协议编程时虽可以管多态的优势发挥到淋漓尽致
    可以写有又通用更灵敏的代码(符合开闭原则)
  • 落实开闭原则最重点有有限触及:

  • 空泛是要(在筹划系统的时势必要统筹好之说道);

  • 封装可变性(桥梁模式 – 将不同之可变因素封装到不同的继续结构面临)

  • 接口(协议)隔离原则:
    协议的设计而稍微而占据不若死而清一色,协议的计划性为如高度内聚

  • 以身作则:打折策略协议

import Foundation

/**
 *  打折策略协议
 */
protocol DiscountStrategy {

    /**
     计算折扣
     - parameter price: 原价
     - returns: 折扣的金额
     */
    func discount(price: Double) -> Double
}

/// 百分比折扣策略
class PercentageDiscount: DiscountStrategy {
    var percentage: Double

    init(percentage: Double) {
        self.percentage = percentage
    }

    func discount(price: Double) -> Double {
        return price * (1 - percentage)
    }
}

// 固定金额折扣策略
class FixedDiscount: DiscountStrategy {
    var fixedMoney: Double

    init(fixedMoney: Double) {
        self.fixedMoney = fixedMoney
    }

    func discount(price: Double) -> Double {
        return price >= fixedMoney ? fixedMoney : 0
    }
}

// 分段折后策略
class SegmentedDiscount: DiscountStrategy {

    func discount(price: Double) -> Double {
        if price < 20 {
            return 0
        }
        else if price < 50 {
            return 3
        }
        else if price < 100 {
            return 10
        }
        else {
            return 30
        }
    }
}

/// 图书
class Book {
    var name: String
    var price: Double
    var type: String

    // 四人帮设计模式 - 策略模式
    var strategy: DiscountStrategy?

    /**
     初始化方法
     - parameter name:  书名
     - parameter price: 价格
     - parameter type:  类型
     */
    init(name: String, price: Double, type: String) {
        self.name = name
        self.price = price
        self.type = type
    }

    /// 减多少钱
    var discountValue: Double {
        get {
            if let s = strategy {
                return s.discount(price)
            }
            else {
                return 0
            }
        }
    }

    /// 折后价格
    var discountedPrice: Double {
        get { return price - discountValue }
    }
}

let booksArray = [
    Book(name: "C语言程序设计", price: 24.0, type: "计算机"),
    Book(name: "名侦探柯南", price: 98.5, type: "漫画"),
    Book(name: "Swift从入门到住院", price: 35.8, type: "计算机"),
    Book(name: "黄冈数学密卷", price: 34.2, type: "教材"),
    Book(name: "中国股市探秘", price: 58.5, type: "金融")
]

let discountDict: [String: DiscountStrategy] = [
    "计算机": PercentageDiscount(percentage: 0.78),
    "教材": PercentageDiscount(percentage: 0.85),
    "漫画": SegmentedDiscount(),
    "科普": FixedDiscount(fixedMoney: 2)
]

var totalPrice = 0.0
var totalDiscount = 0.0
for book in booksArray {
    if let strategy = discountDict[book.type] {
        book.strategy = strategy
    }
    print("《\(book.name)》原价: ¥\(book.price)元")
    print("《\(book.name)》折后价: ¥\(book.discountedPrice)元")
    totalPrice += book.discountedPrice
    totalDiscount += book.discountValue
}

print(String(format: "总计: ¥%.1f元", totalPrice))
print(String(format: "为您节省了: ¥%.1f元", totalDiscount))

图片 10

泛型

被项目不再是次中之硬代码(hard code),可以计划出更通用的代码。

  • 泛型函数
    经过演示来明泛型函数

import Foundation

// 泛型 (generic) - 让类型不再是程序中的硬代码(写死的东西)

func bubbleSort<T: Comparable>(array: [T]) -> [T] {
    var newArray = array
    for i in 0..<newArray.count - 1 {
        var swapped = false
        for j in 0..<newArray.count - 1 - i {
            if newArray[j] > newArray[j + 1] {
                mySwap(&newArray[j], &newArray[j + 1])
                swapped = true
            }
        }
        if !swapped {
            break
        }
    }
    return newArray
}

// 定义一个虚拟类型T, 调用函数时根据传入的参数类型来决定T到底是什么
func mySwap<T>(inout a: T, inout _ b: T) {
    let temp = a
    a = b
    b = temp
}

// 泛型限定
// <T: Comparable>限定T类型必须是遵循了Comparable协议的类型
func myMin<T: Comparable>(a: T, _ b: T) -> T {
    return a < b ? a : b
}


let array1: Array<Int> = [23, 45, 99, 12, 68, 51, 70, 66]
let array2 = bubbleSort(array1)
print(array1)
print(array2)

let array3 = ["hello", "zoo", "kiss", "apple", "good"]
let array4 = bubbleSort(array3)
print(array3)
print(array4)

class Student: Comparable {
    var name: String
    var age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

func ==(one: Student, two: Student) -> Bool {
    return one.name == two.name
}

func <(one: Student, two: Student) -> Bool {
    return one.name < two.name
}

func <=(one: Student, two: Student) -> Bool {
    return one.name <= two.name
}

func >(one: Student, two: Student) -> Bool {
    return one.name > two.name
}

func >=(one: Student, two: Student) -> Bool {
    return one.name >= two.name
}

var stu1 = Student(name: "Luo Hao", age: 35)
var stu2 = Student(name: "Wang Dachui", age: 18)

let minStu = myMin(stu1, stu2)
print(minStu.name)

var x = "hello", y = "good"
mySwap(&x, &y)
print(x, y)
print(myMin(x, y))

var a = 3.5, b = 1.2345
mySwap(&a, &b)
print(a, b)
print(myMin(a, b))

var c = 10, d = 100
mySwap(&c, &d)
print(c, d)
print(myMin(c, d))

// Swift中的类、结构和枚举都可以使用泛型
struct Stack<T> {
    var data: [T] = []

    // 入栈
    mutating func push(elem: T) {
        data.append(elem)
    }

    // 出栈
    mutating func pop() -> T {
        return data.removeLast()
    }

    var isEmpty: Bool {
        get { return data.count == 0 }
    }
}

var stack = Stack<String>()
stack.push("hello")
stack.push("good")
stack.push("zoo")

while !stack.isEmpty {
    print(stack.pop())
}
  • 泛型类/结构/枚举

看罢了表测试结果,现在来探望实际画面展现吧。

有关知识

  • 泛型限定
  • where子句

图片 11

错误处理

enum MyError: ErrorType {
    case A
    case B
    case C
}
  • throw
  • throws / rethrows
  • do
  • catch
  • try
    示例:

// 定义一个遵循ErrorType协议的枚举
// 通过不同的case定义程序中可能出现的若干种异常状况
enum FractionError: ErrorType {
    case ZeroDenominator    // 分母为0
    case DivideByZero       // 除以0
}

class Fraction {
    private var _num: Int
    private var _den: Int

    var info: String {
        get {
            return _num == 0 || _den == 1 ? "\(_num)" : "\(_num)/\(_den)"
        }
    }

    // 如果一个方法抛出了异常 那么在声明方法时必须要写上throws关键字
    // throws关键字是提醒方法的调用者方法可能会出状况 调用时要写try
    init(num: Int, den: Int) throws {
        _num = num
        _den = den
        if _den == 0 {
            // 如果程序中出现问题就抛出错误(异常)
            // 被throw关键字抛出的必须是遵循ErrorType协议的东西
            throw FractionError.ZeroDenominator
        }
        else {
            simplify()
            normalize()
        }
    }

    func add(other: Fraction) -> Fraction {
        // 如果能够确保方法调用时不出异常那么可以在try关键字后加!
        // 这样就可以在不写do...catch的情况下调用可能出状况的方法
        return try! Fraction(num: _num * other._den + other._num * _den, den: _den * other._den)
    }

    func sub(other: Fraction) -> Fraction {
        return try! Fraction(num: _num * other._den - other._num * _den, den: _den * other._den)
    }

    func mul(other: Fraction) -> Fraction {
        return try! Fraction(num: _num * other._num, den: _den * other._den)
    }

    func div(other: Fraction) throws -> Fraction {
        if other._num == 0 {
            throw FractionError.DivideByZero
        }
        return try! Fraction(num: _num * other._den, den: _den * other._num)
    }

    func normalize() -> Fraction {
        if _den < 0 {
            _num = -_num
            _den = -_den
        }
        return self
    }

    func simplify() -> Fraction {
        if _num == 0 {
            _den = 1
        }
        else {
            let x = abs(_num)
            let y = abs(_den)
            let g = gcd(x, y)
            _num /= g
            _den /= g
        }
        return self
    }
}

// 运算符重载(为自定义的类型定义运算符)

func +(one: Fraction, two: Fraction) -> Fraction {
    return one.add(two)
}

func -(one: Fraction, two: Fraction) -> Fraction {
    return one.sub(two)
}

func *(one: Fraction, two: Fraction) -> Fraction {
    return one.mul(two)
}

func /(one: Fraction, two: Fraction) throws -> Fraction {
    return try one.div(two)
}

func foo() {
    // 如果能够保证代码不出错可以在try后面加!
    // 如果不确定代码是否出错可以在try后面加?
    // 需要注意的是有?的地方会产生Optional(可空类型)
    // 稍后可能还需要对可空类型进行拆封, 拆封方式有二: 
    //  1. 不安全的做法: xxx!
    //  2. 安全的做法: 用if let = xxx { }进行拆封
    let f1 = try? Fraction(num: 3, den: 0)
    let f2 = try? Fraction(num: 0, den: 9)

    if let a = f1, b = f2 {
        let f3 = a + b
        print(f3.info)
    }
    else {
        print("无效的分数无法进行加法运算")
    }
}

foo()


// 对于可能出状况的代码要放在do...catch中执行
// 在可能出状况的方法前还要写上try表示尝试着执行
// 如果在do中没有出现任何状况那么catch就不会执行
// 如果do中出现了状况代码就不会再向下继续执行而是转移到catch中
// 在do的后面可以跟上多个catch用于捕获不同的异常状况 但是最多只有一个catch会被执行
do {
    let f1 = try Fraction(num: 3, den: 4)
    let f2 = try Fraction(num: 0, den: 9)

    print(f1.info)
    print(f2.info)

    let f3 = f1 + f2
    print(f3.info)
    let f4 = f1 - f2
    print(f4.info)
    let f5 = f1 * f2
    print(f5.info)
    let f6 = try f1 / f2
    print(f6.info)
}
catch FractionError.ZeroDenominator {
    print("瓜西西的, 分母不能为0!!!")
}
catch FractionError.DivideByZero {
    print("卵球了, 除以0是不行的!!!")
}
catch {
    print("出错了! 我也不知道什么问题")
}

桂林景观,色彩过渡平滑倒影清晰,没有颗粒感。

边角知识

  • ARC

    通过一个示范来了解ARC:

import Foundation

class GrandFather {

}

class Father: GrandFather {

}

class Son: Father {

    override init() {
        // 可以调用Father中的初始化方法
        // 不能调用GrandFather中的初始化方法
    }
}

class Person {
    var name: String
    var age: Int

    // 指派构造器前面加上required可以将构造器指定为必要构造器
    // 所谓的必要构造器意味着子类也要提供一模一样的构造器
    // 指派构造器(designated)
    required init(name: String, age: Int) {
        print("创建一个人!")
        self.name = name
        self.age = age
    }

    // 便利构造器(convenience)
    convenience init() {
        self.init(name: "无名氏", age: 20)
    }

    deinit {
        print("人嗝屁了!")
    }
}

class Student: Person {
    var major: String

    required init(name: String, age: Int) {
        major = "未知"
        super.init(name: name, age: age)
    }

    convenience init(name: String, age: Int, major: String) {
        // 下面的语句必须写在调用自己的初始化方法之后否则major属性会被赋上不正确的值
        // self.major = major
        self.init(name: name, age: age)
        self.major = major
        // 初始化的第一阶段
        //  1. 初始化自己特有的属性
//        self.major = major
//        // 子类只能调用直接父类的构造器
//        // 子类构造器必须调用父类的非便利构造器(指派构造器)
//        // super.init()    // compiler error
//        //  2. 调用父类的初始化方法
//        super.init(name: name, age: age)
//        // 初始化的第二阶段
//        // 此处可以调用对象的方法因为对象已经完成了初始化
//        study()
    }

    func study() {
        print("\(name)正在学习.")
    }

    deinit {
        print("学生对象嗝屁了!")
    }
}

class Teacher: Person {


    deinit {
        print("老师对象嗝屁了!")
    }
}

//// 创建一个学生对象 然后用stu1去引用它 所以此时学生对象引用计数为1
//var stu1: Student? = Student()
//// 此处没有创建新的学生对象 原来的学生对象的引用计数+1
//var stu2 = stu1
//// 同上 原来的学生对象的引用计数+1
//var stu3 = stu2
//
//// 学生对象引用计数-1
//stu1 = nil
//// 学生对象引用计数-1
//stu2 = nil
//// 学生对象引用计数-1
//// 当学生对象引用计数为0时 ARC会自动清理内存释放学生对象
//// ARC即时性的内存清理 优于Java中的Garbage Collection(垃圾回收)
//stu3 = nil

// var stu1: Student? = Student()
// weak修饰的引用(弱引用)不会增加引用计数 默认是强引用(会增加引用计数)
// weak var stu2 = stu1
// weak var stu3 = stu2

// stu1 = nil
// 如果想释放内存 程序员可以手动将一个引用赋值为nil

// func foo() {
    // stu是一个局部变量/常量 在函数调用结束后局部变量就消失了
    // 所以学生对象的引用计数也就变成0了 所以会被ARC释放掉
    // let stu = Student()
    // print(stu)
// }

// foo()

// 栈 - FILO 先进后出的结构
// 创建任何子类对象的时候一定是先创建了父类对象
// var stu: Person = Student()
// 引用转移(会导致原来对象上的引用计数-1 新对象引用计数+1)
// stu = Teacher()
// stu = Person()

// Swift的自动释放池
// 通过向autoreleasepool函数中传入一个闭包来实现
// autoreleasepool { () -> () in
    // 自动释放池中的对象引用在池的边界会收到引用计数-1的消息
    // 将来做iOS开发时如果某个地方会创建很多的临时对象
    // 那么最好在此处设置一个自动释放池避免内存瞬时峰值过高造成闪退
    // let stu1 = Student()
    // let stu2 = stu1
// }
// 离开自动释放池时 stu1会收到引用计数-1消息 stu2也会收到引用计数-1消息
  • 双向关联关系
    倘程序中出现了仿佛和类似中双向关联关系
    必须使用中同样端设置为weak引用
    要不将会晤形成巡回引用导致ARC无法释放内存
    示例:

class Emp {
    // 推荐使用
    // 如果允许使用可空类型通常使用weak来破除循环引用
    // 如果员工关联的部门对象被释放了那么dept会被赋值为nil
    // 如果要继续给dept对象发消息程序不会崩溃
    // weak var dept: Dept?

    // 谨慎使用
    // 如果不允许使用可空类型就必须使用unowned来破除循环引用
    // 需要注意的是如果员工对象关联的部门对象被释放了
    // 如果还要通过员工对象去操作它所关联的部门对象将导致程序崩溃
    // EXC_BAD_ACCESS
    unowned var dept: Dept

    init(dept: Dept) {
        print("创建一个员工")
        self.dept = dept
    }

    deinit {
        print("销毁一个员工")
    }
}

class Dept {
    var manager: Emp?

    init() {
        print("创建一个部门")
    }

    deinit {
        print("销毁一个部门")
    }
}

func bar() {
    // let person = Person()
    let dept = Dept()
    let emp = Emp(dept: dept)
    dept.manager = emp
}

bar()
  • 正则表达式
  • 嵌套类型

图片 12

暗部细节清晰阳光照耀部分渐变自然。

图片 13

法国大街,建筑表面纹理清晰锐利,阳光穿透云层时清晰无渐变斑。

差色彩下的交融非常完美。

由此看来TCL
55N3底画面素质要那个好的,平时用来拘禁像、电视以及高清电影会有大好的画质表现。

标准图测 表现是

图片 14

从今业内侧视图来拘禁,这款电视的色情和绿色区分一般,蓝、粉和红分布非常准。

肉眼可见最特别暗部层次为10,亮部层次254。说明暗部细节显示能力还是得的。

于4K面板的来意下本机对密切小言的展示力量中规中矩。

图片 15

TCL
55N3电视机仍然采用TV+OS3.0系统,系统界面与前的TCL电视没有太怪区别,并支持壁纸更换功能,比如编辑就摘了一样布置比较吻合夏天底背景图。

图片 16

每当装方面提供展示、声音、网络与系装置,其中当系装置里可调节通用设置以及网更新,也可以变背景壁纸。网络端支撑有线和WIFI。画面的切实可行装要当广播视频时才会调动。

TCL
55N3电视主界面分为主页、影视、VIP、应用、生活、教育、K歌和戏等几乎单分页面。反野3大流畅无卡顿,界面也坏直观。

图片 17

每当画面设置及TCL
55N3提供了增长的选择项,包括黑电平、对比度、锐度、伽马、色温等大多独选项。

TCL
55N3外购买了5受预设效果,通过视频播放可以看出不同预设模式下画质的区分。

图片 18

录像播放以及购物体验

每当电影资源方面凭借腾讯影视等强势平台的入住,TCL
55N3电视来海量的电视剧、电影、综艺等剧目。

图片 19

广播时来4K、蓝光1080P、超清720P、高清480P和标清270P这几乎独分辨率可供应选择。

图片 20

4K视频模式下截图,可以望镜头清晰度还是杀正确的。

图片 21

对老来说会格外轻上手。

小内容也是必备的。

游玩与娱乐体验

图片 22

当还少不了天籁K歌,通过该APP可轻松实现K歌和音乐、MTV播放效果。

图片 23

K歌功能很圆,银条调节、音效调整完善。

图片 24

玩耍频道APP分类涵盖竞速、体感、益智、棋牌和小等大多独分类。

于是电视玩游戏很有益。

图片 25

只要对内置APP和使用企业还未满足的言辞,通过嵌入的电视机卫士可以由第三在设备安装APP程序。

假设出来头的语句还会由此手机对电视进行投屏。

图片 26

TCL
55N3电视机采用MS838C处理器,内置A53劫持构四核处理器,GPU也Mali-720四查核。运存方面为1.5GB
DDR4内存,8GB EMMC存储空间,内置蓝牙4.0术。

图片 27

迪拜夜景 H.265 TS 4K

图片 28

川菜美食 H.265 MP4 4K

图片 29

巴黎铁塔 H.265 MP4 4K

TCL 55N3电视对4K H.265视频发优质的解码能力。

立马款电视于1080P的H.264下发出特别好的播放能力,特别是1080P输出及4K面板时画面效果或特别科学的,而且会选外挂字幕、音轨等。

图片 30

美国队长3 H.264 1080P

图片 31

独立日2 H.264 1080P

图片 32

终结者5 H.264 1080P

TCL
55N3电视机要支撑VC1/H.264/H.265/MPEG4/WMV/AVS+/HDR10相当编码,音频方面支持WMA/AC3/EAC3/AAC/
DTS/Dolby Digital Plus,此外本机也支撑JPEG/BMP和PNG格式的图片浏览。

图片 33

TCL
55N3当画质上表现了端庄的力量,色彩精确性好,亮度控制能力出色。系统方面继续了T
V+OS
3.0之易用性和精扩展性,通过电视卫士软件而轻松安装第三着先后,无论是系统工具或媒体、购物乃至娱乐都能够轻轻松松运行。

每当外观设计达到TCL
55N3电视机采用经典曲面设计,4000R黄金曲率高度贴合人眼球弧度,降低观看疲劳,并提供舒适自然之视觉效果。当然TCL
55N3带的不仅仅是参数,4000R黄金曲率在适度去观赏时确实发生甚好之环抱感和临场感,对于好缠在电视圈电影的丁吧,TCL
55N3是慢不错的选取。

发表评论

电子邮件地址不会被公开。 必填项已用*标注