温故而知新-0313-0317

1.NSBundle

最近有在APP中以组件运行动态库的需求,遂调研了下如何实现。首先需要用到NSBundle来定位我们组件中带入的动态库。 官方对NSBundle的解释:

A representation of the code and resources stored in a bundle directory on disk.

Apple uses bundles to represent apps, frameworks, plug-ins, and many other specific types of content. Bundles organize their contained resources into well-defined subdirectories, and bundle structures vary depending on the platform and the type of the bundle. By using a bundle object, you can access a bundle’s resources without knowing the structure of the bundle. The bundle object provides a single interface for locating items, taking into account the bundle structure, user preferences, available localizations, and other relevant factors.

Any executable can use a bundle object to locate resources, either inside an app’s bundle or in a known bundle located elsewhere. You don’t use a bundle object to locate files in a container directory or in other parts of the file system.

官方提供的用法:

The general pattern for using a bundle object is as follows:

  1. Create a bundle object for the intended bundle directory.
  2. Use the methods of the bundle object to locate or load the needed resource.
  3. Use other system APIs to interact with the resource.

首先在组件中建立bundle directory,yourResources.bundle,在此路径下放入我们需要运行的动态库,同时在组件的podspec中加入此路径,这样我们APP在运行中才可以获取到此路径下的资源: s.resource = '****/yourResources.bundle' 做好前置准备后,就可以在代码中通过以下方式获取到你的动态库资源了:

NSBundle *main = [NSBundle mainBundle];
NSString *resourcePath = [main pathForResource:@"yourResources/yourDylib" ofType:@"dylib"];

2.dlopen

获取到资源后下面就行装载运行动态库了,Linux提供了一套API来动态装载库。下面列出了这些API:

dlopen:该函数将打开一个新库,并把它装入内存。该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的。这种机制使得在系统中添加或者删除一个模块时,都不需要重新进行编译。
dlsym:在打开的动态库中查找符号的值。
dlclose:关闭动态库。
dlerror:返回一个描述最后一次调用dlopen、dlsym,或dlclose的错误信息的字符串。

在我们拿到动态库的resourcePath后,直接使用dlopen,就可以运行啦:

void *handle = dlopen(resourcePath, RTLD_LAZY);

3.动态库的链接地址

同时我们还需要注意不要忘记修改动态库的链接地址,dylib的id和引用路径是指dylib文件的唯一标识和被其他文件引用时的查找路径]。我们可以使用otool命令查看dylib的id和引用路径,例如:

otool -L libtest.dylib

同时我们可以使用install_name_tool命令修改dylib的id和引用路径,例如:

install_name_tool -id @rpath/libtest.dylib libtest.dylib

这样就把dylib的id改为了@rpath/libtest.dylib,表示在运行时根据@rpath变量来查找dylib文件。


4.python删除元素

本周犯了一个低级错误,删除元素没有注意方法,导致list出现了奇怪了现象,排查了很久,最终才注意到是删除元素存在问题。错误示范:

for element in element_list:
	if element == '***':
		del element

以上是经典的错误示范,Python list在for循环中删除元素有几种方法,但是要注意不要直接修改正在迭代的列表,否则可能会出现意外的结果或错误

一种方法是创建一个新的列表,只包含你想要保留的元素,然后用新的列表替换原来的列表。例如:

ls = [1, 2, 3, 4, 5]
ls = [x for x in ls if x != 3] # 删除所有等于3的元素
print(ls) # [1, 2, 4, 5]

另一种方法是使用list.remove()方法,在for循环之外逐个删除你不想要的元素。例如:

ls = [1, 2, 3, 4, 5]
to_remove = [3] # 要删除的元素列表
for x in to_remove:
    ls.remove(x) # 删除第一个等于x的元素
print(ls) # [1, 2, 4, 5]

我最后采用的方式是倒序删除:

ls = [1, 2, 3, 4, 5]
to_remove = [3] # 要删除的元素列表
for i in range(len(ls) - 1, -1, -1): # 倒序遍历列表
    if ls[i] in to_remove: # 如果元素在要删除的列表中
        del ls[i] # 删除该元素
print(ls) # [1, 2, 4, 5]

5.prompt engineering

可以参考:

https://zhuanlan.zhihu.com/p/611137227
https://zhuanlan.zhihu.com/p/488279606


6.iOS访问自定义类别的私有属性:

在Objective-C中,可以使用KVC(键值编码)来访问私有变量。KVC是Objective-C的一种机制,可以通过键名称访问对象的属性,即使这些属性是私有的。

# 私有方法及属性定义
@interface Person : NSObject
@property (nonatomic, strong) NSString *name;
@end

@implementation Person
{
    Address *_address;
}
@end

@interface Address : NSObject
@property (nonatomic, strong) NSString *street;
@property (nonatomic, strong) NSString *city;
@end

@implementation Address
@end
Person *person = [[Person alloc] init];
Address *address = [[Address alloc] init];
address.street = @"123 Main St.";
address.city = @"Anytown";
[person setValue:address forKey:@"_address"];

Address *personAddress = [person valueForKey:@"_address"];
NSLog(@"%@, %@", personAddress.street, personAddress.city); // Output: 123 Main St., Anytown

需要注意的是,访问私有变量可能会违反封装性原则,可能会导致代码的不稳定性。建议在实际开发中尽量避免访问私有变量,尽可能使用类提供的公共接口来进行操作。


7.throttle debounce

lodash 提供了`debounce`和`throttle`两个方法。文档上是这么描述这两个方法的:
  • throttle 创建一个节流函数,在 wait 毫秒内最多执行 func 一次;
  • debounce 创建一个防抖函数,该函数会从上一次被调用后,延迟 wait 毫秒后调用 func

可以通过下图理解两个函数及一些参数的作用:

可以把throttle看作是地铁,debounce看作是电梯,throttle的不管上了多少人,什么时候上的,时间一到就按时发车。debounce就像电梯,第一个人进去以后,如果在10s(假设值)内有人进来,电梯又要等10s才关门,以次类推。直到电梯装满,人们都主动等下一趟了,电梯才会关门。
comments powered by Disqus
Copyright © 2024 RainPot