XuqmGroup-RNSDK/packages/update/ios/XuqmBundleModule.m
XuqmGroup 07b08a4f5a feat: T-B01~B04 — XuqmBundleModule + onProgress + JSBridge/厂商文档
T-B01: XuqmBundleModule 原生模块
- Android: XuqmBundleModule.java(文件读写/manifest/路径)
- iOS: XuqmBundleModule.m(对应实现)
- JS: NativeBundle.ts 封装
- 注册到 XuqmUpdatePackage

T-B02: downloadPluginBundle 添加 onProgress
- 使用 ReadableStream 实现下载进度追踪
- checkAndCachePlugin 同步支持 onProgress

T-B03: XWebView JSBridge 标准接口文档
- docs/XWebView-JSBridge.md
- H5→RN 消息协议 / RN→H5 通信
- 下载处理 / Dialog 覆盖 / 标准 Bridge 接口

T-B04: PushSDK Android 厂商集成文档
- docs/PushSDK-厂商集成.md
- 6 厂商配置步骤 / ProGuard 规则 / 调试指南
2026-06-15 02:36:11 +08:00

117 行
4.5 KiB
Objective-C

#import <React/RCTBridgeModule.h>
@interface XuqmBundleModule : NSObject <RCTBridgeModule>
@end
@implementation XuqmBundleModule
RCT_EXPORT_MODULE()
- (NSString *)bundleDir {
NSString *appSupport = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) firstObject];
NSString *dir = [appSupport stringByAppendingPathComponent:@"rn-bundles"];
[[NSFileManager defaultManager] createDirectoryAtPath:dir withIntermediateDirectories:YES attributes:nil error:nil];
return dir;
}
- (NSString *)bundlePathForModule:(NSString *)moduleId {
NSString *filename = [NSString stringWithFormat:@"%@.ios.bundle", moduleId];
return [[self bundleDir] stringByAppendingPathComponent:filename];
}
// ── Bundle 文件操作 ──────────────────────────────────────────────────────────
RCT_EXPORT_METHOD(bundleExists:(NSString *)moduleId
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
NSString *path = [self bundlePathForModule:moduleId];
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path];
resolve(@(exists));
}
RCT_EXPORT_METHOD(readBundle:(NSString *)moduleId
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
NSString *path = [self bundlePathForModule:moduleId];
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
reject(@"BUNDLE_NOT_FOUND", [NSString stringWithFormat:@"Bundle not found: %@", moduleId], nil);
return;
}
NSError *error = nil;
NSString *content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
if (error) {
reject(@"BUNDLE_READ_ERROR", error.localizedDescription, error);
return;
}
resolve(content);
}
RCT_EXPORT_METHOD(writeBundle:(NSString *)moduleId
source:(NSString *)source
md5:(NSString *)md5
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
NSString *path = [self bundlePathForModule:moduleId];
NSError *error = nil;
[source writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error];
if (error) {
reject(@"BUNDLE_WRITE_ERROR", error.localizedDescription, error);
return;
}
resolve(@(YES));
}
RCT_EXPORT_METHOD(deleteBundle:(NSString *)moduleId
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
NSString *path = [self bundlePathForModule:moduleId];
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
NSError *error = nil;
[[NSFileManager defaultManager] removeItemAtPath:path error:&error];
if (error) {
reject(@"BUNDLE_DELETE_ERROR", error.localizedDescription, error);
return;
}
}
resolve(@(YES));
}
RCT_EXPORT_METHOD(getBundlePath:(NSString *)moduleId
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
resolve([self bundlePathForModule:moduleId]);
}
// ── Manifest 操作 ────────────────────────────────────────────────────────────
RCT_EXPORT_METHOD(getManifest:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
NSString *path = [[self bundleDir] stringByAppendingPathComponent:@"manifest.json"];
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
resolve(@"{}");
return;
}
NSError *error = nil;
NSString *content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
if (error) {
reject(@"MANIFEST_READ_ERROR", error.localizedDescription, error);
return;
}
resolve(content);
}
RCT_EXPORT_METHOD(writeManifest:(NSString *)manifestJson
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
NSString *path = [[self bundleDir] stringByAppendingPathComponent:@"manifest.json"];
NSError *error = nil;
[manifestJson writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error];
if (error) {
reject(@"MANIFEST_WRITE_ERROR", error.localizedDescription, error);
return;
}
resolve(@(YES));
}
@end