swift:为键盘添加自定义工具栏

有时候需要为键盘添加一些自定义的按键,如“上一步”,“下一眇”,“完成” 按钮等。

首先自定义一个toolbar

以及对应的响应方法

 

然后以UITextField初始化时加上

这样就可以为为键盘加上自定义行为了。

 

 

Swift学习: 从Objective-C到Swift

这篇文章是自己学习Swift的笔记与深化。希望这篇文章能够帮助已经有Objective-C经验的开发者更快地学习Swift。同时也品味到Swift的精妙之处。

文章组织脉络:

从Objective-C到Swift的语法差异。我们熟悉的Objective-C特性在Swift中如何展现。
从Objective-C到Swift的进步改进。研究对比Swift在安全性,易用性上的提升,给我们带来的新编程范式。

目录:

1.属性(property)和实例变量(instance variable)

2.控制流

3.函数

4.类与初始化(Initializers)

5.枚举与结构体

6.协议(Protocols)

7.Swift与Cocoa

8.总结

1.属性(property)和实例变量(instance variable)

Objective-C property in Swift world

在Cocoa世界开发的过程中,我们最常打交道的是property.

典型的声明为:

而在Swift当中,摆脱了C的包袱后,变得更为精炼,我们只需直接在类中声明即可。

注意到这里,我们不再需要@property指令,而在Objective-C中,我们可以指定property的attribute,例如strong、weak、readonly等。

而在Swift的世界中,我们通过其他方式来声明这些property的性质。

需要注意的几点:

strong: 在Swift中是默认的
weak: 通过weak关键词申明

readonly,readwrie 直接通过声明变量var,声明常量let的方式来指明
copy 通过@NSCopying指令声明。

值得注意的是String、Array和Dictionary在Swift是以值类型(value type)而不是引用类型(reference type)出现,因此它们在赋值、初始化、参数传递中都是以拷贝的方式进行(简单来说String,Array,Dictionary在Swift中是通过struct实现的)

延伸阅读:Value and Reference Types

nonatomic,atomic 所有的Swift properties都是nonatomic。但是我们在线程安全上已经有许多机制,例如NSLock、GCD相关API等。个人推测原因是苹果想把这一个本来就用的很少的特性去掉,线程安全方面交给平时我们用的更多的机制去处理。

然后值得注意的是,在Objective-C中,我们可以跨过property直接与instance variable打交道,而在Swift是不可以的。

例如:我们可以不需要将someString声明为property,直接使用即可。即使我们将otherString声明为property,我们也可以直接用_otherString来使用property背后的实例变量。

而在Swift中,我们不能直接与instance variable打交道。也就是我们声明的方式简化为简单的一种,简单来说在Swift中,我们只与property打交道。

A Swift property does not have a corresponding instance variable, and the backing store for a property is not accessed directly

小结

因此之前使用OC导致的像巧哥指出的开发争议就不再需要争执了,在Swift的世界里,我们只与property打交道。
并且我们在OC中init和dealloc不能使用属性self.property = XXX来进行设置的情况得以解决和统一。

(不知道这一条规定,在init直接用self.property = value 的同学请自觉阅读iOS夯实:内存管理)

:)

个人觉得这看似小小一点变动使Swift开发变得更加安全以及在代码的风格更为统一与稳定。

Swift property延伸:

Stored Properties和Computed properties

在Swift中,property被分为两类:Stored Properties和Computed …

dispatch_once 引起的死锁

今天遇到一个使用dispatch_once引起的问题,在shareInstance的dispatch_once里初始化的同时也调用了别的类的dispatch_once方法初始化,而在别的dispatch_once方法又调用本类的dispatch_once,莫名导致程序死锁。

在google后得知在初始化未完成时相互的调用会造成死锁,也就是A->B->C->A的一个调用过程,,会导致整体链表无限增长,造成永久性死锁。

开始学习swift

        好几个月没写博客了,一部分原因是因为前阵子工作很忙,还有是因为房子的原因,现在房子问题基本搞定,也算是少了一份烦心事。
        最主要的原因是自己变懒了,不想多抽出点时间去学新的东西。现在工作不忙,自己坚持每月更新一两篇新东西。
        计划这一年内学习一门新的计算机语言,想想这都到十月了还没有开始学,心里也狠狠地鄙视了一下自己。
于是选定了swift语言来学习,作为一个ios程序员,一真用oc开发,到现在也还没有学习swift,不知道这算不算一件打脸的事情,总之现在开始学习了。
        由于自己熟悉ios开发,也熟悉lua等一些脚本语言,所以swift学习起来并不困难。但swift看似一个脚本语言,但其实不然,swift是一个强类型和编译型语言,它之所以能够进行类型判断,是因为它是和oc类型的运行时机制吧。但swift还上有很多脚本语言的特点,如闭包等等,这将是一个很强大特点。
一些粗浅的想法,往后写些更全面和深入一点的学习心得。

关于gradle

什么是gradle
如果从eclipse转到android studio上开发android,首先遇到的一个问题是是gradle,发现和一切和eclipse都不一样了,没错,因为android studio是基于gradle来构建项目的。
Gradle和C语言的make,以及eclipse使用的ant一样,是一种项目自动化构建工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,但是要比ANT使用XML构建配置要灵活的多。在编写配置时,你可以像编程一样灵活(比如加入各种条件判断),Gradle是基于Groovy的DSL语言。

什么是Groovy
Groovy是Java平台上设计的面向对象编程语言。这门动态语言拥有类似Python、Ruby和Smalltalk中的一些特性,可以作为Java平台的脚本语言使用(也运行于Java虚拟机中)。

Groovy的语法与Java非常相似,以至于多数的Java代码也是正确的Groovy代码。Groovy代码动态的被编译器转换成Java字节码。由于其运行在JVM上的特性,Groovy可以使用其他Java语言编写的库。
可以理解为Groovy是基于java平台的脚本语言,但它有自己定义的一套语法,很多时候也兼容java语法,如调用一个方法:

也可以写成

等等,grade里很多都使用这种形式来调用方法,方法的定义和调用像ruby语言。

android studio的gradle
Android Studio的工程目录结构通常是这样的:

首先是settings.gradle,用于配置project,通常一个project有一个或者多个module(在eclipse下称为project),在这个文件下,把所有要加入构建的module都在这个文件里加入进来,,比如这里包含一个:app module

和settings.gradle在同一目录下的build.gradle是一个顶级的build配置文件,在这里可以为所有project以及module配置一些常用的配置。

在这个文件中的配置,整个项目的module都起作用。
grade也称为一个编程框架,是基于插件的编译的,也就是说当你编译java项目时,用java插件,编译android项目时,自然也用android的插件,这里的

就是配置gradle编译项目时用android的gradle插件,注意这里是插件的版本,并非gradle的版本,这个版本通常是和android studio的版本相同(但也并非总是相同)。

各module下的build.gradle
除了一个顶级的的build.gradle文件之外,所有的module(如app)下也都会有一个build.gradle文件。
在这个文件中的配置,只对所在的module起作用,对其它的module不起作用。

 

开头第一行

这表示该module是一个app module,应用了com.android.application插件,如果是一个android library,那么这里应该

其次是基于哪个SDK编译,这里是API LEVEL,是21,buildToolsVersion是基于哪个构建工具版本进行构建的。defaultConfig是默认配置,如果没有其他的配置覆盖,就会使用这里的。看其属性的名字就可以知道其作用,比如applicationId是配置包名的,versionCode是版本号,versionName是版本名称等。

buildTypes是构建类型,常用的有release和debug两种,可以在这里面启用混淆,启用zipAlign以及配置签名信息等。

dependencies就不属于Android专有的配置了,它定义了该module需要依赖的jar,aar,jcenter库信息。

 gradle-wrapper.properties文件
这个文件是配置gradle的版本以及存放位置,通常会存放在系统用户目录下的.gradle/wrapper/dists文件夹下对应的版本号目录里,android studio会先去检查这个目录下有没有文件中配置的版本,如果找不到匹配的版本,就会自己去下载gradle,这也是android studio有时候很慢的原因,因为它在下载gradle,如果本地有gradle的版本,可以在这里手动配置上,从而可以关掉android studio的自动下载(offline模式),提高速度。

 

linux学习杂记

最近工作上不忙,抽空重新学习了linux,以前对于linux,是东一命令西一脚本,够用就行,从来没有系统地学过linux,经过这一番学习,从linux基本命令,到内核的基本运行原理,开机启动原理,磁盘存储,网络通讯,软件安装及管理等从底层往上的系统学习后,以及手动编译LFS,自认为对linux有了重新的认识,但觉得对linux的了解又才刚刚入门,对于想玩转linux,还有很长一段路要走。

linux真是一个强大的系统,一个迷你版本的linux系统只需5M大小就可以运行起来,外围是一堆模块以及硬件驱动构成了linux的内核,内核又对外提供事件以及程序接口与外部应用程序通讯。

shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行,是一个命令解释器。另外,shell编程语言具有普通编程语言的很多特点,用这种编程语言编写的shell程序与其他应用程序具有同样的效果。

爱上linux是必然的,虽然很多东西还是不甚理解,目前工作也很少涉及服务器管理,但这是一个值得花精力和时间,衣带渐宽终不悔,为伊消得人憔悴的东西。

nginx反向代理skynet

nginx作为一个web服务器和反向代理服务器,能够使web服务器和逻辑单独分离,也可以作为负载均衡服务器。基于这些优点,可以使用nginx反向代理skynet,即skynet监听本地的一个socket端口,收到请求后处理逻辑,然后返回结果。nginx和skynet可以同一台机器上,也可以在不同的机器上。

新建一个skynet服务并启动起来,当收到请求后简单返回一条信息

启动起来后log如下,监听8008端口

nginx配置

将所有以server为uri的请求全部转向skynet的8008端口上。

重新加载nginx,用浏览器打开http://localhost:8020/server会收到一条信息显示在浏览器上。

skynet已经自带了一个simpleweb例子,可以直接使用,还有一些解析header的代码,自己可以修改体验下skynet作为web服务器使用。

centos 7.x编写开机启动服务

centos 7以上是用Systemd进行系统初始化的,Systemd 是 Linux 系统中最新的初始化系统(init),它主要的设计目标是克服 sysvinit 固有的缺点,提高系统的启动速度。关于Systemd的详情介绍在这里。

Systemd服务文件以.service结尾,比如现在要建立nginx为开机启动,如果用yum install命令安装的,yum命令会自动创建nginx.service文件,直接用命令

设置开机启动即可。
在这里我是用源码编译安装的,所以要手动创建nginx.service服务文件。
开机没有登陆情况下就能运行的程序,存在系统服务(system)里,即:

1.在系统服务目录里创建nginx.service文件

内容如下

[Unit]:服务的说明
Description:描述服务
After:描述服务类别
[Service]服务运行参数的设置
Type=forking是后台运行的形式
ExecStart为服务的具体运行命令
ExecReload为重启命令
ExecStop为停止命令
PrivateTmp=True表示给服务分配独立的临时空间
注意:[Service]的启动、重启、停止命令全部要求使用绝对路径
[Install]运行级别下服务安装的相关设置,可设置为多用户,即系统运行级别为3

保存退出。

2.设置开机启动

3.其它命令
启动nginx服务

设置开机自启动

停止开机自启动

查看服务当前状态

重新启动服务

查看所有已启动的服务

4.Systemd 命令和 sysvinit 命令的对照表

Sysvinit 命令
Systemd 命令
备注

service foo start
systemctl start foo.service
用来启动一个服务 (并不会重启现有的)

service foo stop
systemctl stop foo.service
用来停止一个服务 (并不会重启现有的)。

service foo restart
systemctl restart foo.service
用来停止并启动一个服务。

service foo reload
systemctl reload foo.service
当支持时,重新装载配置文件而不中断等待操作。

service foo condrestart
systemctl condrestart foo.service
如果服务正在运行那么重启它。

service foo status
systemctl status foo.service
汇报服务是否正在运行。

ls /etc/rc.d/init.d/
systemctl list-unit-files –type=service
用来列出可以启动或停止的服务列表。

chkconfig foo on
systemctl enable foo.service
在下次启动时或满足其他触发条件时设置服务为启用

chkconfig foo off
systemctl disable foo.service
在下次启动时或满足其他触发条件时设置服务为禁用

chkconfig foo
systemctl is-enabled foo.service
用来检查一个服务在当前环境下被配置为启用还是禁用。

chkconfig –list
systemctl list-unit-files –type=service
输出在各个运行级别下服务的启用和禁用情况

chkconfig foo –list
ls /etc/systemd/system/*.wants/foo.service
用来列出该服务在哪些运行级别下启用和禁用。

chkconfig foo –add
systemctl daemon-reload
当您创建新服务文件或者变更设置时使用。

telinit 3
systemctl isolate multi-user.target (OR systemctl isolate runlevel3.target OR telinit 3)
改变至多用户运行级别。

5.Sysvinit 运行级别和 systemd 目标的对应表

Sysvinit 运行级别
Systemd 目标
备注

0
runlevel0.target, poweroff.target
关闭系统。

1, s, single
runlevel1.target, …

为iOS添加3D touch功能

一、为ios添加3D Touch 的实现
1.在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法中添加以下代码 :

2.实现这个方法-(void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler 在这个方法中处理添加和分享的事件,代码如下:

二、通过模拟器进行调试
使用SBShortcutMenuSimulator来配置模拟器,地址https://github.com/DeskConnect/SBShortcutMenuSimulator,使模拟器支持3D Touch,

在终端中按顺序输入以下命令:

然后打开刚才写好的程序 运行一下打开模拟器,再去终端中按顺序输入一下命令:

注意: ‘com.apple.mobilecal’ ”里边写的是自己项目的Bundle identifier. 
这行命令就是要让模拟器显示出3D Touch,每次想要显示快速入口只要重复
echo ‘com.apple.mobilecal’ | nc 127.0.0.1 8000
即可

我测试的时候crashed了,报了如下错误

google了下,发现我的模拟器ios版本是9.2,需要换成9.1,需要下载ios9.1的sdk包,打开模拟器Hardware->Devices->Manage Device
点击+按钮,选择Add Simulator。在iOS version 那一行选择ios9.1,如果没有9.1,就选择去下载一个9.1。

下载完成后,再次运行,成功显示定义的两个按钮

centos为某一网卡设置固定ip

编辑 /etc/sysconfig/network-scripts/目录下ifcfg-(网卡名称) 的文件,如 ifcfg-eth0,修改参考如下:

重启网络服务生效

/etc/init.d/network restart