app擴展輸出log到文件并從containing app讀取

app擴展,即appex,如today widget,network extension之類。現在有個需求是在開發擴展時,將log輸出到文件,在必要的時候獲取文件內容進行查看。此處不討論將log通過網絡傳輸到服務器的情況,也不討論使用類似CocoaLumberjack這樣的第三方庫的情況,我們簡單的使用NSLog而已。

  • 思路整理:

    • 首先,我們要能取得log文件,此處不討論通過網絡將log文件傳輸到服務器的情況。如果是普通應用,可以在xcode->devices里面通過Download container的方法,將應用數據下載到電腦上。對于擴展,雖然也有自己的沙盒,但是我并沒有找到直接將沙盒數據下載到電腦的方法。所以不考慮將log寫到擴展沙盒里面。
    • 所以考慮變通的方法,將log寫到擴展和應用都能訪問到的位置,然后在應用中讀取log并轉存到應用的沙盒,這樣就可以使用xcode直接取得log。這個都能訪問到的位置是基于擴展和應用同屬于一個app group,這樣可以使用[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:[self sharedGroupIdentifier]];獲取到這個container目錄。
    • 然后我們就只有考慮怎么將NSLog的內容寫到文件里面去了。最方便的方法是使用freopen重定向。
  • 相關代碼:

    • 擴展中的代碼:在擴展啟動時,獲取group container路徑,構造log文件路徑,并重定向stdout, stderr。
      NSURL * containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:[self sharedGroupIdentifier]];
      NSString* logFilePath = [[containerURL URLByAppendingPathComponent:@"appex.log"] path];
      freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stdout);
      freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr);
      
      重定向使用"a+"模式,將log添加到文件末尾,因此多次啟動擴展Log是累積的。
    • 應用中的代碼
      NSURL * containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:[self sharedGroupIdentifier]];
      NSString* appexLogFilePath = [[containerURL URLByAppendingPathComponent:@"appex.log"] path];
      
      //讀取appex的log內容到string
      NSString* content = [NSString stringWithContentsOfFile:appexLogFilePath encoding:NSUTF8StringEncoding error:nil];
      NSLog(@"appex log的內容是:\n%@",content);
      
      if(content.length==0){
         return;
      }
      
      //save the log to a file in document folder
      //使用當前時間命名doucments中的log文件
      NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
      [dateFormatter setDateFormat:@"yyyy-MM-dd_HH-mm-ss"];
      NSString *strDate = [dateFormatter stringFromDate:[NSDate date]];
      NSString *docLogFileName = [NSString stringWithFormat:@"%@.appex.log", strDate];
      NSString *docLogFilePath = [[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:docLogFileName];
      //將content轉存到應用沙盒documents中
      BOOL result = [content writeToFile:docLogFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
      NSLog(@"save log to:%@ result=%d",docLogFilePath,result);
      
      if(result){
         //如果成功將appex的log清空
         //clear the appex log file
         NSString *ccc=@"";
         [ccc writeToFile:appexLogFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
      }
      
      
  • 這個方法簡單的進行了log的轉存,并清除了appex的log,每次調用都生成一個新的log文件放在documents里面。需要注意的是,如果log文件很大,就不能直接讀取和保存了,需要打開一個文件流,逐步讀取和保存。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • iOS開發系列--網絡開發 概覽 大部分應用程序都或多或少會牽扯到網絡開發,例如說新浪微博、微信等,這些應用本身可...
    lichengjin閱讀 3,721評論 2 7
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,991評論 19 139
  • 一、iOS中的沙盒機制 iOS應用程序只能對自己創建的文件系統讀取文件,這個獨立、封閉、安全的空間,叫做沙盒。它一...
    tzhtodd閱讀 1,300評論 0 2
  • 1、文件的創建 -(IBAction) CreateFile { //對于錯誤信息 NSError *error;...
    東引甌越閱讀 3,472評論 0 50
  • //設置尺寸為屏幕尺寸的時候self.window = [[UIWindow alloc] initWithFra...
    LuckTime閱讀 838評論 0 0