本文作者 Jinkey(微信公众号 jinkey-love,官网 https://jinkey.ai)
原文链接 https://jinkey.ai/post/tech/swift-jie-ru-wei-xin-mars_xlogger-tian-keng-zhi-nan
文章允许非篡改署名转载,删除或修改本段版权信息转载的,视为侵犯知识产权,我们保留追求您法律责任的权利,特此声明!

示例代码地址:
https://github.com/Jinkeycode/XloggerSwiftDemo

支持开源,但吐槽一句,作为公司级开源项目,文档有点少哦,希望微信的开发大大能尽快补上。

Step 1 下载代码

使用 git clone 或者直接下载 zip,解压后进入目录 mars-master/mars/libraries,看到有一个 build_apple.py 的文件

Step 2 编译Mars

在终端进入工程目录输入

python build_apple.py

然后回答一系列问题
第一个问题

input prefix for save directory. like trunk,br,tag:
输入保存目录的前缀

第二个问题

Enter menu:

  1. build mars for iphone.

  2. build mars for iphone with bitcode.

  3. build xlog for iphone

  4. build mars for macosx.

  5. build all.

  6. exit.

选择 3 回车,报错:

xcodebuild: error: UnkNown build action 'Center/marsmaster/mars/libraries/../marslogiphone.xcodeproj'.

!!!!clean iphoneos10.0 Failed!!!

看看控制台打印的记录发现路径和我目录的路径不一致:

Download Center/mars-master/mars/mars-log-iphone.xcodeproj

对比之后发现一个大坑:build_apple.py 的路径不能有空格!!!

编译成功之后生成一个以你自定义前缀的目录,里面就有 framwork:

从 mars-log-iphone.xcodeproj 的 iOS deployment target 来看,最低支持 iOS 7.

Step 3 引入项目

将 mars.framework 拖入 Linked Frameworks and Libraries 并且加入其他四个系统库,弄好之后如下:

20170102 早上的 mars.framework 漏了一个斜杠,会导致无法编译,20170102 下午官方已修复,请确保你把版本更新到你看这篇文章时候的最新版本。

Step 4 引入辅助库

将编译得到的 log_crypt.cc(log_crypt.cc.rewriteme 直接重命名去掉 .rewriteme)、log_crypt.h 拖入 Xcode 左侧目录结构,弹出的对话框勾选“copy items if needed”

mars-master/samples/iOS/iOSDemo/Component 目录下的 LogHelper.hLogHelper.mmLogUtil.hLogUtil.m 拖入 Xcode 左侧目录结构,弹出的对话框勾选 “copy items if needed”
为了整洁,对几个文件进行了分组

最终的文件目录和工程目录如下:(忽略 Appender2SwiftBridge), 下文会说到)

Step 5 桥接 Objective-C 和 C++ 代码

新建两个文件(不想写的可以直接下载 Github 下的示例代码拖入工程)
appender-swift-bridge.h

//  Created by Jinkey on 2017/1/2.
//  copyright © 2017年 Jinkey. All rights reserved.
//  appender-swift-bridge.h

#include <stdio.h>
#import <Foundation/Foundation.h>
#import "LogUtil.h"

typedef NS_ENUM(NSUInteger,XloggerType) {
    
    debug,info,warning,error,};

@interface JinkeyMarsBridge: NSObject

- (void)initXlogger: (XloggerType)debugLevel releaseLevel: (XloggerType)releaseLevel path: (Nsstring*)path prefix: (const char*)prefix;
- (void)deinitXlogger;

- (void)log: (XloggerType) level tag: (const char*)tag content: (Nsstring*)content;

@end

appender-swift-bridge.mm

//  Created by Jinkey on 2017/1/2.
//  copyright © 2017年 Jinkey. All rights reserved.
//  appender-swift-bridge.mm

#import "appender-swift-bridge.h"
#import <mars/xlog/appender.h>
#import <mars/xlog/xlogger.h>
#import <sys/xattr.h>

@implementation JinkeyMarsBridge

// 封装了初始化 Xlogger 方法
// initialize Xlogger
-(void)initXlogger: (XloggerType)debugLevel releaseLevel: (XloggerType)releaseLevel path: (Nsstring*)path prefix: (const char*)prefix{
    
    Nsstring* logPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) objectAtIndex:0] stringByAppendingString:path];
    
    // set do not backup for logpath
    const char* attrName = "io.jinkey";
    u_int8_t attrValue = 1;
    setxattr([logPath UTF8String],attrName,&attrValue,sizeof(attrValue),0);
    
    // init xlog
    #if DEBUG
    switch (debugLevel) {
        case debug:
            xlogger_SetLevel(kLevelDebug);
        case info:
            xlogger_SetLevel(kLevelInfo);
        case warning:
            xlogger_SetLevel(kLevelWarn);
        case error:
            xlogger_SetLevel(kLevelError);
        default:
            break;
    }
    appender_set_console_log(true);
    #else
    switch (releaseLevel) {
        case debug:
            xlogger_SetLevel(kLevelDebug);
        case info:
            xlogger_SetLevel(kLevelInfo);
        case warning:
            xlogger_SetLevel(kLevelWarn);
        case error:
            xlogger_SetLevel(kLevelError);
        default:
            break;
    }
    appender_set_console_log(false);
    #endif
    appender_open(kAppednerAsync,[logPath UTF8String],prefix);
    
}

// 封装了关闭 Xlogger 方法
// deinitialize Xlogger
-(void)deinitXlogger {
    appender_close();
}


// 利用微信提供的 LogUtil.h 封装了打印日志的方法
// print log using LogUtil.h provided by Wechat
-(void) log: (XloggerType) level tag: (const char*)tag content: (Nsstring*)content{
    
    Nsstring* levelDescription = @"";
    
    switch (level) {
        case debug:
            LOG_DEBUG(tag,content);
            levelDescription = @"Debug";
            break;
        case info:
            LOG_INFO(tag,content);
            levelDescription = @"Info";
            break;
        case warning:
            LOG_WARNING(tag,content);
            levelDescription = @"Warn";
            break;
        case error:
            LOG_ERROR(tag,content);
            levelDescription = @"Error";
            break;
        default:
            break;
    }
    
    #if DEBUG
    NSLog(@"[%s][%s]%@%@",levelDescription,tag,content,@">>>该行 log 由于目前Xlogger 在控制台输出中文会乱码而使用 NSlog 输出的,不会记录到 Xlogger 文件中且在 Release 版本中不会输出到控制台");
    #endif
}

@end

Xlogger 目前在 Xcode 的控制台输出中文会乱码,不清楚是 Xcode 还是 Xlogger 的问题,待官方解决吧
补充更新,微信在20170103下午已经修复了中文乱码的问题,所以示例代码中我去掉了:

#if DEBUG
NSLog(@"[%s][%s]%@%@",不会记录到 Xlogger 文件中且在 Release 版本中不会输出到控制台");
#endif

Step 6 桥接 Swift 和 Objective-C

新建文件 <工程名>-Bridging-Header.h,我这里的示例工程名为XloggerSwiftDemo 所以新建文件XloggerSwiftDemo-Bridging-Header.h
写入以下代码

#import "appender-swift-bridge.h"

至此,Xlogger 的基本方法已暴露给 Swift 使用了。

Step 7 初始化和反初始化 Xlogger

打开 AppDelegate.swift
在 didFinishLaunchingWithOptions 方法中加入以下代码初始化

var jmb = JinkeyMarsBridge()
jmb.initXlogger(.debug,releaseLevel: .info,path: "/jinkeylog",prefix: "Test")

其中 initXlogger 的第一个参数是开发环境显示日志的级别;第二个参数是生产环境显示日志的级别;第三个是储存路径日志的级别,我在示例代码中封装了 debug,info,warning,error 四个级别;第四个参数是输入日志文件的前缀。

在 applicationWillTerminate 方法中加入以下代码反初始化

JinkeyMarsBridge().deinitXlogger()

Step 8 打印日志

在想要打印日志的地方写入以下代码

var jmb = JinkeyMarsBridge()
jmb.log(.debug,tag: "JinkeyIO",content: "我的公众号是 jinkey-love")

这里为了说明方便而在打印日志的地方实例化,生产环境使用建议使用单例模式实例化JinkeyMarsBridge

Xcode8 默认会在控制台打印一大堆日志,为了演示效果最佳,可以点击 Xcode 选择Product->Scheme->Edit Scheme

在弹出的窗口中Environment Variables 下添加 0S_ACTIVITY_MODE disable,如下图

Step 9 分析日志

通过以下代码在控制台打印出模拟器中示例程序沙盒所在的目录

var logPath = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask,true)[0]
print(logPath)

通过 MacOS 的 Finder-前往文件夹粘贴该路径打开

可以看到以下目录结构

Test.mmap2 是缓存文件,不用关心,我们需要的是 Test_20170103.xlog 文件,我们把这个文件使用Mars提供的 Python 脚本进行解密。脚本在mars-master/mars/log/crypt/decode_mars_log_file.py
把 decode_mars_log_file.py 和 Test_20170103.xlog 拉到桌面,从 MacOS 的终端使用 cd 命令进入桌面,再输入命令

python decode_mars_log_file.py Test_20170103.xlog

接着会在桌面生成一个 Test_20170103.xlog.log 文件,用文本编辑工具打开即可看到打印的日志

Swift 接入微信 Mars_Xlogger 填坑指南——Jinkey 原创的更多相关文章

  1. three.js模拟实现太阳系行星体系功能

    这篇文章主要介绍了three.js模拟实现太阳系行星体系功能,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

  2. HTML5页面无缝闪开的问题及解决方案

    这篇文章主要介绍了HTML5页面无缝闪开方案,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. ios – Xcode警告:“没有处理文件的规则”和“找不到目录”

    重命名我的项目文件夹后,我收到以下错误消息:什么可能出错?解决方法关于第一个警告,您可以在项目设置中的“构建阶段”中检查XCode,即头文件不会出现在“编译源”列表中.

  4. 你如何将xcode项目转换为cocoapod?

    我有一段代码,我发现我在多个不同的项目中重复使用,所以我想把它变成一个cocoapod并使用私人cocoapod仓库.我的问题是如何将xcode项目设置为cocoapod?它应该是一个静态库还是一个带有appdelegate的空“项目”?

  5. ios – 如何将文件添加到主包的/ Library / Sounds目录中?

    根据Apple’sdocumentation,/Library/Sounds中的声音文件将在尝试播放声音时由系统搜索.如何将声音文件添加到此文件夹?适用于iOS的正确文档应为here总之,您只需将声音文件作为应用程序包的非本地化资源添加到项目中.

  6. ios – 资产目录与文件夹参考:何时使用其中一个?

    我可以将文件放入Assets.xcassets,或者我可以将文件放入文件夹引用.我何时会选择一个而不是另一个?

  7. ios – 为什么,将nil作为参数从Objc C发送到swift类初始化器,用新对象替换nil参数

    除非属性本身被声明为nonnull:

  8. ios – 使用Swift的Lumberjack 2.0记录器

    我以前使用物镜C的Lumberjack记录器,我喜欢它.现在我开始学习Swift,我不能在那里使用我最喜欢的记录器.有人可以一步一步地写出我能做到的事吗?在Lumberjack2.0发布之前,我尝试在这里找到一些东西,但所有主题都是自定义包装器.我做了什么:>我用Cocoapods添加了Lumberjack;>我将“#import”添加到Bridging-Header文件中.我不知道接下来该怎么办?因为在ObjC中我有宏:staticconstintddLogLevel=LOG_LEVEL_INFO;el

  9. ios – 从icloud备份中限制sqlite-wal和sqlite-shm

    我是第一次使用coredata,我必须从文档目录中的iCloud备份限制sqlitedb文件,我使用下面的代码完成了它//阻止iCloud备份文档目录文件夹现在我不明白的是,我们还需要从icloud备份中限制sqlite-wal和sqlite-shm文件,如果是,那么如何从icloud备份限制sqlite-wal和sqlite-shm文件我想要一个解决方案,而无需从文档目录文件夹中更改sqlitedb位置…

  10. ios – 在Swift中对MKCircle进行子类化

    我想通过添加另一个String属性来继承MKCircle,我们称之为“代码”.这个属性不是可选的和常量的,所以我必须从初始化器设置它,对吧?有没有办法定义一个单一的便利初始化器,在这种情况下需要3个参数?本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部