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

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

首先自定义一个toolbar

func addToolbar() -> UIToolbar {
var toolbar: UIToolbar = UIToolbar();
toolbar.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: 35)
toolbar.tintColor = UIColor.blue;
toolbar.backgroundColor = UIColor.gray;
var pre: UIBarButtonItem = UIBarButtonItem(title: “上一步”, style: UIBarButtonItemStyle.plain, target: self, action: #selector(textFieldpre))
var next: UIBarButtonItem = UIBarButtonItem(title: “下一步”, style: UIBarButtonItemStyle.plain, target: self, action: #selector(textFieldnext))

var space: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, …

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.

典型的声明为:

@property (strong,nonatomic) NSString *string;

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

class Shape {

    var name = “shape”

}

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

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

需要注意的几点:

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

weak var delegate: UITextFieldDelegate?

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背后的实例变量。

@interface SomeClass : NSObject {

  NSString *someString;

}

@property(nonatomic, copy) NSString* otherString;

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

A Swift property does not have a corresponding instance variable, and the backing store …

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语法,如调用一个方法:

println(“hello”)

也可以写成

 println “hello”

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

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

├── app #Android App目录
│   ├── app.iml
│   ├── build #构建输出目录
│   ├── build.gradle #构建脚本
│   ├── libs #so相关库
│   ├── proguard-rules.pro #proguard混淆配置
│   └── src #源代码,资源等
├── build
│   └── intermediates
├── build.gradle #工程构建文件
├── gradle
│   └── wrapper
│         └── gradle-wrapper.properties
├── gradle.properties #gradle的配置
├── gradlew #gradle wrapper linux shell脚本
├── gradlew.bat
├── LibSqlite.iml
├── local.properties #配置Androod SDK位置文件
└── settings.gradle #工程配置

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

include ‘:app’

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

buildscript {
    repositories {
        jcenter()//使用jcenter库
    }
    dependencies {
        // 依赖android提供的2.1.0的gradle build插件来编译android
        classpath ‘com.android.tools.build:gradle:2.1.0′

    …

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服务并启动起来,当收到请求后简单返回一条信息

local skynet = require “skynet”
local socket = require “socket”
local httpd = require “http.httpd”
local sockethelper = require “http.sockethelper”

skynet.start(function()
    local id = socket.listen(“0.0.0.0”, 8008)
    skynet.error(“Listen  port 8008″)
    socket.start(id , function(id, addr)
        socket.start(id)
        httpd.write_response(sockethelper.writefunc(id), 200,”this is a http response”);
        socket.close(id);
    end)
end)

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

[:01000001] LAUNCH logger
[:01000002] LAUNCH snlua bootstrap
[:01000003] LAUNCH snlua launcher
[:01000004] LAUNCH snlua cmaster
[:01000004] master listen socket 0.0.0.0:2013
[:01000005] LAUNCH snlua cslave
[:01000005] slave connect to master 127.0.0.1:2013
[:01000006] LAUNCH harbor 1 16777221
[:01000004] connect from …

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

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

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

systemcel enable nginx.service

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

/lib/systemd/system/

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

vim /lib/systemd/system/nginx.service

内容如下

[Unit]
Description=nginx
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target

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

保存退出。

2.设置开机启动

systemctl enable nginx.service

3.其它命令
启动nginx服务

systemctl start nginx.service

设置开机自启动

systemctl enable nginx.service

停止开机自启动

systemctl disable nginx.service

查看服务当前状态

systemctl status nginx.service

重新启动服务

systemctl restart nginx.service

查看所有已启动的服务

systemctl list-units –type=service

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 …

为iOS添加3D touch功能

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

UIApplicationShortcutIcon *firstItemIcon = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeAdd];
    UIMutableApplicationShortcutItem *firstItem = [[UIMutableApplicationShortcutItem alloc]initWithType:@”First” localizedTitle:@”第一个按钮” localizedSubtitle:nil icon:firstItemIcon userInfo:nil];

    UIApplicationShortcutIcon *secondItemIcon = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeShare];
    UIMutableApplicationShortcutItem *secondItem = [[UIMutableApplicationShortcutItem alloc]initWithType:@”Second” localizedTitle:@”第二个按钮” localizedSubtitle:nil icon:secondItemIcon userInfo:nil];

    application.shortcutItems = @[firstItem,secondItem];

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

-(void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler{

       if ([shortcutItem.type isEqual:@”First”]) {

        NSLog(@”第一个按钮事件”);

    }else if([shortcutItem.type isEqual:@”share”]){

        NSLog(@”第二个按钮事件 “);

    }
}

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

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

git clone https://github.com/DeskConnect/SBShortcutMenuSimulator.git

cd SBShortcutMenuSimulator

make

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

xcrun simctl …