react native ios版本熱更新


react native 熱更新的好處

js腳本代碼改變了,比如對ui進行了一些修改,客戶端要是想更新的話,如果直接下載apk 或者ipa,一個是浪費流量,還有比較麻煩

熱更新只要下載打包好的bundle 文件,然后進行替換就可以了

思路比較簡單,客戶端跟服務端都維持 一個bundle版本信息,如果服務端的版本比客戶端的 版本新就下載,然后替換掉 重新渲染就OK了

具體實現,如果沒有 熱更新,載入bundle的代碼是這樣的

jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];

如果加入熱更新,是這樣的

NSURL *jsCodeLocation=nil;

  jsCodeLocation=[self getBundle];
  
  if(jsCodeLocation==nil)
  {
    jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
  }
getBundle 函數就包含加載 服務端獲取到的bundle 的邏輯

-(NSURL *) getBundle
{
  NSString* ss=@"#####";//服務端bundle版本號的地址
  NSString* str = [self httpGet:ss];
  NSString *pathDocuments=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
  
  NSString *createPath=[NSString stringWithFormat:@"%@/%@",pathDocuments,@"version.txt"];//用文件名補全路徑
  Boolean bb=false;
  NSFileManager *defaultManager;
  defaultManager = [NSFileManager defaultManager];
  NSURL *nsurl=nil;
  if ([[NSFileManager defaultManager] fileExistsAtPath:createPath])//判斷文件是否已存在
  {
     NSString* fileContents = [NSString stringWithContentsOfFile:createPath encoding:NSUTF8StringEncoding error:nil];
    int a=[str intValue];//服務端bundle版本號
    int b=[fileContents intValue];//客戶端bundle版本信息
    if(a>b)//如果服務端的bundle版本比加大,就刪除客戶端的bundle,然后更新成服務端的
    {
      if ([[NSFileManager defaultManager] fileExistsAtPath:createPath])//判斷文件是否已存在
      {
        [defaultManager removeItemAtPath:createPath error:NULL];
      }
      [self storeFile:@"version.txt" content:str];
      bb=true;
    }
    else//如果發現下載的bundle文件不存在,也要下載更新
    {
      createPath=[NSString stringWithFormat:@"%@/%@",pathDocuments,@"main.jsbundle"];
      if (![[NSFileManager defaultManager] fileExistsAtPath:createPath])//判斷文件是否已存在
      {
        bb=true;
      }
    }
  }
  else//如果客戶端的bundle是空,也要下載
  {
   [self storeFile:@"version.txt" content:str];
    bb=true;
  }
  if (bb==true) {
    createPath=[NSString stringWithFormat:@"%@/%@",pathDocuments,@"main.jsbundle"];
   if ([[NSFileManager defaultManager] fileExistsAtPath:createPath])//判斷文件是否已存在
    {
      [defaultManager removeItemAtPath:createPath error:NULL];
    }
    ss=@"####";//服務端bundle文件的地址
    str = [self httpGet:ss];
    
    NSString *fileName=[self storeFile:@"main.jsbundle" content:str];
    nsurl=[NSURL fileURLWithPath:fileName];//這是bundle 文件的路徑
    
  }
  else{
    createPath=[NSString stringWithFormat:@"%@/%@",pathDocuments,@"main.jsbundle"];
    nsurl=[NSURL fileURLWithPath:createPath];//這是bundle 文件的路徑
  }
  return nsurl;
  
}
-(NSString *) httpGet:(NSString *)ss
{
  //第一步,創建URL
  NSURL *url = [NSURL URLWithString:ss];
  
  //第二步,通過URL創建網絡請求
  NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
  //NSURLRequest初始化方法第一個參數:請求訪問路徑,第二個參數:緩存協議,第三個參數:網絡請求超時時間(秒)
  /*其中緩存協議是個枚舉類型包含:
   NSURLRequestUseProtocolCachePolicy(基礎策略)
   NSURLRequestReloadIgnoringLocalCacheData(忽略本地緩存)
   NSURLRequestReturnCacheDataElseLoad(首先使用緩存,如果沒有本地緩存,才從原地址下載)
   NSURLRequestReturnCacheDataDontLoad(使用本地緩存,從不下載,如果本地沒有緩存,則請求失敗,此策略多用於離線操作)
   NSURLRequestReloadIgnoringLocalAndRemoteCacheData(無視任何緩存策略,無論是本地的還是遠程的,總是從原地址重新下載)
   NSURLRequestReloadRevalidatingCacheData(如果本地緩存是有效的則不下載,其他任何情況都從原地址重新下載)*/
  //第三步,連接服務器
  NSData *received = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
  
  NSString *str = [[NSString alloc]initWithData:received encoding:NSUTF8StringEncoding];
  return str;
}
//存儲文件
-(NSString *)storeFile:(NSString *)fileName content:(NSString *)writeContent
{
  NSString *pathDocuments=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
  
  NSString *createPath=[NSString stringWithFormat:@"%@/%@",pathDocuments,fileName];//用文件名補全路徑
  NSError *ReadFileError;
  NSString *readContent ;
  NSData *data ;
  if ([[NSFileManager defaultManager] fileExistsAtPath:createPath])//判斷文件是否已存在
  {
    if (nil == writeContent) {
      readContent = [NSString stringWithContentsOfFile:createPath encoding:NSUTF8StringEncoding error:&ReadFileError];
    }else{
      data = [writeContent dataUsingEncoding:NSUTF8StringEncoding];//新文件的初始數據
      [[NSFileManager defaultManager] createFileAtPath:createPath contents:data attributes:nil];//創建文件
      readContent = [NSString stringWithContentsOfFile:createPath encoding:NSUTF8StringEncoding error:&ReadFileError];
    }
  }
  else
  {
    if (nil == writeContent) {
      return nil;
    }else{
      data = [writeContent dataUsingEncoding:NSUTF8StringEncoding];//新文件的初始數據
      [[NSFileManager defaultManager] createFileAtPath:createPath contents:data attributes:nil];//創建文件
      readContent = [NSString stringWithContentsOfFile:createPath encoding:NSUTF8StringEncoding error:&ReadFileError];
    }
  }
  return createPath;
}

以上就是主要代碼,有注釋說明意思

ios bundle打包腳本如下

react-native bundle --entry-file index.ios.js --bundle-output ./bundle/index.ios.bundle --platform ios --assets-dest ./bundle --dev false

 上面的下載讀本地緩存 會更新不了,更正下,應該選這個

NSURLRequestReloadIgnoringLocalAndRemoteCacheData(無視任何緩存策略,無論是本地的還是遠程的,總是從原地址重新下載)

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM