2017年9月

iOS 获取图片的原始格式

今天测试给过来一张图片(后缀是.png)说无法在 APP 的 WebView 里面无法显示,而且在 Safari 里也是无法打开的,但在谷歌浏览器上是可以正常显示。起初是知道 WebP 格式的图片苹果是不支持显示的,但这个图片的后缀是.png 的,难道还有 png 的图片是苹果不支持的么?

根据个人经验,是没有听说苹果不支持 png 格式的图片的,这时想到以前自己更改 JPG 图片后缀的事情,是不是这张图片也是经过别人手动改后缀的呢,带着这个疑问,我决定手动判断这张图片的原始格式。

记得以前在看 SDWebImage 源码时,源码中是有关于判断根据 image 来判断图片的实际格式的,于是从 SDWebImage 中的源码中抠出来判断图片实际格式的代码。

图片的前8位是存储图片格式的,可以通过先读取图片的数据,拿到图片的前8位来判断图片的类型

/**
 *
 * 根据图片数据获取图片的原始类型
 * 
 * @param data 图片的二进制数据
 * @return 图片的实际格式
 */
- (NSString *)typeForImageData:(NSData *)data {
    uint8_t c;
    [data getBytes:&c length:1];
    
    switch (c) {
        case 0xFF:
            return @"image/jpeg";
        case 0x89:
            return @"image/png";
        case 0x47:
            return @"image/gif";
        case 0x49:
        case 0x4D:
            return @"image/tiff";
        case 0x52: {
            //R as RIFF for WEBP
            if (data.length < 12) {
                return nil;
            }
            NSString *identifierTypeStr = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
            if ([identifierTypeStr hasPrefix:@"RIFF"] && [identifierTypeStr hasSuffix:@"WEBP"]) {
                return @"image/webp";
            }
            return nil;
        }
            
        default:
            break;
    }
    return nil;
}

That's All.

Code

原文链接:iOS 获取图片的原始格式

XCode 8.0下 NSLog 打印不完全

今天在重新整理希尔排序的时候,使用了 100000 个种子数据进行测试,但发现在排序好后,用 NSLog 无法打印完全排序结果,开始以为自己的排序算法写法有误,但查看内存数据信息,显示排序结果正常。这时怀疑 NSLog 在 XCode 8.0 下可能有 Bug。 于是使用 c 语言函数 printf 进行打印。

Bingo !

代码如下:

NSMutableArray<NSNumber *> *results = [dataList mutableCopy];
printf("%s", [results.description UTF8String]);

附(NSString 与 char 相互转换):

//NSString转换char
NSString * str1= @"Test";
const char * c1 =[str1 UTF8String];
//char转换NSString
const char * c2 ="test";
NSString *str2 = [NSString stringWithUTF8String:c2];

原文链接:XCode 8.0下 NSLog 打印不完全

Ubuntu 16.0.4 安装 Swift 后提示 error while loading shared libraries: libpython2.7.so.1.0

Ubuntu 16.0.4 安装 Swift 后提示: error while loading shared libraries: libpython2.7.so.1.0:

swift/usr/bin/lldb: error while loading shared libraries: libpython2.7.so.1.0: cannot open shared object file: No such file or directory

这个问题会在 Ubuntu 14.04 和 Ubuntu 16.04 上出现,是 swift 的一个依赖问题,只需要安装 libpython2.7-dev 就可以解决问题。代码如下

sudo apt-get install libpython2.7-dev

Done !

Link : Incomplete install instructions for Ubuntu
原文链接: Ubuntu 16.0.4 安装 Swift 后提示 error while loading shared libraries: libpython2.7.so.1.0

iOS 位枚举

在 iOS 开发中,我们使用系统的枚举定义的时候,经常可以看到位枚举

typedef NS_OPTIONS(NSUInteger, UIControlState) {
    UIControlStateNormal       = 0,
    UIControlStateHighlighted  = 1 << 0,                  // used when UIControl isHighlighted is set
    UIControlStateDisabled     = 1 << 1,
    UIControlStateSelected     = 1 << 2,                  // flag usable by app (see below)
    UIControlStateFocused NS_ENUM_AVAILABLE_IOS(9_0) = 1 << 3, // Applicable only when the screen supports focus
    UIControlStateApplication  = 0x00FF0000,              // additional flags available for application use
    UIControlStateReserved     = 0xFF000000               // flags reserved for internal framework use
};

需要掌握位枚举,我们需要先了解位运算位移

位运算

位运算有两种:位或(|)位与(&)

  • 位或(|) :两个进行或(|)运算。运算规则:两个运算的只要有一个为1则运算结果为1,否则为0

如:
0000 0001 | 0000 0010 结果为:0000 0011
0000 0000 | 0000 0000 结果为:0000 0000

  • 位与(&) :两个进行与(&)运算。运算规则:两个运算的都为1则运算结果为1,否则为0

如:
0000 0001 & 0000 0001 结果为:0000 0001
0000 0001 & 0000 0010 结果为:0000 0000

位移

位移包含两种:左移(<<)右移(>>)

  • << :将一个数的二进制位向左移动 n 位,高位丢弃,低位补 0。如将数字1(0000 0001)左移两位得到结果为:4(0000 0100)。表述为:1 << 2。

左移就是将一个数乘以 2 的 n 次方。

  • >> :将一个数的二进制位向右移动 n 位,低位丢弃,高位补 0。如将数字4(0000 0100)右移两位得到结果为:1(0000 0001)。表述为:4 >> 2。

右移就是将一个数除以 2 的 n 次方。

iOS 位枚举

我们有如下定义:

typedef NS_ENUM(NSUInteger, HJDirection) {
    // 0000 0001
    HJDirectionLeft = 1 << 0,
    // 0000 0010
    HJDirectionRight = 1 << 1,
    // 0000 0100
    HJDirectionTop = 1 << 2,
    // 0000 1000
    HJDirectionBottom = 1 << 3
};

PS:定义一个位枚举时,我们通常以一个数字作为基准,如数字1,然后对该数字进行左移(右移),这样我们才能在后面使用中判断是否包含某个枚举值。

使用:

//获取所有方向(位或运算)
//0000 1111
HJDirection directionAll = HJDirectionLeft | HJDirectionRight | HJDirectionTop | HJDirectionBottom;

//获取是否包含某个方向(位与运算)
if ((directionAll & HJDirectionLeft) == HJDirectionLeft) {
    //0000 0001
    NSLog(@"满足条件:左方向");
}
if ((directionAll & HJDirectionRight) == HJDirectionRight) {
    //0000 0010
    NSLog(@"满足条件:右方向");
}
if ((directionAll & HJDirectionTop) == HJDirectionTop) {
    //0000 0100
    NSLog(@"满足条件:上方向");
}
if ((directionAll & HJDirectionBottom) == HJDirectionBottom) {
    //0000 1000
    NSLog(@"满足条件:下方向");
}

我们回到开始的 UIControlState 枚举定义

我们在定义 UIButton 状态时,一般会用到 UIControlStateNormalUIControlStateHighlightedUIControlStateSelected,但我们怎么去定义一个选中状态下的高亮呢?如果我们单纯的使用 UIControlStateHighlighted, 我们得到的只是默认状态下的高亮显示。这时我们就需要用到位枚举的神奇之处了。

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTitle:@"点击我" forState:UIControlStateNormal];
//定义普通状态文字颜色
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
//定义选中状态文字颜色
[button setTitleColor:[UIColor blueColor] forState:UIControlStateSelected];
//定义普通状态高亮文字颜色
[button setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
//定义选中状态高亮文字颜色
[button setTitleColor:[UIColor orangeColor] forState:UIControlStateSelected | UIControlStateHighlighted];

Done !

Link:iOS 位枚举

Ubuntu 搭建 DNS 服务器

系统环境:

Ubuntu 16.04.3 LTS
IP : 192.168.1.110

安装步骤

1. 安装

apt-get update
apt-get install bind9

2. 配置缓存转发

打开打开/etc/bind/named.conf.options,修改后如下:

acl goodclients {
        192.168.1.0/24;
        localhost;
        localnets;
};

options {
        directory "/var/cache/bind";

        // If there is a firewall between you and nameservers you want
        // to talk to, you may need to fix the firewall to allow multiple
        // ports to talk.  See http://www.kb.cert.org/vuls/id/800113

        // If your ISP provided one or more IP addresses for stable
        // nameservers, you probably want to use them as forwarders.
        // Uncomment the following block, and insert the addresses replacing
        // the all-0's placeholder.

        // forwarders {
        //      0.0.0.0;
        // };

        //========================================================================
        // If BIND logs error messages about the root key being expired,
        // you will need to update your keys.  See https://www.isc.org/bind-keys
        //========================================================================
        dnssec-validation auto;

        auth-nxdomain no;    # conform to RFC1035
        listen-on-v6 { any; };

        //added
        listen-on { 192.168.1.110;};

        recursion yes ;
        allow-query { goodclients;};
        allow-query-cache { any; }; # 很重要,不然无法解析外网
        allow-transfer { none; }; # disable zone transfers by default

        forwarders {
                223.5.5.5; # alidns
                223.6.6.6; # alidns
                202.96.199.133; #上海电信DNS
                202.96.0.133; #上海电信DNS
                114.114.114.114; # 114 现在只配置alidns,不能解析国内域名
                114.114.115.115; # 114 现在只配置alidns,不能解析国内域名
                8.8.8.8; # Google Google可以解析国内和国外域名
                8.8.4.4; # Google Google可以解析国内和国外域名
        };
        forward only ;

};

3. 配置local文件

named.conf.local 文件默认是空的。本文在配置文件中分别定义一条正向解析一条反向解析。配置文件修改后类似如下:

//domain->ip
zone "local.com" in {
        type master;
        file "/var/cache/bind/db.local.com";
};
//domain->ip(for anthor domain)
//zone "local1.com" in {
//        type master;
//        file "/var/cache/bind/db1.local.com";
//};

//ip->domain
zone "1.168.192.in-addr.arpa" in {
        type master;
        file "/var/cache/bind/db.1.168.192";
};

4. 定义区域配置文件

配置文件定义后类似如下,分别是正向和反向两个解析记录。按照自己需求修改相应的区域和区域解析记录,IP等信息。

正向记录

sudo vim /var/cache/bind/db.local.com

$TTL 604800
@ IN SOA local.com. root.local.com. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604000) ; Negative Cache TTL
;
; name servers
@ IN NS ns.local.com.
@ IN A 192.168.1.110
;ns records
ns IN A 192.168.1.110
;host records
www IN A 192.168.1.110
api IN A 192.168.1.100

反向记录

sudo vim /var/cache/bind/db.1.168.192

$TTL 604800
@ IN SOA local.com. root.local.com. (
2 ; Serial Number
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
86400 ); ; Minimum

@ IN NS local.com.

66 IN PTR www.local.com.
66 IN PTR api.local.com.

5. 检查配置、重启

hejun@ubuntu:/var/cache/bind$named-checkconf
hejun@ubuntu:/var/cache/bind$named-checkzone local.com /var/cache/bind/db.local.com

zone local.com/IN: loaded serial 2
OK

hejun@ubuntu:/var/cache/bind$named-checkzone db.1.168.192 /var/cache/bind/db.1.168.192

zone db.1.168.192/IN: loaded serial 2
OK

分别检查了语法和区域配置文件,没有报错。重启bind服务。

sudo service bind9 restart

到这里DNS服务器的配置就完成了,可以使用dig命令测试。

配置路由器首要DNS

在路由器里设置首要DNS192.168.1.110 ,这样我们就可以在同一个内网下访问:www.local.com 就会指向到 192.168.1.110,访问:api.local.com 就会指向到 192.168.1.100

参考链接:Ubuntu系统Bind搭建配置私有、主备DNS服务器