TCL 55N3电视评测

说从曲面电视,在故乡企业遭遇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是慢性不错的精选。

发表评论

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

网站地图xml地图