更新Xcode描述文件包含的设备UUID

更新Xcode描述文件

  • 找到 Xcode 描述文件并删除,
rm ~/Library/MobileDevice/Provisioning\ Profiles/
// XCode 16
rm ~/Library/Developer/Xcode/UserData/Provisioning\ Profiles
  • 清理工程
  • 打包

查看ipa文件包含的设备UUID

  • 修改 ipa 包后缀为 zip 并解压
  • 查看包内容,找到 embedded.mobileprovision 文件下的 ProvisionedDevices,列表显示就是所有的设备UUID
查看描述文件内容命令:(需要先进入描述文件所在目录)
security cms -D -i embedded.mobileprovision

SQLite使用总结

使用的库 FMDB

创建数据库

//数据库的路径
NSString *path = [NSString stringWithFormat:@"%@/Documents/DB.sqlite",NSHomeDirectory()];
//创建数据库
self.database = [[FMDatabase alloc] initWithPath:path];

if (self.database.open == NO) {
    NSLog(@"失败");
    
    return ;
}
NSLog(@"成功");

创建表

NSString *createSQL = [NSString stringWithFormat:@"create table if not exists %@ (id varchar(32), type int(11), create_time int(11))", kTableName];

BOOL status = [self.database executeUpdate:createSQL];
NSLog(@"status: %@", @(status));

新增数据

NSString *sql = [NSString stringWithFormat:@"insert into %@(id,type,create_time) values(?,?,?)", kTableName];
BOOL status = [_database executeUpdate:sql,@(myId),@(type), @(time)];

查询数据

NSString *sql = [NSString stringWithFormat:@"select * from %@ where id = %@", kTableName, @(myId)];
FMResultSet *set = [self.database executeQuery:sql];
while ([set next]) {
    model.myId = [set stringForColumn:@"id"];
    model.type = [set intForColumn:@"type"];
    model.createTime = [set intForColumn:@"create_time"];
    
    [resultList addObject:model];
}

更新数据

NSString *sql = [NSString stringWithFormat:@"update %@ set create_time = %@ where id = %@", kTableName, @(time), @(myId)];
BOOL status = [_database executeUpdate:sql];

删除数据

NSInteger expireTime = [NSDate timeStamp] - 60 * 60 * 24 * 30;
NSString *sql = [NSString stringWithFormat:@"delete from %@ where create_time > %@", kTableName, @(expireTime)];
BOOL status = [self.database executeUpdate:sql];

通过命令行管理数据

打开 Terminal
sqlite3 filename; 

// 查看帮助
.help
// 查看所有数据库
.databases
// 查看所有表
.tables
// 显示/隐藏 查询结果表头
.headers on|off
// 显示数据操作历史记录
.dump
// 将查询结果导出为Excel
.excel
// 以什么格式显示,推荐 column 格式显示
.mode list|line|column
// 查看配置
.show
// 退出
.quit

// 更多命令查看帮助文档...

修改数据失败问题处理

错误: attempt to write a readonly database

原因:sqlite3所在的文件夹没有读写权限,或者权限不足

解决办法:

  • 普通用户的话提升文件夹的权限
chmod 777 db.sqlite3
cd ..
chmod 777  *
  • 将项目移动到有全部权限的文件夹下启动

Link: Mac终端查看sqlite3数据库、表数据等(含sqlite可视化工具下载)

OC调用私有方法

OC调用私有方法共有以下四种方式:

以Person类为例:
#import "Person.h"
@implementation Person
- (void)privateMethod
{
    NSLog(@"privateMethod");
}
@end

一、分类

#import "Person.h"
NS_ASSUME_NONNULL_BEGIN
@interface Person (Test)
//只有声明,没有实现
- (void)privateMethod;
@end
NS_ASSUME_NONNULL_END

调用方式如下:

Person *person = [[Person alloc] init];
[person privateMethod];

二、performSelector

调用方式如下:

Person *person = [[Person alloc] init];
[person performSelector:@selector(privateMethod) withObject:nil];

三、objc_msgSend

调用方式如下:

Person *person = [[Person alloc] init];
objc_msgSend(person,@selector(privateMethod));

四、IMP

调用方式如下:

Person *person = [[Person alloc] init];
IMP imp = [person methodForSelector:@selector(privateMethod)];
    void (* tempFunc)(id target, SEL) = (void *)imp;
    tempFunc(person, @selector(privateMethod));

Link: OC调用私有方法

NSImageView图像填充模式

NSImageView图像填充模式

可以使用这个:图像将强制填充视图大小

(Aspect Fill)

imageView.imageScaling = .scaleAxesIndependently

(Aspect Fit)

imageView.imageScaling = .scaleProportionallyUpOrDown

(中心顶部)

imageView.imageScaling = .scaleProportionallyDown

您可能会发现子类更容易 NSView 并提供一个 CALayer 方面为您填充的内容。以下是 initNSView 子类的可能外观。

- (id)initWithFrame:(NSRect)frame andImage:(NSImage*)image {
  self = [super initWithFrame:frame];
  if (self) {
    self.layer = [[CALayer alloc] init];
    self.layer.contentsGravity = kCAGravityResizeAspectFill;
    self.layer.contents = image;
    self.wantsLayer = YES;
  }
  return self;
}

请注意,设置图层的顺序,然后设置 wantsLayer 非常重要(如果先设置wantsLayer,则会获得默认的背衬层)。

您可以使用一种 setImage 方法来简单地更新图层的内容。

Link:(NSImageView图像方面填充?)[https://xbuba.com/questions/23002653]

通过命令行安装iPhone模拟器

查看所有模拟器

xcrun instruments -s

通过以上命令,可以看到系统有以下模拟器:

iPhone 8 (11.2) [39E670F7-F9B0-4A1F-92E7-202EED62E66A] (Simulator)
iPhone 8 (11.2) + Apple Watch Series 3 - 38mm (4.2) [02C9E3B3-9846-4AD0-9890-B2B840811BC9] (Simulator)
iPhone 8 Plus (11.2) [18B8751C-097C-427C-9DB8-BF59FB3C1D7E] (Simulator)
iPhone 8 Plus (11.2) + Apple Watch Series 3 - 42mm (4.2) [E381F8A1-54E9-4428-BE4A-7011902C5D69] (Simulator)
iPhone SE (11.2) [D8ACFB1F-6678-4014-8993-72050939481D] (Simulator)
iPhone X (11.2) [1346D0CB-C0A7-40F9-BB8B-C095B736C696] (Simulator)

打开指定模拟器

xcrun instruments -w "iPhone 8 (11.2)"

安装指定APP

xcrun simctl install booted <app路径>

运行指定的app (com.example.app)

xcrun simctl launch booted <app identifier>

卸载指定的应用

xcrun simctl uninstall booted <app identifier>

Link: 从命令行启动Xcode模拟器

Swift 打印二进制

示例代码:

let initialBits: UInt8 = 0b00001111
let invertedBits = ~initialBits // 按位取反
let stringOfInvertedBits = String(invertedBits, radix: 2) // 转化为字符串
print(stringOfInvertedBits) // 输出结果为 11110000
let stringOfInvertedBits = String(invertedBits, radix: 2)
相当于
let stringOfInvertedBits = String(invertedBits, radix: 2, uppercase: false)

函数定义:

extension String {
    /// Create an instance representing `v` in base 10.
    public init<T : _SignedIntegerType>(_ v: T)
    /// Create an instance representing `v` in base 10.
    public init<T : UnsignedIntegerType>(_ v: T)
    /// Create an instance representing `v` in the given `radix` (base).
    ///
    /// Numerals greater than 9 are represented as roman letters,
    /// starting with `a` if `uppercase` is `false` or `A` otherwise.
    public init<T : _SignedIntegerType>(_ v: T, radix: Int, uppercase: Bool = default)
    /// Create an instance representing `v` in the given `radix` (base).
    ///
    /// Numerals greater than 9 are represented as roman letters,
    /// starting with `a` if `uppercase` is `false` or `A` otherwise.
    public init<T : UnsignedIntegerType>(_ v: T, radix: Int, uppercase: Bool = default)
}

Link:

brew安装时,取消homebrew更新

使用Mac的同学大多都用过 Homebrew 这个比较好用的工具,一个命令行就可以解决软件的下载安装问题。但同时我们也发现,每次使用 brew 命令安装软件时,brew 都会默认先更新一下,然后进行安装。特别是对于我们墙内用户及为不友好。我们可以使用一下命令来跳过 brew 安装软件时的更新:

export HOMEBREW_NO_AUTO_UPDATE=true

然后再该终端中,继续执行:

brew install xxx

Done.

Link:

Debian用Nginx搭建Webdav Server

Debian用Nginx搭建Webdav Server

安装 Nginx

sudo apt install nginx nginx-extras
mkdir -p /var/www/webdav/files # Webdav根目录

创建配置文件 /etc/nginx/conf.d/webdav.conf

server {
    listen       8080; # 端口
    server_name  webdav.Your_domain; #域名
    root /var/www/webdav/files; # 根目录,如果是其他的目录,需要注意目录权限
    client_body_temp_path /var/www/webdav/tmp;
    access_log  /var/log/nginx/webdav_access.log;
    error_log   /var/log/nginx/webdav_error.log;
    location / {
      #auth_basic "Not currently available";
      #auth_basic_user_file /etc/nginx/conf.d/.htpasswd; # htpasswd验证文件

      dav_methods PUT DELETE MKCOL COPY MOVE;
      dav_ext_methods PROPFIND OPTIONS;

      create_full_put_path on;
      dav_access user:rw group:r;

      autoindex on; # 可以在浏览器打开

      #limit_except GET {
      #  allow 115.115.0.0/32; # 允许访问的IP段,可以填自己家的IP,这样就只有你家的IP可以访问,大大增加安全性。
      #  deny  all;
      #}
   }
}

创建 .htpasswd,这是简单密码验证,因为限制了IP,所以安全性足够了。

htpasswd -c /etc/nginx/conf.d/.htpasswd UserName #自己用户名,然后输入密码

配置防火墙

如果你的防火墙默认放过所有包,可以忽略此步骤。
iptables -A INPUT -p tcp -m tcp --dport 8080 -m state --state NEW -j ACCEPT

如果想重启后防火墙依然生效,请看 这里

然后 service nginx restart 应该可以跑起来了。在浏览器输入 http://webdav.Your_domain:8080 如果要求登陆就说明成了,只需要将文件放在你设置的webdav根目录就可以访问,也可以用支持webdav的客户端访问。

Link:

Typecho Nginx下的伪静态rewrite规则

Typecho Nginx下的伪静态rewrite规则

设置 -- 永久链接 -- 是否使用地址重写功能 打开地址重写功能,如果提示 重写功能检测失败,请检查你的服务器设置,选择仍然启用此功能,勾选即可

在 Nginx server 里添加以下配置:

location / {
    index index.html index.php;
    if (-f $request_filename/index.html){
        rewrite (.*) $1/index.html break;
    }
    if (-f $request_filename/index.php){
        rewrite (.*) $1/index.php;
    }
    if (!-f $request_filename){
        rewrite (.*) /index.php;
    }
}