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:
- Create a bundle object for the intended bundle directory.
- Use the methods of the bundle object to locate or load the needed resource.
- 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
- throttle 创建一个节流函数,在
wait
毫秒内最多执行func
一次; - debounce 创建一个防抖函数,该函数会从上一次被调用后,延迟
wait
毫秒后调用func
。
可以通过下图理解两个函数及一些参数的作用: