Swift 3类型转换报错,cannot convert value of type NSMutableDictionary to expected argument type '[NSObject:AnyObject]?'

Swift的NSError已经更新为接受原生的Swift字典作为参数,和不可变字典NSDictionary不一样, NSMutableDictionary 没有和Swift做转换关联,所以会有这样的错误。

方法一:

更改为使用swift原生的字典:

let errorInfo= [String: AnyObject]()

方法二

如果不方便修改NSMutableDictionary的类型,把可变的NSMutableDictionary转换为NSDictionary,然后再转换为[String: AnyObject]()

var errorInfo = errorInfo as NSDictionary? as? [String: AnyObject] ?? [:]

Swift 3报错:Value of type 'String' has no member 'substringWithRange'

Swift 3截取字符串有下面这三种方法:

str.substring(to: String.Index)
str.substring(from: String.Index)
str.substring(with: Range<String.Index>)

Swift 2的String.substringWithRange的方法可以使用Swift 3的String.substring(with: Range<String.Index>)代替。

可以参考Swift 3字符串截取substring的用法

Swift 3字符串截取substring的用法

Swift 3的String有三个方法用于做字符串截取:

str.substring(to: String.Index)
str.substring(from: String.Index)
str.substring(with: Range<String.Index>)

用于做示范的示例:

var str = "Hello, World"

str.substring(to: String.Index)

这个方法会从字符串的开始截取到to参数指定的索引。

let index = str.index(str.startIndex, offsetBy: 5)  //索引为从开始偏移5个位置
str.substring(to: index)  // 获取Hello

substring(from: String.Index)

这个方法会从from参数指定的索引截取到字符串的末尾。

let index = str.index(str.startIndex, offsetBy: 7) //索引从开始偏移7个位置
str.substring(from: index)  // 输出World

str.substring(with: Range<String.Index>)

这个方法是截取指定的字符串范围,范围由Range指定。类似于Swift 2的String.substringWithRange

let start = str.index(str.startIndex, offsetBy: 7)  //索引从开始偏移7个位置
let end = str.index(str.endIndex, offsetBy: -3)   //所有从末尾往回偏移三个位置
let range = start..<end

str.substring(with: range)  // 输出Wo

怎么使用CSS变量

CSS变量由用户定义,并设置一个值,这个变量可以在文档里重用。使用CSS变量可以提高代码的可维护性和提高可读性。

基本用法

声明变量

element {
  --main-bg-color: brown;
}

使用变量

element {
  background-color: var(--main-bg-color);
}
  • element

    element为CSS选择器,包括id选择器,类选择器,元素选择器等。其中:root伪类在声明CSS变量是比较常用来放置CSS变量。

    :root {
      --main-bg-color: brown;
    }

    :root匹配文档根元素,在HTML里,文档的根元素就是html。把CSS变量放置在:root下,这样文档里的任何元素都可以引用这个变量重用,如果在特定的元素里需要改变变量的值,可以在特定的选择器里定义这个变量。

  • 自定义属性

    与CSS标准属性不一样,自定义属性由用户自己定义属性的名字,它的格式是在属性名前加上'--':

     --my-size: 100px;

    CSS变量就是使用自定义属性来声明。

  • var()函数

    在CSS里,需要使用CSS的var()函数来获取自定义属性的值。

    :root {
       --text-color: #000000;
    }
    p {
      color: var( --text-color );
      font-size: 16px;
    }

变量的继承

自定义属性是可以继承的,如果某个元素的自定义属性没有被设置,自定义属性则会继承元素的父元素的值。

:root {
  --base-button-color : red;
}
form {
  --base-button-color: blue;
}
a{
  background-color: var(--base-button-color);
}

page1

<html>
  <body>
    <a>button</a>
  </body>
<html>

page2

<html>
  <body>
    <form>
      <a>button</a>
    </form>
  </body>
<html>

page1里a元素没有定义对应的--base-button-color,所以它会继承父元素,一直追溯到:root,背景颜色显示红色。

page2里a元素追溯的父元素form定义的--base-button-color,form定义的-base-button-color则会覆盖根元素定义的值。

使用CSS变量的好处

使用CSS变量最明显的两个好处是:提高代码的维护性和提高代码的可读性

  • 可维护性

    在一些比较大的网站,CSS代码量往往也比较大,如果在多个地方会使用同样的值,当有更改时,那么就需要搜索出来做替换。这种人工搜索替换的方式很容易出现人为失误导致bug。

    使用CSS变量,碰到上面的这些情况就比较容易处理了,如果是全部修改,那只需修改变量的值。

  • 可读性

    background-color: yellow;

    对比

    background-color: var( --highlight-color );

    自定义属性的方式具有语义,可读性比较好。

C语言里怎么把宏定义转换为字符串

首先使用str(a) 把参数a的值转换为字符串,然后使用宏扩展把xstr扩展为str(a)

#define str(a) #a
#define xstr(a) str(a)

#define PAGE_SIZE 10

int main()  
{  
    printf("page size = " xstr(PAGE_SIZE) " \n");  
    return 0;  
} 

vagrant 启动报错,The box could not be found or could not be accessed in the remote catalog

这是 vagrant 1.8.7 的问题,vagrant自带的curl版本低与mac里的curl不兼容,把vagrant自带的curl删除即可

sudo rm /opt/vagrant/embedded/bin/curl

执行vagrant box add也会出现这个问题,也是把vagrant自带的curl删除。

参考:embedded libcurl provides out-of-date version

Gradle提示,You have not accepted the license agreements of the following SDK components: [Android SDK Build-Tools 24.0.2]

license存放在$ANDROID_HOME/licenses下

创建license

Linux

mkdir "$ANDROID_HOME/licenses"
echo -e "\n8933bad161af4178b1185d1a37fbf41ea5269c55" > "$ANDROID_HOME/licenses/android-sdk-license"

Windows

mkdir "%ANDROID_HOME%\licenses"
echo |set /p="8933bad161af4178b1185d1a37fbf41ea5269c55" > "%ANDROID_HOME%\licenses\android-sdk-license"

升级到iOS 10.1.1后,用Xcode 8.1 build app失败,file was built for archive which is not the architecture being linked (arm64)

  1. 检查Architectures 和 Valid Architectures是否设置正确

    Project -> target (项目名) -> build settings ,设置architectures 和Valid Architectures,Active Architectures 设置为 YES

  2. 清除DerivedData里的数据

    exit xcode
    rm -rf ~/Library/Developer/Xcode/DerivedData

JavaScript检查2G网络环境

使用Network Information API来检查网络2G状态

if(navigator.connection &&
   navigator.connection.type === 'cellular' &&
   navigator.connection.downlinkMax <= 0.115) {
  // 2G网络
}

A Parser-blocking, cross-origin script is invoked via document.write. This may be blocked by the browser if the device has poor network connectivity.

在弱的网络连接环境下,比如2G网络,在页面上使用document.write()来动态插入外部的脚本会阻塞页面的解析,延迟页面的显示,甚至加载脚本失败,最终导致页面不能正确显示。

为了提高用户的体验,Chrome对于由document.write()动态插入的<script>会做检查,当满足下面所有的条件下,Chrome不会执行加载<script>里的脚本。

  1. 用户处在弱网络连接的环境下,特别是2G网络。
  2. document.write()在主页面里,对于那些嵌入在iframe里的页面没有影响。
  3. document.write()插入的脚本是阻碍解析的(parser-blocking)。如果插入的<script>标签加了 'async' 或着'defer'属性,脚本会异步加载,不影响解析 ,所以也是能被执行的。
  4. 加载的脚本和站点不是同一个域名。
  5. 脚本没有在浏览器的缓存里
  6. 页面不是重新加载

从Chrome 53开始,对于满足2-5条件的代码,在控制台会输出问题里的警告:

A Parser-blocking, cross-origin script, https://example.com/script.js, is invoked via document.write. This may be blocked by the browser if the device has poor network connectivity.

解决方案:

  1. 最好的办法就是不要使用document.write()动态加载脚本
  2. 如果一定要使用document.write()加载脚本,使用异步加载的方式,如<script src="..." async> 或使用DOM API element.appendChild()

CSS实现在圆圈里创建三个竖直排列的小圆点

圆圈实现:把元素的宽和高设为相等,border-radius设为50%。

小圆点可以使用着重点'•',对应的Unicode 编码为'\u2022',三个小圆点'•••'使用transform: rotate做旋转90度即可得到竖直排列。

实现代码如下:

div {
  position: relative;
  background: #3F3C53;
  width: 50px;
  height: 50px;
  color: white;
  border-radius: 50%;
  box-shadow: 0px 0px 15px 1px #4185BC;
  margin: 50px;
}
div:after {
  content: '•••';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) rotate(90deg);
  font-size: 15px; 
  letter-spacing: 4px;
  margin-top: 2px;
}

JavaScript报错,ReferenceError: invalid assignment left-hand side

var a1, a2; a1 = !a2 = true;

实际等同于:

var a1, a2;
!a2 = true;
a1 = a2;

在赋值表达式!a2 = true;中,左边是一个表达式,不能接收被赋值,所以报这个错误。

所以遇到invalid assignment left-hand side 错误,可以查看下代码哪里出现了不能被赋值。

Chrome:您的连接不是私密连接,ERR_CERTIFICATE_TRANSPARENCY_REQUIRED

这是Chrome 53 的一个bug,如果https链接不能正常通过SSL certificate验证,就会提示Certificate Transparency 错误:ERR_CERTIFICATE_TRANSPARENCY_REQUIRED。

解决方案:

  1. 升级到chrome 54
  2. Google发布更新补丁后,重启chrome 53

参考:bugs

C++里为什么'A'字符会同时与0x41和0xc1做比较呢

在EBCDIC编码里0xc1表示字符'A',0x41则是ASCII编码里表示字符A。

EBCDIC编码是IBM在1963年-64年间推出的字符编码表,根据早期打孔机式的二进化十进数排列编码。在IBMOS/390操作系统上使用EBCDIC编码作为文本文件的编码。所以,这段代码应该是用来区分不同机器的。

参考:EBCDIC

Error:java: Compilation failed: internal java compiler error

这是因为在IntelliJ Idea设置项目编译器的jdk版本和项目所需要的jdk版本不一致导致。

修改地方如下:

File -> Settings -> Build,Excution,Deployment -> Compiler -> Java Compiler

修改右侧的窗口的两个配置项

  • Project bytecode version(leave blank for JDK default) -> 修改为对应的JDK版本
  • Per-module bytecode version -> 模块Target bytecode version 修改为对应JDK版本

Android Studio buildTools升级到25报错,Exception raised during rendering: Unable to locate mode 0

这是buildTool使用RecyclerView 渲染的问题,是buildTool 25.0.0的bug。参考issue

临时的解决方案是把recyclerview版本降到24

compile 'com.android.support:appcompat-v7:24.2.1'
compile 'com.android.support:design:24.2.1'
compile 'com.android.support:recyclerview-v7:24.2.1'

Java移除数组里的负数

方法一

Java8可以使用stream来过滤

Arrays.stream(num).filter(s -> s >= 0).toArray();

方法二

使用新数组处理

public static int[] removeNegativeNumbers(int[] num) {
    int[] output = new int[num.length];
    int k = 0;
    int i = 0;
    while(i < num.length) {
       if(num[i] >= 0) {
           output[k++] = num[i++];
       } else {
           ++i;
       }
    }
    return Arrays.copyOfRange(output, 0, k);
}

方法三

在原来的数组处理

public static int removeNegativeNumbers(int[] num) {
    int k = 0;
    int i = 0;
    while(i < num.length) {
       if(num[i] >= 0) {
           num[k++] = num[i++];
       } else {
           ++i;
       }
    }
    return Arrays.copyOfRange(num, 0, k);
}

CSS3使用translateY实现元素竖直居中

CSS3使用transform属性translateY实现元素竖直居中代码如下:

.element {
  position : relative;
  top: 50%;
  transform: translateY(-50%);
}

这里父元素不需要设置高度和position属性。

在不支持CSS3,但支持transform属性的浏览器里可以使用浏览器前缀做兼容:

.element {
  position: relative;
  top: 50%;
  -webkit-transform: translateY(-50%);
  -ms-transform: translateY(-50%);
  transform: translateY(-50%);
}

解析

top:0

默认情况下,元素的top值为0,在页面的位置如下

--------Top of Page--------
{element}


------Middle of  Page------



------Bottom of  Page------

top:50%

把top值设为50%,元素的左上角在页面中间的位置,但不是居中

--------Top of Page--------



------Middle of  Page------
{element}


------Bottom of  Page------

top:50%; transform:translateY(-50%);

为了让在top:50%的元素居中,使用transform属性的translateY(-50%),把元素在Y轴上往上移动元素50%的高度。

--------Top of Page--------



{element}-Middle of Page---



------Bottom of  Page------

这里有一个小问题,元素使用translateY往上移动会失去半个像素,可能会导致元素变得模糊。解决方法是在父元素设置转换的样式为preserve-3d

.parent-element {
  -webkit-transform-style: preserve-3d;
}

sql server为什么NOT LIKE返回的不是与LIKE返回的相反数据

如果数据里有NULL值,那么不管是like 还是 not like 得到的结果都是UNKNOWN,所以检查下是不是NULL导致了not like返回的不是like返回数据的补集。

如果要包括NULL值,查询改为:

select * from user where name not like 'a%' or name is null;

Java try-with-resources用法

在Java 7之前,IO操作为了保证资源能被关闭,往往会在try代码块后加上finally代码块来处理资源的关闭。

BufferedReader br = new BufferedReader(new FileReader(path));
try {
    return br.readLine();
} finally {
    if (br != null) br.close();
}

Java 7新增了try-with-resources语法来保证资源的关闭

try(BufferedReader br = new BufferedReader(new FileReader(path));) {
  return br.readLine();
}

BufferedReader 会在代码块里处理完后会被关闭,不需要显式调用BufferedReader的close方法。

使用方法

  1. 被关闭的资源类需要实现AutoClosable接口,Closeable接口继承于AutoClosable,所以实现了Closable接口的BufferedReader可以在try-with-resources被自动关闭。

  2. 需要自动关闭的资源在try后面的括号里声明。允许声明多个被关闭的资源,关闭的顺序是与创建资源的顺序相反。

异常处理

在传统的try-catch-finally方式处理异常时,如果在finally代码块里有异常抛出,try代码块里抛出的异常会被抑制。

public void testTryWithFinally() {
    try {
        throw new RuntimeException("try exception");
    } finally {
        throw new RuntimeException("finally exception");
    }
}

在这个示例里,虽然try代码块里先抛出了异常,但是外部调用只捕获到finally抛出的异常,try代码块抛出的异常被抑制。

try-with-resources里关闭资源时都允许抛出异常,但与传统的try-catch-finally处理异常不同,如果try执行的代码块里抛出异常,那么try-with-resources关闭资源抛出的异常将被抑制。

public void testTryWithResources() throws Exception {
    try (ClosableResource resource = new ClosableResource()) {
        throw new RuntimeException("try exception");
    }
}

class ClosableResource implements AutoCloseable{

    @Override
    public void close() throws Exception {
        throw new RuntimeException("close resource runtime exception");
    }
}

在这个示例里,ClosableResource 被关闭时会抛出运行时异常,但是在try执行的代码块里也有异常抛出,外部调用捕获的将是try执行代码块里的异常。

关闭资源与catch-finally执行顺序

try-with-resources也可以添加catch和finally语句,但catch和finally里的代码在资源被关闭后才会被执行。

public void testTryWithResources2() throws IOException {
    try (ClosableResource resource = new ClosableResource()) {
        throw new RuntimeException("try exception");
    } catch (Exception e) {
        System.out.println("catch exception:" + e.getMessage());
        System.out.println("suppressed exception:" + e.getSuppressed()[0].getMessage());
    } finally {
        System.out.println("finally exception");
    }
}

class ClosableResource implements AutoCloseable{

    @Override
    public void close() throws Exception {
        System.out.println("close resource");
        throw new RuntimeException("close resource runtime exception");
    }
}

输出的顺序是

close resource
catch exception:try exception
suppressed exception:close resource runtime exception
finally exception

输出顺序是关闭资源,catch捕获try里抛出的异常,最后才是执行finally代码。其中关闭资源抛出的异常可以使用Throwable.getSuppressed()获得。