0%

开发环境搭建Hello World

  1. 安装Xcode

  2. File => New => Playground

     import UIKit
     var str = "Hello World,yahue"
    

在Playground 就可以看到Hello World,yahue

数据类型

内置类型:

swift内置类型非常丰富,列举几个

int:整型

  1. 长度和运行平台对应

    32位平台=>Init32
    64位平台=>Init64

  2. 长度范围:-2,147,483,648~2,147,483,647

UInt 无符号整型

浮点数

Double

表示64位浮点数。当你需要存储很大或者很高精度的浮点数时请使用此类型。

Float

表示32位浮点数。精度要求不高的话可以使用此类型。

Double精确度很高,至少有15位数字,而Float最少只有6位数字。选择哪个类型取决于你的代码需要处理的值的范围。

布尔值

Boolean 值有true和false

… 不一一介绍内置类型了

类型别名

对当前类型定义一个别名
如:
import Cocoa

typealias meter = Int
var distance: meter = 10086
print(distance)

playground 执行以上程序,输出结果为:

10086

类型安全

swift是个强类型的语言,声明之后不能修改类别
如以下代码:
import Cocoa

var a = 10010
a = "10086"
print(a)

在xcode中会直接提示错误

error: cannot assign value of type 'String' to type 'Int'
a = "10086"

类型申明

类型声明的方式有多重
###var 声明一变量

变量是一种使用方便的占位符,用于引用计算机内存地址。

如代码:

import Cocoa

var var1 = 421
print(var1)

var var2:Float

var2 = 3.1415926
print(var2)

输出:
421
3.1415926
###let 声明一个常量

申明方式和var一样,但是意义不一样
常量一旦设定,在程序运行时就无法改变其值。

可选类型的申明

可选(Optional)类型,用于处理值缺失(值为null)的情况。

申明方式:

var optionalInteger: Int?
var optionalInteger: Optional<Int>

代码示例:
import Cocoa

var vars1:String? = nil

if vars1 != nil {
    print(vars1)
}else{
    print("字符串为 nil")
}

运行结果:

字符串为 nil

强制获取值:

import Cocoa

var vars1:String? = nil
vars1="hello http://blog.yahui.wang"
  print(vars1)
if vars1 != nil {
    print(vars1!) //强制获取值
}else{
    print("字符串为 nil")
}

执行结果:

Optional("hello http://blog.yahui.wang")
hello http://blog.yahui.wang

自动解析值

!?

?

上面我们说到 这两种声明方式是一样的
var optionalInteger: Int?
var optionalInteger: Optional
查看Optional的文档可以知道Optional只是一个枚举
enum Optional : LogicValue, Reflectable
也就是说当你使用var varS: String?的时候 你是“申明了一个Optional类型值,它可能包含一个String值,也可能什么都不包含”
不要以为是 “我声明了一个Optional的String值”

!

一下代码意义一样
var optionalInteger: Int! //!相当于下面这种写法的语法糖
var optionalInteger: ImplicitlyUnwrappedOptional

Implicitly Unwrapped Optionals, 直译就是隐式拆包的Optional,也就是说每次使用这个值的时候都会自动在变量后面加上个!拆包,当值为nil的时候 肯定会报错

那么!大概也有两种使用场景
1.强制对Optional值进行拆包(unwrap)
2.声明Implicitly Unwrapped Optionals值,一般用于类中的属性

执行流控制

条件语句

if … else

switch

循环

for

for in

while

repeat while

循环控制

continue

break

fallthough

字符串和字符

数组

字典

函数

函数

闭包

枚举

结构体和类

共同点

  1. 定义属性用于存储值
  2. 定义方法用于提供功能
  3. 定义附属脚本用于访问值
  4. 定义构造器用于生成初始化值
  5. 通过扩展以增加默认实现的功能
  6. 符合协议以对某类提供标准功能

类还有如下的附加功能:

  1. 继承允许一个类继承另一个类的特征
  2. 类型转换允许在运行时检查和解释一个类实例的类型
  3. 解构器允许一个类实例释放任何其所被分配的资源
  4. 引用计数允许对一个类的多次引用

属性

存储属性

延迟存储属性

实例化变量

计算属性和只读计算属性

只有 getter 没有 setter 的计算属性就是只读计算属性。

属性观察器

全局变量和局部变量

类型属性

获取和设置类型属性的值

方法

下标脚本

继承

构造过程和拆构过程

构造过程是类初始化
拆构过程是类被释放时执行

可选链

ARC 自动引用计数

类型转换

扩展

协议

访问控制

泛型

golang中如果你定了一个struct T,有个可以定义一个接收者为T的函数来使T更强大

但是T作为receiver有两种形式:

一种是T本身,另一种是*T,即T的指针形式

但作为T本身是 方法里的操作 相当于把 T 复制了一份出来

如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
"fmt"
)
func main() {
var persion=Persion{Name:"Tom",Age:10}
fmt.Println(persion)
persion.Say("hello yahui")
fmt.Println(persion)
}
type Persion struct
{
Name string
Age int
}
func (p Persion) Say(word string) {
p.Name="Jack"
fmt.Println(p.Name,"Say",word)
}

输出:

1
2
3
4

{Tom 10}
Jack Say hello yahui
{Tom 10}

但作为*T是方法里的操作是真正的正在引用T

如以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
"fmt"
)
func main() {
var persion=Persion{Name:"Tom",Age:10}
fmt.Println(persion)
persion.Say("hello yahui")
fmt.Println(persion)
}
type Persion struct
{
Name string
Age int
}
func (p *Persion) Say(word string) {
p.Name="Jack"
fmt.Println(p.Name,"Say",word)
}

输出:

1
2
3
{Tom 10}
Jack Say hello yahui
{Jack 10}

问题描述

很多人会遇到 初次运行 react-native run android的时候 gradle下载极慢,甚至会失败的问题
如下图

react-native-gradle-201879143159

解决办法

1. 首先 把对应版本的gradle下载到本地任意一个磁盘里

比如说我在到了 Z:\gradle\gradle-2.4-all.zip

2. 然后拖拽 Z:\gradle\文件夹到chrome浏览器 就会得到 file:///Z:/gradle/的访问地址 后面加上文件名 gradle-2.4-all.zip

得到 file:///Z:/gradle/gradle-2.4-all.zip的访问地址

然后 替换 项目中的 android/gradle/wrapper/gradle-wrapper.properties中的 distributionUrl
注意: :之前要加个\ 转义 即:file\:///Z:/gradle/gradle-2.4-all.zip

此方法 MacWin通用

视图

常用视图

  1. UIView 容器 大部分的ios用户界面的基本对象
  2. UIBotton 按钮视图
  3. UILable 标签视图 用户显示文本
  4. UIImageView 图像视图,用户显示图像
  5. UITextFidld 文本框视图 单行操作
  6. UITextView 文本视图 多行操作
  7. UIScrollView 滚动视图 提供滚动视图的能力
  8. UIPageView 页面视图, 提供不同的页面和屏幕的导航作用
  9. UIAlertView 警告视图 向用户显示一个消息框

定制视图

在项目中添加和定制视图 主要有两种方式,分别是 InterfaceBuilder编辑使用代码构建

Interface Builder

  1. 打开项目新建一个 storyboard文件
  2. 在ide的右边有个工具栏按钮,打开工具栏界面
  3. 把工具栏里的View拖动到storyboard的主视图中
  4. 保存项目 运行 查看运行效果

这里使用的是最快速方便的ant打包,选用ant打包的原因是他比aapt package之类的打包命令简单直接,便于入手
首先保证你的环境可以IDE里正常调试,无错误

设置打包环境

这里我用一个批处理把打包需要的环境变量设置好
批处理setting.bat

set JAVA_HOME=%~dp0\Java\jdk
set CLASSPATH=.;%JAVA_HOME%/lib/dt.jar;%JAVA_HOME%/lib/tools.jar
set path=%JAVA_HOME%\bin;%path%
set ANDROID_HOME = %~dp0\android\sdk
set path=%~dp0\android\sdk;%path%
set path=%~dp0\android\sdk\tools;%path%
set path=%~dp0\android\sdk\platform-tools;%path%
set path=%~dp0\apache-ant\bin;%path%

由代码可以清楚的知道 这里主要是设置了jdk Android和ant的环境变量

执行打包

在项目的主目录新建 builder.bat

call /setting
:这里是 lib-project 初始化应用的项目 weibo.sdk.android.api
cd ../weibo.sdk.android.api
call android update lib-project -p . -t android-19

cd ../myapp

call ant clean
call android update project -p . -t android-19
call ant release

所有命令执行完毕,就会在bin目录下生成 -release.apk结尾的 apk文件既是打包好的安装包

注意:

1.如果引用了第三方类库需要在project.properties里的 android.library.reference.1=..\\weibo.sdk.android.api

2.执行 ant release 发布代签名的apk的时候 需要在项目主目录里有ant.properties文件 里面要正确的配置key.storekey.aliaskey.store.passwordkey.alias.password

主要命令:

  1. xcodebuild : 主要是用于编译构建xcode项目 把项目构建成 项目名.app
  2. xcrun :主要用于把编译成的.app 文件夹打包成ipa文件
    下面用shell脚本的格式来讲解
    文件名 ios.sh
    代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #bin/bash
    echo "开始打包"
    projectPath=$1 # shell脚本的第一个参数 xcode项目路径
    ipaReleasePath=$2 # shell脚本的第二个参数 打包好的ipa文件的路径
    echo "项目路径:"$projectPath # 打印项目路径
    cd "$projectPath"
    xcodebuild clean -configuration Release # 清空以前的项目构建信息
    xcodebuild -target 项目名 -configuration Release -sdk iphoneos build # 开始生成生产环境APP
    xcrun -sdk iphoneos PackageApplication -v "$projectPath""build/Release-iphoneos/项目名字.app" -o $ipaReleasePath #给 项目名字.app(签名并)打包成ipa文件
    echo "结束打包"

注意

  1. 以上的脚本中-configuration Release 指的是使用在xcode中 名字为Release的配置信息
  2. 打包好的ipa文件使用 Application Loader 上传到 app store中

aop是面向切面编程的简称,对业务逻辑中的各个部分切割隔离,使耦合度降到最低,不仅增加了开发效率,还增强了系统的重用性和可维护性。
个人理解是把面向对象编程和面向函数编程结合在了一起。

说了这多的好处,那么AOP如何实现呢

Autofac.Aop里面提供了方便的AOP实现方式 下面我用Autofac.Aop做了个小示例

1
2
3
4
5
6
7
public class TestOnMethodBondedAspect : OnMethodBondedAspect
{
public override void OnExecuting(Castle.DynamicProxy.IInvocation invocation)
{
Console.WriteLine("Some things running");
}
}
1
2
3
4
5
6
public interface IPerson
{
[TestOnMethodBondedAspect]
string DoSomeThing(string name);
}

1
2
3
4
5
6
7
public class Studen : IPerson
{
public string DoSomeThing(string name)
{
return "I im" + name+ ", I'm studying";
}
}

下面我们把对象注入容器中 并且调用 IPerson的 DoSomeThing

1
2
3
4
5
6
7
8
var builder = new ContainerBuilder();
builder.RegisterType<Studen>().As<IPerson>()//;
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(MethodInterceptor));
builder.Register(x => new MethodInterceptor());
Container = builder.Build();
var studen= Container.Resolve<IPerson>();
Console.WriteLine(studen.DoSomeThing("Yahui"));

执行结果

Some things running
I im Yahui, I'm studying

如果熟悉asp.net mvc 的朋友会感觉aop很像其中的filter,的确很像 aop就是让各个业务之间实行拦截,业务更清晰,将耦合度降到最低

这里我用autofac作为DI工具因为autofac支持的.NET版本比较新,纯属个人爱好
Spring.net Castle.Windsor,Unity等也都有AOP的实现方式,感兴趣的朋友可以动手去试试,对比下其中的区别和优劣。

CentOS下安装使用start-stop-daemon

在centos下下了个自启动的服务器脚本 执行的时候发现找不到start-stop-daemon命令
好吧 执行手动编译一下 加上这个命令

1
2
3
4
5
6
7
8
9
wget http://developer.axis.com/download/distribution/apps-sys-utils-start-stop-daemon-IR1_9_18-2.tar.gz

tar -xzvf apps-sys-utils-start-stop-daemon-IR1_9_18-2.tar.gz
# 然后进入解压之后的路径 一直 cd 到start-stop-daemon.c在的目录

cc start-stop-daemon.c -o start-stop-daemon

cp start-stop-daemon /usr/bin/start-stop-daemon

ok 现在可以正常启动服务了

linux的服务开机设置一般在 /etc/init.d/里

而jexus的默认安装目录在 /usr/jexus里 启动文件为 jws 参数 有start stop restart

这里贡献一个刚写好的jexus的开启启动脚本

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
#!/bin/bash
### BEGIN INIT INFO
#
# Provides:jws
# Required-Start:$local_fs $remote_fs
# Required-Stop:$local_fs $remote_fs
# Default-Start:2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: jws
# Description: This file should be used to construct scripts to be placed in /etc/init.d.
#
### END INIT INFO

## Fill in name of program here.
PROG="jws"
PROG_PATH="/usr/jexus" ## Not need, but sometimes helpful (if $PROG resides in /opt for example).
PROG_ARGS="start"
PID_PATH="/var/run/"

start() {
if [ -e "$PID_PATH/$PROG.pid" ]; then
## Program is running, exit with error.
echo "Error! $PROG is currently running!" 1>&2
exit 1
else
## Change from /dev/null to something like /var/log/$PROG if you want to save output.
$PROG_PATH/$PROG $PROG_ARGS 2>&1 >/var/log/$PROG &
$pid=`ps ax | grep -i 'jws' | sed 's/^\([0-9]\{1,\}\).*/\1/g' | head -n 1`

echo "$PROG started"
echo $pid > "$PID_PATH/$PROG.pid"
fi
}

stop() {
echo "begin stop"
if [ -e "$PID_PATH/$PROG.pid" ]; then
## Program is running, so stop it
pid=`ps ax | grep -i 'jws' | sed 's/^\([0-9]\{1,\}\).*/\1/g' | head -n 1`
kill $pid
rm -f "$PID_PATH/$PROG.pid"
echo "$PROG stopped"
else
## Program is not running, exit with error.
echo "Error! $PROG not started!" 1>&2
exit 1
fi
}

## Check to see if we are running as root first.
## Found at http://www.cyberciti.biz/tips/shell-root-user-check-script.html
if [ "$(id -u)" != "0" ]; then
echo "This script must be run as root" 1>&2
exit 1
fi

case "$1" in
start)
start
exit 0
;;
stop)
stop
exit 0
;;
restart)
stop
start
exit 0
;;
**)
echo "Usage: $0 {start|stop|restart}" 1>&2
exit 1
;;
esac

最后记得 sudo chmod +x /etc/init.d/jws
添加自动启动服务 sudo update-rc.d jws defaults
删除自动启动服务 sudo update-rc.d jws remove

程序的执行不只是根据代码的先后顺序,可以使用条件控制语句和循环语句对代码的执行加以控制

条件控制语句

根据条件 来判断是否执行相应的代码 关键字:有 if,switch

if

if和else和配合起来会使用 if 后面是个小括号,小括号里面是要判断的特定的条件,条件结果是bool类型。紧跟着条件结果为true的时候要执行的代码,如果是多行代码需要使用大括号{}括起来。如果条件结果是false,则执行其后紧跟着的else后面的代码,同样如果是多行代码需要用大括号括起来 else后面也可以继续加if判断 代码示例:

        int i = 1;
        if (i > 0)
        {
            Console.WriteLine("i大于0");
        }
        else
        {
            Console.WriteLine("i不大于0");
        }

执行结果: i不大于0

        //int i = 1;
        int i = -1;
        if (i > 0)
        {
            Console.WriteLine("i大于0");
        }
        else
        {
            Console.WriteLine("i不大于0");
        }

执行结果: i大于0

switch

switch和case一起使用 当在一组互斥的分支中需要选择一个执行的时候使用。但switch参数里的值等于case后面的值的时候,执行case的代码 代码示例:

        int i = -1;
        switch (i)
        {
            case 0:
                Console.WriteLine("当前i为0");
                break;
            case 1:
                Console.WriteLine("当前i为1");
                break;
            case -1:
                Console.WriteLine("当前i为-1");
                break;
            default:
                break;
        }

执行结果: 当前i为-1  

循环语句

是代码在满足了一定的条件可以重复的执行的关键语句 主要有:for、foreach、while、do… while

for

先来看个for语句执行的经典的例子

        for (int i = 0; i < 3; i++)
        {
            Console.WriteLine(i.ToString());
        }

执行结果: 0 1 2   其中代码中 a. int i=0是第一次执行要运行的代码 b. i<10是迭代执行的时候需要判断的条件,如果这个条件结果不是true,for语句将执行结束 c. i++ 是每次循环执行的时候要计算的表达式 d. Console.WriteLine(i.ToString()); 是需要循环执行的代码 代码执行的顺序是 a->b->d->c->b->d->c->b->d->c->b(此时i=3 已经不满足i<3了 迭代结束)

foreach

与for相比foreach不需要那么繁琐 示例代码:

        string[] strInfo = new string[] { "你好", "这里是", "http://yahui.wang" };
        foreach (string item in strInfo)
        {
            Console.WriteLine(item);
        }

执行结果: 你好 这里是 http://yahui.wang 可以看出foreach遍历了一个集合,取到集合里所有的单元,并且在循环语句中使用这个单元

while

如果while里的表达式如果条件满足,将会执行while后大括号里的代码,条件不满足的时候跳出执行 代码示例:

          int value = 0;
        while (value<2)
        {
            Console.WriteLine("我执行了一次");
            value++;
        }

执行结果: 我执行了一次 我执行了一次

do … while

do while相当于while的另一个版本 区别在于先执行do后面大括号的代码 在进行while判断,也就是说 do后面大括号里的代码必定会执行一编 代码示例:

        do
        {
            Console.WriteLine("我执行了一次");
        } while (false)

  执行结果: 我执行了一次

跳转语句

在代码执行的过程中跳到另一行代码执行或者跳出当前循环,结束当前代码段执行等起跳转作用的语句,包括:goto、break、continue、return、

goto

从示例中学习

        goto label;
        Console.WriteLine("世界");
    label:
        Console.WriteLine("你好");

执行结果: 你好 说明:其中label:是一个名为label的标签;后面的代码是标记的代码,执行goto label的时候直接跳转到了label标记代码,中间的  Console.WriteLine(“世界”) 没有被执行。 goto不能跳转到循环关键字的代码块中,也不能跳出try catch 的finally代码块 但是在实际使用中,goto的口碑并不怎么好。不建议经常使用。

break

break可以跳出switch里的单个case ,也可以跳出for、foreach、while、do…while循环  

continue

continue是跳出此次循环,进入下个循环。在for、foreach、while、do…while中使用。  

return

return结束一个函数的执行,给出一个函数的返回值,当一个函数没有返回值的时候 return只做结束当前函数使用   本文代码地址:https://github.com/yahue/JustDoIt-CSharp/tree/master/0003_Source/0003_Source