Swifter - 100 个 Swift 必备 tips,作者[王巍](SWifter - 100个 Swift 必备 tips)。书买了很久了,25元比实体书便宜不少,而且收入基本上都归作者。学习完疯狂 Swift 讲义,再看看这个补充一下。

章节顺序可能与书不一致,全凭兴趣随意浏览,尤其是不太懂得方面。

##操作符
infix 表示一个中位操作符,前后都有输入。类似的还有 prefix 和 postfix。

associativity 定义了结合律

precedence 运算的优先级,Swift 中乘法和除法的优先级是150,加法和减法是140,这里定义160,就是高于普通的四则运算。

操作符定义在全局,不可滥用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//  main.swift
// Swift-test

import Foundation

struct Vector2D {
var x = 0.0
var y = 0.0
}

func +(left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y + right.y)
}

let v1 = Vector2D(x: 2.0, y: 3.0)
let v2 = Vector2D(x: 1.0, y: 5.0)
print(v1 + v2) // Swift_test.Vector2D(x: 3.0, y: 8.0)

infix operator +* {
associativity none
precedence 160
}

func +*(left: Vector2D, right: Vector2D) -> Double {
return left.x * right.x + left.y * right.y
}

print(v1 +* v2) // 17.0

随机数生成

创建一个 Range 的随机数的方法,方便以后复用。

Swift 支持 // MARK: 、// TODO:、// FIXME:等编译标记,方便分段,将一标签的形式显示在导航栏中,让程序更易读。

1
2
3
4
5
6
7
8
9
10
// MARK: 实现方法
func randomInRange(range: Range<Int>) -> Int {
let count = UInt32(range.endIndex - range.startIndex)
return Int(arc4random_uniform(count)) + range.startIndex
}

// TODO: 测试是否有效
for _ in 0...100 {
print(randomInRange(1...6))
}

断言

对于判断输入是否满足某种条件的运用情景,使用断言比 if 更合适。且在 Debug 编译是才有效,运行时不被编译执行,不会消耗运行时的性能。是非常合适的调试判断。

1
2
3
4
5
6
7
8
9
10
import Foundation

func convertToKelvin( celsius: Double) -> Double {
let AbsoluteZeroInCelsius = -273.15
assert(celsius > AbsoluteZeroInCelsius, "输入的摄氏温度不能低于绝对零度。")
return celsius - AbsoluteZeroInCelsius
}

let roomTemperature = convertToKelvin(27)
print(roomTemperature) // 300.15

自省

程序设计和人类哲学所面临的同一个重大课程就是解决“我是谁”。

isKindOfClass、isMemberOfClass、is

1
2
3
4
5
6
7
8
9
class ClassA: NSObject { }
class ClassB: NSObject { }

let obj1: NSObject = ClassA()
let obj2: NSObject = ClassB()

print(obj1.isKindOfClass(ClassA.self)) // true
print(obj2.isMemberOfClass(ClassA.self)) // false

属性观察

属性观察可以对当前类型内监视其属性的设定,并作出响应。

1
2
3
4
5
6
class MyClass {
    var date: NSDate {
        willSet {
        print("即将将日期从 \(date) 设定至 \(newValue)")
        }
        didSet {
        print("已经将日期从 \(oldValue) 设定至 \(date)")
        }
} init() { date = NSDate() }
}
let foo = MyClass() foo.date = foo.date.dateByAddingTimeInterval(10086)
// 输出 // 即将将日期从 2015-07-16 16:01:49 +0000 设定至 2015-07-16 18:49:55 +0000
// 已经将日期从 2015-07-16 16:01:49 +0000 设定至 2015-07-16 18:49:55 +0000

本节介绍了一些 Swift 和 Foundation Framework,基本是要求自己搜索学习完成的,最好是参考 Swift 教材系统看看。说实话老师一节课只是把大纲列一下,好多根本没有展开详细系统的讲,当然时间上也不允许。

  • 可选值和枚举
  • 数组、字典、区间
  • 数据类型
  • 方法
  • 属性
  • 初始化
  • AnyObject
  • 常用的方法和函数

看英文视频加中文字幕,效率也是蛮低的,下个星期六博览网的 iOS 极客班就开学了,希望能够认真高效投入更多时间去学习,一定要学好,找到开发的工作,圆毕业三年的一个梦。

Swift 学习还算顺利,MVC 模式也有所熟悉,就是独自开发和想法实现有困难,暂时停留在看懂和自己写一遍的水平。

还有就是玩手机,刷微博啥的超级浪费时间,因为这个不费脑,玩的也高兴,能够一天不吃饭,也不困,也停不下来。
但是学习或看书,就很费神,容易犯困,这个一定要克服,实在困了就休息10分钟,再继续。

New Calculator Demo

  • Applying MVC to the Calculator
  • enum
  • Simple initializer
  • Returning an Optional
  • Dicionary
  • Tuples

源码如下,待修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//
// CalculatorBrain.swift
// Calculator
//
// Created by Will Ge on 7/11/15.
// Copyright © 2015 gewill.org. All rights reserved.
//

import Foundation

class CauculatorBrain
{
// 定义一个枚举类型,来分类表示输入的:运算数、一元运算和二元运算
enum Op {
case Operand(Double)
case UnaryOperation(String, Double -> Double)
case BinaryOperation(String, (Double, Double) -> Double)
}

// 定义一个数组来储存所有输入
var opStack = [Op]()

// 定义已知运算符
var knownOps = [String:Op]()

// 初始化已知运算符
init() {
knownOps["+"] = Op.BinaryOperation("+", +)
knownOps["−"] = Op.BinaryOperation("−") {$1 - $0}
knownOps["×"] = Op.BinaryOperation("×", *)
knownOps["÷"] = Op.BinaryOperation("÷") {$1 / $0}
knownOps["√"] = Op.UnaryOperation("√", sqrt)
}

// 定义一个函数,把输入递归取出
func evaluate(ops: [Op]) -> (result: Double?, remainingOps:[Op]) {
if !ops.isEmpty {
var remainingOps = ops
let op = remainingOps.removeLast()
switch op {
case.Operand(let operand):
return (operand, remainingOps)
case .UnaryOperation(_, let operation):
let operandEvaluation = evaluate(remainingOps)
if let operand = operandEvaluation.result {
return (operation(operand), operandEvaluation.remainingOps)
}
case .BinaryOperation(_, let operation):
let op1Evaluation = evaluate(remainingOps)
if let operand1 = op1Evaluation.result {
let op2Evaluation = evaluate(remainingOps)
if let operand2 = op2Evaluation.result {
return (operation(operand1, operand2), op2Evaluation.remainingOps)
}


}

}
}
return (nil, ops)
}

func evaluate() -> Double? {
let (result, remainder) = evaluate(opStack)
print("\(opStack) = \(result) with \(remainder) left over")
return result

}

// 运算数
func pushOperand(operand: Double) -> Double? {
opStack.append(Op.Operand(operand))
return evaluate()
}

// 运算符
func performOperation(symbol: String) -> Double? {
if let operation = knownOps[symbol] {
opStack.append(operation)
}
return evaluate()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//
// ViewController.swift
// Calculator
//
// Created by Will Ge on 6/28/15.
// Copyright © 2015 gewill.org. All rights reserved.
//

import UIKit

class ViewController: UIViewController {


@IBOutlet weak var history: UILabel!

@IBOutlet weak var display: UILabel!


var userIsInTheMiddleOfTypingANumber: Bool = false

var brain = CauculatorBrain()

@IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle!
if userIsInTheMiddleOfTypingANumber{
display.text = display.text! + digit
} else {
display.text = digit
userIsInTheMiddleOfTypingANumber = true
}

print("digit = \(digit)")
}



@IBAction func enter() {
userIsInTheMiddleOfTypingANumber = false
if let result = brain.pushOperand(displayValue) {
displayValue = result
} else {
displayValue = 0
}
print("pushOperand = \(displayValue)")

}

@IBAction func operate(sender: UIButton) {

if userIsInTheMiddleOfTypingANumber {
enter()
}
if let operation = sender.currentTitle {
print("\(operation)")
}
}



var displayValue: Double{
get {
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
}
set {
display.text = "\(newValue)"
userIsInTheMiddleOfTypingANumber = false
}
}
}


我的需求: www.gewill.org 跳转到 gewill.org。

使用万网域名服务提供的 DNS 解析需要备案才能实现301跳转,所以之前使用 DNSPOD 的服务,但是不知为何竟失效了,gewill.org 能打开,www.gewill.org打不开了。换了其他的也都不行,dig 也是对的。

Google Github Pages 的相关信息,发现官方帮助文档就有简单是实现方案:

Configuring a www subdomain

If you configure both an apex domain (e.g. example.com) and a matching www subdomain (e.g. www.example.com), GitHub’s servers will automatically create redirects between the two.

For example:

If your CNAME file contains example.com, then www.example.com will redirect to example.com.
If your CNAME file contains www.example.com, then example.com will redirect to www.example.com.”

DNS 同时 CNAME 顶级域名和 WWW,然后在 Github CNAME文件中添加偏好的一个。

虽然之前有看过,一则英文看了只解一二,二则当时对于 DNS 和网站都刚刚接触。我学习新鲜东西节奏还是太慢,以后还要多思考,多与人交流。官方文档还是最简洁正确的。

继续 DEMO: Calculator

Swift 能类型推断

自动布局:

  • Pin: Spacing to nearest neighbor, Equal Widths, Equal Heights
  • Resolve Auto Layout Issues: Clear Constraints

87果然是个神奇的数字,我之前没有对齐就开始 Pin,始终无法得到“Add 87 Constraints”,自然没有得到自动对齐的理想布局。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//
// ViewController.swift
// Calculator
//
// Created by Will Ge on 6/28/15.
// Copyright © 2015 gewill.org. All rights reserved.
//

import UIKit

class ViewController: UIViewController {


@IBOutlet weak var display: UILabel!

var userIsInTheMiddleOfTypingANumber: Bool = false

@IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle!
if userIsInTheMiddleOfTypingANumber{
display.text = display.text! + digit
} else {
display.text = digit
userIsInTheMiddleOfTypingANumber = true
}

print("digit = \(digit)")
}

var operandStack = Array<Double>()

@IBAction func enter() {
userIsInTheMiddleOfTypingANumber = false
operandStack.append(displayValue)
print("operandStack = \(operandStack)")

}

@IBAction func operate(sender: UIButton) {
let operation = sender.currentTitle!
if userIsInTheMiddleOfTypingANumber {
enter()
}
switch operation {
case "×": performOperation { $0 * $1 }
case "÷": performOperation { $1 / $1 }
case "+": performOperation { $0 + $1 }
case "−": performOperation { $1 - $0 }
case "√": performOperation1 { sqrt($0) }
default: break
}
}

func performOperation(operation: (Double, Double) ->Double) {
if operandStack.count >= 2 {
displayValue = operation(operandStack.removeLast(), operandStack.removeLast())
enter()
}
}

func performOperation1(operation: Double ->Double) {
if operandStack.count >= 2 {
displayValue = operation(operandStack.removeLast())
enter()
}
}


var displayValue: Double{
get {
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
}
set {
display.text = "\(newValue)"
userIsInTheMiddleOfTypingANumber = false
}
}
}

MVC:

  • 各个模块之间的含义
  • 模块之间的通信有无
  • 模块之间的控制关系

MVC

iTunes U 课程地址:iTunes U/Developing iOS 8 Apps Swift

CS193P 课程地址:CS193P iPhone Application Development

字幕下载:https://github.com/x140yu/Developing_iOS_8_Apps_With_Swift

课程不用多介绍,下面直接进入笔记:

iOS 仍是一个 Unix 系统,添加了很多移动方面的模块和优化。

Cocoa Touch 是本课的重点,如涉及 Media 等主题需要自行找资料深入学习。

自己动手写代码,绝不复制粘贴别人的代码。

接下来是 DEMO:Calculator

蓝线是自动布局时的好帮手。

Storyboard 是正方形,自动布局就是实现对真实屏幕比例添加挤压效果或规则,已完成适配。

Trailing Margin (尾部到边框)
Leading Margin (头部到边框)
Top (顶部)

Outline mode (大纲模式)

? 表示 Optional,有两种情况:

  • nil : 值缺失
  • 有值

源码如下:

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

// ViewController.swift


import UIKit

class ViewController: UIViewController {


@IBOutlet weak var display: UILabel!

var userIsInTheMiddleOfTypingANumber: Bool = false

@IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle!
if userIsInTheMiddleOfTypingANumber{
display.text = display.text! + digit
} else {
display.text = digit
userIsInTheMiddleOfTypingANumber = true
}

print("digit = \(digit)")
}

}

Windows 进阶的学习方法博览网Windows专家管理与排错第一讲,讲师彭爱华,其中关于学习方法,尤其是少下载,贪多嚼不烂,击中我要害。虽然讲的是 Windows,但方法还是通用的,以下为学习笔记。

##良好的学习习惯

  • 养成阅读英文资料的习惯
  • 少下载、勤阅读、多动手
  • 知识的整理,善于写博客,多分享
  • 基础知识要扎实,平台和核心领域知识

##关于提问

  • 必须经过仔细思考,才提问,切忌不动脑子
  • 提问不是为了解决眼前问题,而是获得启发
  • 好的问题时带有启发性的,衍生性的
  • 能否整理经典的问题,沉淀下来?(写博客)

##常见弊病

  • 盲目的跟风式学习
  • 吃着碗里,想着锅里
  • 理论不联系实际
  • 不能高效利用资源

原文链接 Minimalism in Web design: past and future,偏软文但是内容是好的。并非全文翻译,取其要旨。大约翻译了4个小时,算是通篇读懂了,还多亏了 Google 的翻译,下次提取大纲好了。

极简主义(Minimalist)以其永恒的优雅和清晰明确的内容显示,是网页设计最为长久的视觉架构之一。

Beatbox

以下为几个网页设计中极简主义的几个原则:

少即是多(Less is More):简史和解构

和平面设计的起源类似的,极简主义在网页设计是通过减法做雕塑的一种最纯净方式–最完美的实现不是没有元素可以添加,而是没有元素可以删去。尽管目前极简主义围绕着负空间和黑色字体-即是极简主义的核心-该风格通过任何手段已达到最低来定义自己。

最小化网页设计基于以下基础,并全部以网站内容为设计中心:

  • 负空间- 通常是指白色空间,负空间简单来说就是在设计中没有被使用的空间。 通常极简主义设计中,你将会看到负空间被充满活力的颜色填充(或者就是简单的留白/灰/黑)。
  • 高清照片 - 因为更少的界面修饰物,用户可以更好地欣赏高清照片的惊艳的细节。通常照片上覆盖幽灵按钮(白色轮廓的按钮)和粗体的文字排版。
  • 有特色的排版 - 不管手写体的标题或是简洁无衬字体的正文,字体方面的极简主义设计少数的领域之一,可以包含少许修饰。如果你感兴趣,可以看一下这些优秀的字体集 20 minimalist typefaces
  • 鲜明的对比 - 对比是通过独立设计元素组合而成。例如在一张黑色图片上使用72点阵的粗体字。又或者白色手写字体用在浅绿色的单色背景上。
  • 简洁的导航栏 - 最复杂的导航栏带有下拉菜单(即使没有没有二级菜单弹出)。更常见的是几个顶部水平的导航栏,甚至汉堡菜单。
  • 视觉上的平衡 - 网页设计对于人眼来说,视觉平衡通过一个明确的视觉层次,一致的对准和定位,以及灵活的利用对称和不对称来实现。

现在你可能觉得极简主义很容易 - 毕竟更少元素的使用意味着更少工作量,对吧? 可事实上正相反:以为你要受限于少量的元素,而这些元素必须是经过细致的关注下和有目标性低挑选出来的。粗糙地使用极简主义是很容易,但正确的使用则不然。

简洁的设计是故意而为之的。它是条从一个框架的不必要的元素只留下所需要的方法。多数简洁的网站设计不会包含了很多色彩(调色板往往只有一种主色),纹理或形状或类似颜色。

极简主义行之有效是因为,它做了所有设计都应该做的 - 把重心放在内容上。

极简主义将继续成为一个受欢迎的选择,但很可能演变成一种少一点鲜明对比的风格。正如我们所看到的技术,如“扁平设计”演变成“全平话设计”,极简主义设计将更丰富(更可用),UI 设计师尝试纹理、颜色和效果 - 以及不在使用对称的图案。

以下让我们看看一些进化的元素:

  • 最小化质感纹理(Minimal texture)
    Minimal texture
  • 反转颜色(Reverse colors)
    Reverse colors
  • 更多互动特效(More interactive effects)
  • 移除对称(Move away from symmetry)
    Move away from symmetry
  • 提高可用性(Improved usability)
    Improved usability

结论

极简主义不仅仅是白色的空间和尽可能使用最少的元素。极简主义哲学的核心是在强调内容。减少元素,并使有大量的负空间追求一个结果 - 他们尽量减少干扰,使用户可以只专注于真正重要的(内容)。

千万不要误解为极简的目的本身,或者你也可能发现自己删除了不可替代的元素。这不是通过减法进行雕塑(代指设计) - 这只是减法。

可以下载 The Curated Collection of Design Techniques: Cards & Minimalism 学习更多极简主义的网页设计内容。

添加分享

###方法一:原生分享

添加分享按钮代码, Hexo 文件夹下/theme/next/layout/_macro/post.swig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<html xmlns:wb="http://open.weibo.com/wb">

<script src="http://tjs.sjs.sinajs.cn/open/api/js/wb.js" type="text/javascript" charset="utf-8"></script>

<wb:share-button appkey="2407521490" addition="simple" type="button"></wb:share-button>


<a href="https://twitter.com/share" class="twitter-share-button" data-via="gewillorg" data-size="large" data-count="none">Tweet</a>

<script>
!function(d,s,id){
var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';
if(!d.getElementById(id)){
js=d.createElement(s);
js.id=id;js.src=p+'://platform.twitter.com/widgets.js';
fjs.parentNode.insertBefore(js,fjs);
}
}
(document, 'script', 'twitter-wjs');
</script>

###方案二:ShareThis 定制

更加统一优美的解决方案,有个各种样式可选,非常方便。
稍后我再进行定制,最好是默认黑色,点击激活时恢复彩色。

默认有添加后缀在你的网址,去除方法如下 doNotHash: ture,详情参考:CopyNShare Settings

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

<script type="text/javascript">var switchTo5x=true;</script>
<script type="text/javascript" src="http://w.sharethis.com/button/buttons.js"></script>
<script type="text/javascript">stLight.options({
publisher: "7fb5f31a-b8e7-4aa1-a6eb-9aac8b9b13f0", doNotHash: ture, doNotCopy: false, hashAddressBar: true});
</script>

<span class='st_sina_large' displayText='Sina'></span>
<span class='st_twitter_large' displayText='Tweet'></span>
<span class='st_facebook_large' displayText='Facebook'></span>
<span class='st_googleplus_large' displayText='Google +'></span>
<span class='st_pinterest_large' displayText='Pinterest'></span>
<span class='st_tumblr_large' displayText='Tumblr'></span>
<span class='st_reddit_large' displayText='Reddit'></span>


不蒜子统计

不蒜子”与百度统计谷歌分析等有区别:“不蒜子”可直接将访问次数显示在您在网页上。

添加统计代码, Hexo 文件夹下/theme/next/layout/_partials/footer.swig

Sketch 进阶与技巧

一:App 设计标准

  1. Point (PT)
  • Point (PT) - 表示独立于设备的
    像素点 (在 Android 上叫 DP)
  1. Point (PT)和像素的关系
  • 像素点: 相同 Point 的按钮, 在 Retina 屏幕上的图片像素是非Retina屏幕的两倍
  • 通过 @2x 后缀标识
  1. iPhone 分辨率的终极指南

  2. iOS App 设计尺寸标准

0%