IOS OC NSUserDefaults

NSUserDefaults

NSUserDefaults可以理解为本地的key-value数据库,类似sqlite的本地数据库的作用。

获取key的值

例子:

[[NSUserDefaults standardUserDefaults] boolForKey:kWifiOptimizeSwitch];

api:

/// -stringForKey: is equivalent to -objectForKey:, except that it will convert NSNumber values to their NSString representation. If a non-string non-number value is found, nil will be returned.
- (nullable NSString *)stringForKey:(NSString *)defaultName;

/// -arrayForKey: is equivalent to -objectForKey:, except that it will return nil if the value is not an NSArray.
- (nullable NSArray *)arrayForKey:(NSString *)defaultName;
/// -dictionaryForKey: is equivalent to -objectForKey:, except that it will return nil if the value is not an NSDictionary.
- (nullable NSDictionary<NSString *, id> *)dictionaryForKey:(NSString *)defaultName;
/// -dataForKey: is equivalent to -objectForKey:, except that it will return nil if the value is not an NSData.
- (nullable NSData *)dataForKey:(NSString *)defaultName;
/// -stringForKey: is equivalent to -objectForKey:, except that it will return nil if the value is not an NSArray<NSString *>. Note that unlike -stringForKey:, NSNumbers are not converted to NSStrings.
- (nullable NSArray<NSString *> *)stringArrayForKey:(NSString *)defaultName;
/*!
 -integerForKey: is equivalent to -objectForKey:, except that it converts the returned value to an NSInteger. If the value is an NSNumber, the result of -integerValue will be returned. If the value is an NSString, it will be converted to NSInteger if possible. If the value is a boolean, it will be converted to either 1 for YES or 0 for NO. If the value is absent or can't be converted to an integer, 0 will be returned.
 */
- (NSInteger)integerForKey:(NSString *)defaultName;
/// -floatForKey: is similar to -integerForKey:, except that it returns a float, and boolean values will not be converted.
- (float)floatForKey:(NSString *)defaultName;
/// -doubleForKey: is similar to -integerForKey:, except that it returns a double, and boolean values will not be converted.
- (double)doubleForKey:(NSString *)defaultName;
/*!
 -boolForKey: is equivalent to -objectForKey:, except that it converts the returned value to a BOOL. If the value is an NSNumber, NO will be returned if the value is 0, YES otherwise. If the value is an NSString, values of "YES" or "1" will return YES, and values of "NO", "0", or any other string will return NO. If the value is absent or can't be converted to a BOOL, NO will be returned.

 */
- (BOOL)boolForKey:(NSString *)defaultName;
/*!
 -URLForKey: is equivalent to -objectForKey: except that it converts the returned value to an NSURL. If the value is an NSString path, then it will construct a file URL to that path. If the value is an archived URL from -setURL:forKey: it will be unarchived. If the value is absent or can't be converted to an NSURL, nil will be returned.
 */
- (nullable NSURL *)URLForKey:(NSString *)defaultName API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));

看api,可以看到支持多种数据类型的获取

设置key的值

例子:

NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
    [userDefault setBool:senderSwitch.on forKey:kWifiOptimizeSwitch];

api:

/// -setInteger:forKey: is equivalent to -setObject:forKey: except that the value is converted from an NSInteger to an NSNumber.
- (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName;
/// -setFloat:forKey: is equivalent to -setObject:forKey: except that the value is converted from a float to an NSNumber.
- (void)setFloat:(float)value forKey:(NSString *)defaultName;
/// -setDouble:forKey: is equivalent to -setObject:forKey: except that the value is converted from a double to an NSNumber.
- (void)setDouble:(double)value forKey:(NSString *)defaultName;
/// -setBool:forKey: is equivalent to -setObject:forKey: except that the value is converted from a BOOL to an NSNumber.
- (void)setBool:(BOOL)value forKey:(NSString *)defaultName;
/// -setURL:forKey is equivalent to -setObject:forKey: except that the value is archived to an NSData. Use -URLForKey: to retrieve values set this way.
- (void)setURL:(nullable NSURL *)url forKey:(NSString *)defaultName API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));

同样支持各种数据的set。

说明:在set了后,数据其实还在内存数据结构中。还没有持久化到本地存储。

其他说明

 -synchronize is deprecated and will be marked with the API_DEPRECATED macro in a future release.

 -synchronize blocks the calling thread until all in-progress set operations have completed. This is no longer necessary. Replacements for previous uses of -synchronize depend on what the intent of calling synchronize was. If you synchronized...
 - ...before reading in order to fetch updated values: remove the synchronize call
 - ...after writing in order to notify another program to read: the other program can use KVO to observe the default without needing to notify
 - ...before exiting in a non-app (command line tool, agent, or daemon) process: call CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication)
 - ...for any other reason: remove the synchronize call

IOS OC UITableView

object c 中的UITableView 可以实现灵活的列表内容效果。列表的内容可以是多种类型元素。

主要步骤

  1. 正确实现numberOfSectionsInTableView和numberOfRowsInSection,获取正确的sections和每个section中的rows。例如:
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView {
    NSInteger num =[self.settingCellTitles count]+1;
    return num;
}

- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section {
    if (section == 0) {
        return 1;
    } else {
        NSInteger num =[[self.settingCellTitles objectAtIndex:section-1] count];
        return num;
    }
}
  1. 实现 UITableViewCell,可以理解为每个row中的内容。
  2. 实现didSelectRowAtIndexPath,点击每个row的逻辑

要点

因为可以是一个section多个rows,也可能是多个sections,相当于一维数组和二维数组的区别。

对于一维数组获取row index:

 [[_settingCellModes objectAtIndex:indexPath.row] integerValue];

对于二维数组:

[[[self.settingCellModes objectAtIndex:indexPath.section-1] objectAtIndex:indexPath.row] integerValue];

主要就是先获取indexPath.section对应的section,而一维是直接
indexPath.row。

联盛德W600 W100 wifi scan结果的串口报文解析

目前使用的版本,w100出厂自带wifi scan逻辑代码,上电开机后会从spi和uart发出wifi scan的结果,开机后只输出一次。

uart输出的报文如下:

报文样例

hspi tx:449
Z0C:4B:54:08:44:85,jinkun-lab2,-36|D0:C7:C0:6F:6D:96,COREACH_OFFICE,-47|88:44:77:F2:D2:74,dcup,-59|54:BA:D6:33:BB:3C,2305,-59|D0:76:E7:95:2D:F4,AIT-OFFICE,-59|40:F4:20:E4:CF:22,ChinaNet-vCCG,-64|7C:B5:9B:6B:A4:9A,TP-FX-2305-2.4G,-64|68:13:24:66:65:AC,2306,-71|64:6E:97:B7:99:DA,FX-2302,-71|F0:92:B4:D6:9A:29,ChinaNet-gSHU,-71|64:6E:97:5A:EC:42,涓滆揪閫氭櫤鑳借惀閿€涓績,-71|F0:92:B4:9C:51:19,ChinaNet-Dxat,-82|B0:7F:B9:94:25:8B,pinballtest,-90|

对应的hex:

68 73 70 69 20 74 78 3A 34 34 39 0D 0A 5A 0D 30 43 3A 34 42 3A 35 34 3A 30 38 3A 34 34 3A 38 35 2C 6A 69 6E 6B 75 6E 2D 6C 61 62 32 2C 2D 33 36 7C 44 30 3A 43 37 3A 43 30 3A 36 46 3A 36 44 3A 39 36 2C 43 4F 52 45 41 43 48 5F 4F 46 46 49 43 45 2C 2D 34 37 7C 38 38 3A 34 34 3A 37 37 3A 46 32 3A 44 32 3A 37 34 2C 64 63 75 70 2C 2D 35 39 7C 35 34 3A 42 41 3A 44 36 3A 33 33 3A 42 42 3A 33 43 2C 32 33 30 35 2C 2D 35 39 7C 44 30 3A 37 36 3A 45 37 3A 39 35 3A 32 44 3A 46 34 2C 41 49 54 2D 4F 46 46 49 43 45 2C 2D 35 39 7C 34 30 3A 46 34 3A 32 30 3A 45 34 3A 43 46 3A 32 32 2C 43 68 69 6E 61 4E 65 74 2D 76 43 43 47 2C 2D 36 34 7C 37 43 3A 42 35 3A 39 42 3A 36 42 3A 41 34 3A 39 41 2C 54 50 2D 46 58 2D 32 33 30 35 2D 32 2E 34 47 2C 2D 36 34 7C 36 38 3A 31 33 3A 32 34 3A 36 36 3A 36 35 3A 41 43 2C 32 33 30 36 2C 2D 37 31 7C 36 34 3A 36 45 3A 39 37 3A 42 37 3A 39 39 3A 44 41 2C 46 58 2D 32 33 30 32 2C 2D 37 31 7C 46 30 3A 39 32 3A 42 34 3A 44 36 3A 39 41 3A 32 39 2C 43 68 69 6E 61 4E 65 74 2D 67 53 48 55 2C 2D 37 31 7C 36 34 3A 36 45 3A 39 37 3A 35 41 3A 45 43 3A 34 32 2C E4 B8 9C E8 BE BE E9 80 9A E6 99 BA E8 83 BD E8 90 A5 E9 94 80 E4 B8 AD E5 BF 83 2C 2D 37 31 7C 46 30 3A 39 32 3A 42 34 3A 39 43 3A 35 31 3A 31 39 2C 43 68 69 6E 61 4E 65 74 2D 44 78 61 74 2C 2D 38 32 7C 42 30 3A 37 46 3A 42 39 3A 39 34 3A 32 35 3A 38 42 2C 70 69 6E 62 61 6C 6C 74 65 73 74 2C 2D 39 30 7C 0A 

字段说明

格式说明:

hspi tx:[字节数] 0x0d 0x0a
0x5A [0xNN][wifi scan list] 0x0a

字节数:回车换后后面的内容长度,但是实际计算下来发现是 字节数-1。
0x5A:是二进制报文头。
0xNN:标识wifi的个数。
wifi scan list:wifi scan list由多个类似的wifi节点:

40:16:9F:33:6A:18,COREACH,-82|

拼接而成。

解析

知道格式了,解析就很简单了。

wordpress更新php7.4后mysql连接问题

问题

Warning: mysqli_connect(): (HY000/2002): No such file or directory

更新完php7.4 后,再访问wordpress后,出现了上述的错误(开启DEBUG)。

定位

  1. 先单独通过mysql 命令在本地测试确认mysql服务正常。
  2. 检查wp-config.php的配置,没有问题
  3. 检查php的mysql支持,通过phpinfo()确认mysql支持没问题
  4. 初步锁定在php访问mysql的这个过程。

mysql status

登录mysql 后,通过status命令产看mysql socket:

UNIX socket:        /tmp/mysql.sock

php中mysql的配置

  1. 确认php.ini的配置文件路径:
# php --ini
Configuration File (php.ini) Path: /etc
Loaded Configuration File:         /etc/php.ini
  1. 通过phpinfo()页面来确认mysql的socket配置:
pdo_mysql.default_socket
mysqli.default_socket

解决

通过上面的过程,发现phpinfo页面和mysql实际的socket文件不一致,于是修改php.ini:

pdo_mysql.default_socket=/tmp/mysql.sock
mysqli.default_socket=/tmp/mysql.sock

或者修改my.cnf中相关:

[client]
socket=/tmp/mysql.sock
[mysqld]
socket=/tmp/mysql.sock

php和wordpress中版本显示不一致问题

现象

更新php到7.4后,在wordpress面板仍然提示php版本为7.1,通过或 php -v命令确认7.4更新成功,让人疑惑。

分析

  1. 既然php -v没有问题,那么就是web server相关使用的版本没更新,web server部分我们使用的是php-fpm。
  2. 搜索php-fpm,找到相关执行文件,确认php-fpm -v,确认是7.1。

解决

既然确认是php-fpm的问题,最简单的就是通过yum来更新php对应的php-fpm,更新后在检查,确认版本已经变成7.4。

DirectoryLister文件列表展示页面生成工具介绍

需求

寻找一款简单部署的工具,可以将服务上的文件通过页面列表展示,从而方面下载,有其他功能更好。

DirectoryLister

一款开源,开箱即用的好工具,github repo:
https://github.com/DirectoryLister/DirectoryLister

主要特点:

  1. php语言。
  2. 支持搜索。
  3. 其他见repo。

安装事项

  1. php 版本要大于>=7.2。
  2. 组件要求 zip,dom,fileinfo。
  3. cache目录要有写入权限,否则无法正常展示页面,需要通过php-fpm错误日志来定位。

使用

  1. 配置对应的php支持,一般就是设置nginx或者php-fpm相关fastcgi配置项。
  2. 需要安装在域名的根目录,在子目录会有问题。
  3. Copy .env.example to .env。
  4. Edit the configuration values in .env。
  5. 放在根目录后,可能会暴露不想暴露的文件和目录,在根目录创建 .hidden文件,配置语法和git的ignore文件一样,就可以实现相关文件目录的隐藏。

done!

wordpress 插件异常导致无法登录

问题

出现错误时,无法通过admin页面登录到后台面板,而且页面的错误提示也有限,无法确认具体问题。这个时候,只能通过ssh来尝试解决。

解决

  1. 开启wordpress 调试:
    https://wordpress.org/support/article/debugging-in-wordpress/
    只需修改 wp-config.php中下面的开关就可以在页面看到进一步的调试信息:

    // Enable WP_DEBUG mode
    define( 'WP_DEBUG', true );

    这样我们就能在页面看到想象的错误提示。

  2. 当发现是插件错误导致时,因为此时已经无法登录后台的插件管理页面,这时,直接删除wp-content目录下对应的插件目录就可以,这时wordpress会检测插件失效,从而跳过插件代码逻辑。

如果还有其他问题,可以进一步结合php nginx等日志进一步分析。

unraid安装windows10

最近在体验unraid。打算装一个windows,用来运行一些window专有或者体验好的软件。因为开始各种装不上,所以期间参考文章,体验了了灯大的精简img,发现实在用不下去,所以还是研究自己怎么装。

以下文章为自己的的安装过程,因为硬件或者版本可能会有差异,请读者自行消化。

windows 的下载

个人建议下载微软的原版,具体自行搜索。

硬件配置

nas-inf

windows10 vm config

windows10 vm config

安装

按照类似的配置正常应该能进入window的那个窗口的界面,显示进入了安装引导过程,如果没有反应或者其他错误,请尝试更改Bus类型,和vDisk。如果安装中断,那么会导致再次启动直接启动系统无法成功,请删除vDisk,重新创建。

无法找到安装磁盘

安装中常见的问题,在正常按照引导进入安装界面过程时,无法找到磁盘,解决方案是安装虚拟io驱动,分别选择以下驱动,并进行下一步:
Balloon
NetKVM
vioserial
viostor(一定要最后加载这个驱动)
然后就看到你分配的容量的虚拟磁盘了,然后正常分区和格式化就可以正常安装了。

再安装成功进入windows界面后,建议安装驱动盘中的qemu-ga-x64.msi

安装成功

window10