{"id":18974663,"url":"https://github.com/pujiaxin33/jxcaptain","last_synced_at":"2025-04-19T16:41:00.970Z","repository":{"id":56916707,"uuid":"203730896","full_name":"pujiaxin33/JXCaptain","owner":"pujiaxin33","description":"像美国队长一样威猛的应用调试工具箱！","archived":false,"fork":false,"pushed_at":"2021-07-01T02:07:31.000Z","size":321,"stargazers_count":27,"open_issues_count":2,"forks_count":9,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-29T10:22:13.240Z","etag":null,"topics":["debug","ios","performance","tool","tools"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pujiaxin33.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-08-22T06:42:16.000Z","updated_at":"2024-11-13T10:03:05.000Z","dependencies_parsed_at":"2022-08-21T03:50:42.141Z","dependency_job_id":null,"html_url":"https://github.com/pujiaxin33/JXCaptain","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pujiaxin33%2FJXCaptain","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pujiaxin33%2FJXCaptain/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pujiaxin33%2FJXCaptain/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pujiaxin33%2FJXCaptain/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pujiaxin33","download_url":"https://codeload.github.com/pujiaxin33/JXCaptain/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249223936,"owners_count":21232833,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["debug","ios","performance","tool","tools"],"created_at":"2024-11-08T15:15:43.842Z","updated_at":"2025-04-16T09:34:03.486Z","avatar_url":"https://github.com/pujiaxin33.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"![](https://github.com/pujiaxin33/JXExampleImages/blob/master/JXCaptain/JXCaptain_icon_shield.png)\n# JXCaptain\n\n像美国队长一样威猛的应用调试工具箱！\n\n# 前言\n\n每个稍有规模的APP都会有一些开发测试功能，比如切换服务器环境、浏览沙盒文件、查看页面帧率以及接口请求日志等。之前项目内部前前后后实现了一些功能，直到看到了滴滴开源的[DoraemonKit](https://github.com/didi/DoraemonKit)。被它完整的功能实现所折服，引入之后真的就拥有了强大的工具集合。在是否要引入`DoraemonKit`之际，我陷入了深深的思考。第一，项目几乎是纯Swift语言开发，并且尽量不再去引用OC的库。第二，内部已经实现了许多功能，稍加改造也能转正为人名服务。所以，就借鉴了`DoraemonKit`的思路和部分代码，重新实现了`JXCaptain`，一个强大的Swift编写的应用调试工具箱。\n\n取名`Captain`队长的含义，就是把一个个功能比喻为战士，队长就是指挥这些战士的精神领袖。有了队长就能所向披靡，战无不胜！\n\n# 预览\n\n\u003cdiv align=center\u003e\u003cimg src=\"https://github.com/pujiaxin33/JXExampleImages/blob/master/JXCaptain/JXCaptain.png\" width=\"364\" height=\"761\" /\u003e\u003c/div\u003e\n\n# 功能模块\n\n## 常用工具\n\n- **【App信息】** 快速查看手机信息，App 信息，权限信息的渠道，避免去手机设置查找或者查看项目源代码的麻烦；\n- **【沙盒浏览】** 沙盒目录浏览，支持图片、视频、sql数据库等文件预览，支持文件的共享；\n- **【Crash日志】** 捕获Crash，并将日志通过文件形式保存在沙盒里面；\n- **【H5任意门】** 开始输入H5地址进行网页功能验证；\n- **【UserDefauls】** 查看`UserDefauls.shared`记录的键值对数据；\n\n## 性能检测\n\n- **【FPS】** 顶部状态栏实时显示当前的帧率；\n- **【内存】** 顶部状态栏实时显示当前的内存占用；\n- **【CPU】** 顶部状态栏实时显示当前的CPU使用率；\n- **【卡顿】** 当页面出现卡顿是，保存当时的堆栈信息，使用`BSBacktraceLogger`获取堆栈信息；\n- **【流量】** 监听APP和网页的接口调用，查看Header、Response等信息；\n\n\n# 自定义工具\n\n## 实现`Soldier`协议\n\n```Swift\npublic class UserDefaultsSoldier: Soldier {\n    public static let shared = UserDefaultsSoldier()\n    //工具列表显示的名字\n    public var name: String\n    //归属于哪个团队？比如：常用工具、性能检测或者自定义团队名\n    public var team: String\n    //工具列表显示的icon\n    public var icon: UIImage?\n    //如果你不适用默认的name加icon的显示，直接创建新视图赋值给contentView即可\n    public var contentView: UIView?\n    //是否监听到了新的事件，比如Crash日志捕获到了新的Crash，将hasNewEvent设置为true，就会显示红点提示\n    public var hasNewEvent: Bool = false\n\n    public init() {\n        name = \"UserDefaults\"\n        team = \"常用工具\"\n        icon = ImageManager.imageWithName(\"JXCaptain_icon_app_user_defaults\")\n    }\n    //APP启动之后会调用该方法，用于启动当前工具的工作。比如帧率检测，调用prepare之后就开始检测帧率并显示到顶部状态了。\n    public func prepare() { }\n    //用点击了工具列表的Icon之后，就行页面的调整。一般工具都会有一个进行配置的Dashboard页面\n    public func action(naviController: UINavigationController) {\n        naviController.pushViewController(UserDefaultsKeyValuesListViewController(defaults: UserDefaults.standard), animated: true)\n    }\n}\n```\n\n## 添加新的`Soldier`\n\n```Swift\nCaptain.default.enqueueSoldiers([ServerEnvironmentSoldier()])\n```\n\n## 配置已有的`Soldier`\n\n```Swift\nCaptain.default.configSoldierClosure = { (soldier) in\n    if let websiteEntry = soldier as? WebsiteEntrySoldier {\n        //设置H5任意门默认网址\n        websiteEntry.defaultWebsite = \"https://www.baidu.com\"\n        //设置H5任意门自定义落地页面，比如项目有自定义WKWebView、有JS交互逻辑等\n        websiteEntry.webDetailControllerClosure = { (website) in\n            return UIViewController()\n        }\n    }\n    if let anr = soldier as? ANRSoldier {\n        //设置卡顿时间阈值，单位秒\n        anr.threshold = 2\n    }\n    if let crash = soldier as? CrashSoldier {\n        //自定义处理crash信息，可以存储到本地，下次打开app再传送到服务器记录\n        crash.exceptionReceiveClosure = { (signal, exception, info) in\n            if signal != nil {\n                print(\"signal crash info:\\(info ?? \"\")\")\n            }else if exception != nil {\n                print(\"exception crash info:\\(info ?? \"\")\")\n            }\n        }\n    }\n}\n```\n\n## 启动工具\n\n```Swift\nCaptain.default.prepare()\n```\n\n# `Captain`的显示与隐藏\n\n可以监听摇一摇、或者在Window上面添加两指连击4次，就显示`Captain`。调用如下代码即可：\n```Swift\nCaptain.default.show()\n```\n\n隐藏`Captain`调用如下代码：\n```Swift\nCaptain.default.hide()\n```\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpujiaxin33%2Fjxcaptain","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpujiaxin33%2Fjxcaptain","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpujiaxin33%2Fjxcaptain/lists"}