update
This commit is contained in:
31
Pods/CocoaDebug/Sources/Logs/CocoaDebugTool.h
generated
Normal file
31
Pods/CocoaDebug/Sources/Logs/CocoaDebugTool.h
generated
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// CocoaDebugTool.h
|
||||
// Example_Swift
|
||||
//
|
||||
// Created by man 5/8/19.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface CocoaDebugTool : NSObject
|
||||
|
||||
/// log with string,
|
||||
/// default color is white
|
||||
+ (void)logWithString:(NSString *)string;
|
||||
+ (void)logWithString:(NSString *)string color:(UIColor *)color;
|
||||
|
||||
/// log with JSON Data,
|
||||
/// default color is white,
|
||||
/// return string
|
||||
+ (NSString *)logWithJsonData:(NSData *)data;
|
||||
+ (NSString *)logWithJsonData:(NSData *)data color:(UIColor *)color;
|
||||
|
||||
/// log with Protobuf Data,
|
||||
/// default color is white,
|
||||
/// return string
|
||||
//+ (NSString *)logWithProtobufData:(NSData *)data className:(NSString *)className;
|
||||
//+ (NSString *)logWithProtobufData:(NSData *)data className:(NSString *)className color:(UIColor *)color;
|
||||
|
||||
@end
|
||||
103
Pods/CocoaDebug/Sources/Logs/CocoaDebugTool.m
generated
Normal file
103
Pods/CocoaDebug/Sources/Logs/CocoaDebugTool.m
generated
Normal file
@@ -0,0 +1,103 @@
|
||||
//
|
||||
// CocoaDebugTool.m
|
||||
// Example_Swift
|
||||
//
|
||||
// Created by man 5/8/19.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
#import "CocoaDebugTool.h"
|
||||
#import "_OCLogHelper.h"
|
||||
#import "GPBMessage+CocoaDebug.h"
|
||||
//#import "GPBMessage.h"
|
||||
|
||||
@implementation CocoaDebugTool
|
||||
|
||||
#pragma mark - logWithString
|
||||
+ (void)logWithString:(NSString *)string {
|
||||
[self logWithString:string color:[UIColor colorWithRed:1 green:1 blue:1 alpha:1]];
|
||||
}
|
||||
|
||||
+ (void)logWithString:(NSString *)string color:(UIColor *)color {
|
||||
[self finalLogWithString:string type:CocoaDebugToolTypeNone color:color];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - logWithJsonData
|
||||
+ (NSString *)logWithJsonData:(NSData *)data {
|
||||
return [self logWithJsonData:data color:[UIColor colorWithRed:1 green:1 blue:1 alpha:1]];
|
||||
}
|
||||
|
||||
+ (NSString *)logWithJsonData:(NSData *)data color:(UIColor *)color {
|
||||
NSString *string = [self getPrettyJsonStringWithData:data] ? : @"NULL";
|
||||
return [self finalLogWithString:string type:CocoaDebugToolTypeJson color:color];
|
||||
}
|
||||
|
||||
|
||||
//#pragma mark - logWithProtobufData
|
||||
//+ (NSString *)logWithProtobufData:(NSData *)data className:(NSString *)className {
|
||||
// return [self logWithProtobufData:data className:className color:[UIColor colorWithRed:1 green:1 blue:1 alpha:1]];
|
||||
//}
|
||||
//
|
||||
//+ (NSString *)logWithProtobufData:(NSData *)data className:(NSString *)className color:(UIColor *)color {
|
||||
// NSString *string = [self parsingProtobufWithData:data className:className] ? : @"NULL";
|
||||
// return [self finalLogWithString:string type:CocoaDebugToolTypeProtobuf color:color];
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma mark - tool
|
||||
|
||||
+ (NSString *)getPrettyJsonStringWithJsonString:(NSString *)jsonString {
|
||||
return [self getPrettyJsonStringWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
}
|
||||
|
||||
+ (NSString *)getPrettyJsonStringWithData:(NSData *)data {
|
||||
if (!data) {return nil;}
|
||||
|
||||
//1.pretty json
|
||||
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
|
||||
if (!dict) {return nil;}
|
||||
|
||||
NSData *prettyData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
|
||||
if (!prettyData) {return nil;}
|
||||
|
||||
NSString *prettyJsonString = [[NSString alloc] initWithData:prettyData encoding:NSUTF8StringEncoding];
|
||||
if (prettyJsonString) {
|
||||
return prettyJsonString;
|
||||
}
|
||||
|
||||
//2.protobuf
|
||||
// GPBMessage *message = [GPBMessage parseFromData:data error:nil];
|
||||
// if ([message serializedSize] > 0) {
|
||||
// return [message description];
|
||||
// }
|
||||
|
||||
//3.utf-8 string
|
||||
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
+ (NSString *)finalLogWithString:(NSString *)string type:(CocoaDebugToolType)type color:(UIColor *)color {
|
||||
[[_OCLogHelper shared] handleLogWithFile:@"XXX" function:@"XXX" line:1 message:string color:color type:type];
|
||||
return string;
|
||||
}
|
||||
|
||||
//解析Protobuf
|
||||
//+ (NSString *)parsingProtobufWithData:(NSData *)data className:(NSString *)className {
|
||||
// if (!data || !className) {return nil;}
|
||||
//
|
||||
// Class cls = NSClassFromString(className);
|
||||
// //protobuf
|
||||
// GPBMessage *obj = [cls parseFromData:data error:nil];
|
||||
// //HuiCao
|
||||
// NSString *jsonString = [obj _JSONStringWithIgnoreFields:nil];
|
||||
// if (!jsonString) {return nil;}
|
||||
//
|
||||
// NSString *prettyJsonString = [self getPrettyJsonStringWithJsonString:jsonString];
|
||||
// if (!prettyJsonString) {return nil;}
|
||||
//
|
||||
// return [prettyJsonString stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"];
|
||||
//}
|
||||
|
||||
@end
|
||||
68
Pods/CocoaDebug/Sources/Logs/LogCell.swift
generated
Normal file
68
Pods/CocoaDebug/Sources/Logs/LogCell.swift
generated
Normal file
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// Example
|
||||
// man
|
||||
//
|
||||
// Created by man 11/11/2018.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class LogCell: UITableViewCell {
|
||||
|
||||
@IBOutlet weak var labelContent: CustomTextView!
|
||||
@IBOutlet weak var viewTypeLogColor: UIView!
|
||||
|
||||
var model: _OCLogModel? {
|
||||
didSet {
|
||||
guard let model = model else { return }
|
||||
|
||||
labelContent.text = nil
|
||||
labelContent.text = model.str
|
||||
labelContent.attributedText = model.attr
|
||||
|
||||
labelContent.textContainer.lineBreakMode = NSLineBreakMode.byCharWrapping
|
||||
labelContent.textContainer.lineFragmentPadding = 0
|
||||
labelContent.textContainerInset = .zero
|
||||
labelContent.isUserInteractionEnabled = false
|
||||
|
||||
//tag
|
||||
if model.isTag == true {
|
||||
self.contentView.backgroundColor = "#007aff".hexColor
|
||||
} else {
|
||||
//isSelected
|
||||
if model.isSelected == true {
|
||||
self.contentView.backgroundColor = "#222222".hexColor
|
||||
} else {
|
||||
self.contentView.backgroundColor = .black
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class CustomTextView : UITextView {
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)!
|
||||
self.inputView = UIView.init(frame: CGRect(x: 0, y: 0, width: 1, height: 1))
|
||||
}
|
||||
|
||||
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
|
||||
if action == #selector(selectAll) {
|
||||
if let range = selectedTextRange, range.start == beginningOfDocument, range.end == endOfDocument {
|
||||
return false
|
||||
}
|
||||
return !text.isEmpty
|
||||
}
|
||||
else if action == #selector(paste(_:)) {
|
||||
return false
|
||||
}
|
||||
else if action == #selector(cut(_:)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return super.canPerformAction(action, withSender: sender)
|
||||
}
|
||||
}
|
||||
700
Pods/CocoaDebug/Sources/Logs/LogViewController.swift
generated
Normal file
700
Pods/CocoaDebug/Sources/Logs/LogViewController.swift
generated
Normal file
@@ -0,0 +1,700 @@
|
||||
//
|
||||
// Example
|
||||
// man
|
||||
//
|
||||
// Created by man 11/11/2018.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class LogViewController: UIViewController {
|
||||
|
||||
var reachEndDefault: Bool = true
|
||||
var reachEndRN: Bool = true
|
||||
var reachEndWeb: Bool = true
|
||||
|
||||
var firstInDefault: Bool = true
|
||||
var firstInRN: Bool = true
|
||||
var firstInWeb: Bool = true
|
||||
|
||||
var selectedSegmentIndex: Int = 0
|
||||
var selectedSegment_0: Bool = false
|
||||
var selectedSegment_1: Bool = false
|
||||
var selectedSegment_2: Bool = false
|
||||
|
||||
var defaultReloadDataFinish: Bool = true
|
||||
var rnReloadDataFinish: Bool = true
|
||||
var webReloadDataFinish: Bool = true
|
||||
|
||||
|
||||
@IBOutlet weak var segmentedControl: UISegmentedControl!
|
||||
@IBOutlet weak var deleteItem: UIBarButtonItem!
|
||||
|
||||
@IBOutlet weak var defaultTableView: UITableView!
|
||||
@IBOutlet weak var defaultSearchBar: UISearchBar!
|
||||
var defaultModels: [_OCLogModel] = [_OCLogModel]()
|
||||
var defaultCacheModels: Array<_OCLogModel>?
|
||||
var defaultSearchModels: Array<_OCLogModel>?
|
||||
|
||||
@IBOutlet weak var rnTableView: UITableView!
|
||||
@IBOutlet weak var rnSearchBar: UISearchBar!
|
||||
var rnModels: [_OCLogModel] = [_OCLogModel]()
|
||||
var rnCacheModels: Array<_OCLogModel>?
|
||||
var rnSearchModels: Array<_OCLogModel>?
|
||||
|
||||
@IBOutlet weak var webTableView: UITableView!
|
||||
@IBOutlet weak var webSearchBar: UISearchBar!
|
||||
var webModels: [_OCLogModel] = [_OCLogModel]()
|
||||
var webCacheModels: Array<_OCLogModel>?
|
||||
var webSearchModels: Array<_OCLogModel>?
|
||||
|
||||
|
||||
|
||||
//MARK: - tool
|
||||
//搜索逻辑
|
||||
func searchLogic(_ searchText: String = "") {
|
||||
|
||||
if selectedSegmentIndex == 0
|
||||
{
|
||||
guard let defaultCacheModels = defaultCacheModels else {return}
|
||||
defaultSearchModels = defaultCacheModels
|
||||
|
||||
if searchText == "" {
|
||||
defaultModels = defaultCacheModels
|
||||
} else {
|
||||
guard let defaultSearchModels = defaultSearchModels else {return}
|
||||
|
||||
for _ in defaultSearchModels {
|
||||
if let index = self.defaultSearchModels?.firstIndex(where: { (model) -> Bool in
|
||||
return !model.content.lowercased().contains(searchText.lowercased())//忽略大小写
|
||||
}) {
|
||||
self.defaultSearchModels?.remove(at: index)
|
||||
}
|
||||
}
|
||||
defaultModels = self.defaultSearchModels ?? []
|
||||
}
|
||||
}
|
||||
else if selectedSegmentIndex == 1
|
||||
{
|
||||
guard let rnCacheModels = rnCacheModels else {return}
|
||||
rnSearchModels = rnCacheModels
|
||||
|
||||
if searchText == "" {
|
||||
rnModels = rnCacheModels
|
||||
} else {
|
||||
guard let rnSearchModels = rnSearchModels else {return}
|
||||
|
||||
for _ in rnSearchModels {
|
||||
if let index = self.rnSearchModels?.firstIndex(where: { (model) -> Bool in
|
||||
return !model.content.lowercased().contains(searchText.lowercased())//忽略大小写
|
||||
}) {
|
||||
self.rnSearchModels?.remove(at: index)
|
||||
}
|
||||
}
|
||||
rnModels = self.rnSearchModels ?? []
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
guard let webCacheModels = webCacheModels else {return}
|
||||
webSearchModels = webCacheModels
|
||||
|
||||
if searchText == "" {
|
||||
webModels = webCacheModels
|
||||
} else {
|
||||
guard let webSearchModels = webSearchModels else {return}
|
||||
|
||||
for _ in webSearchModels {
|
||||
if let index = self.webSearchModels?.firstIndex(where: { (model) -> Bool in
|
||||
return !model.content.lowercased().contains(searchText.lowercased())//忽略大小写
|
||||
}) {
|
||||
self.webSearchModels?.remove(at: index)
|
||||
}
|
||||
}
|
||||
webModels = self.webSearchModels ?? []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - private
|
||||
func reloadLogs(needScrollToEnd: Bool = false, needReloadData: Bool = true) {
|
||||
|
||||
if selectedSegmentIndex == 0
|
||||
{
|
||||
if defaultReloadDataFinish == false {return}
|
||||
|
||||
if defaultSearchBar.isHidden != false ||
|
||||
rnSearchBar.isHidden != true ||
|
||||
webSearchBar.isHidden != true {
|
||||
defaultSearchBar.isHidden = false
|
||||
rnSearchBar.isHidden = true
|
||||
webSearchBar.isHidden = true
|
||||
}
|
||||
|
||||
if defaultTableView.isHidden != false ||
|
||||
rnTableView.isHidden != true ||
|
||||
webTableView.isHidden != true {
|
||||
defaultTableView.isHidden = false
|
||||
rnTableView.isHidden = true
|
||||
webTableView.isHidden = true
|
||||
}
|
||||
|
||||
if needReloadData == false && defaultModels.count > 0 {return}
|
||||
|
||||
if let arr = _OCLogStoreManager.shared()?.normalLogArray {
|
||||
defaultModels = arr as! [_OCLogModel]
|
||||
}
|
||||
|
||||
self.defaultCacheModels = self.defaultModels
|
||||
|
||||
self.searchLogic(CocoaDebugSettings.shared.logSearchWordNormal ?? "")
|
||||
|
||||
// dispatch_main_async_safe { [weak self] in
|
||||
self.defaultReloadDataFinish = false
|
||||
self.defaultTableView.reloadData {
|
||||
self.defaultReloadDataFinish = true
|
||||
}
|
||||
|
||||
if needScrollToEnd == false {return}
|
||||
|
||||
//table下滑到底部
|
||||
// guard let count = self.defaultModels.count else {return}
|
||||
if self.defaultModels.count > 0 {
|
||||
// guard let firstInDefault = self.firstInDefault else {return}
|
||||
self.defaultTableView.tableViewScrollToBottom(animated: !firstInDefault)
|
||||
self.firstInDefault = false
|
||||
}
|
||||
// }
|
||||
}
|
||||
else if selectedSegmentIndex == 1
|
||||
{
|
||||
if rnReloadDataFinish == false {return}
|
||||
|
||||
if defaultSearchBar.isHidden != true ||
|
||||
rnSearchBar.isHidden != false ||
|
||||
webSearchBar.isHidden != true {
|
||||
defaultSearchBar.isHidden = true
|
||||
rnSearchBar.isHidden = false
|
||||
webSearchBar.isHidden = true
|
||||
}
|
||||
|
||||
if defaultTableView.isHidden != true ||
|
||||
rnTableView.isHidden != false ||
|
||||
webTableView.isHidden != true {
|
||||
defaultTableView.isHidden = true
|
||||
rnTableView.isHidden = false
|
||||
webTableView.isHidden = true
|
||||
}
|
||||
|
||||
if needReloadData == false && rnModels.count > 0 {return}
|
||||
|
||||
if let arr = _OCLogStoreManager.shared()?.rnLogArray {
|
||||
rnModels = arr as! [_OCLogModel]
|
||||
}
|
||||
|
||||
self.rnCacheModels = self.rnModels
|
||||
|
||||
self.searchLogic(CocoaDebugSettings.shared.logSearchWordRN ?? "")
|
||||
|
||||
// dispatch_main_async_safe { [weak self] in
|
||||
self.rnReloadDataFinish = false
|
||||
self.rnTableView.reloadData {
|
||||
self.rnReloadDataFinish = true
|
||||
}
|
||||
|
||||
if needScrollToEnd == false {return}
|
||||
|
||||
//table下滑到底部
|
||||
// guard let count = self.rnModels.count else {return}
|
||||
if self.rnModels.count > 0 {
|
||||
// guard let firstInRN = self.firstInRN else {return}
|
||||
self.rnTableView.tableViewScrollToBottom(animated: !firstInRN)
|
||||
self.firstInRN = false
|
||||
}
|
||||
// }
|
||||
}
|
||||
else
|
||||
{
|
||||
if webReloadDataFinish == false {return}
|
||||
|
||||
if defaultSearchBar.isHidden != true ||
|
||||
rnSearchBar.isHidden != true ||
|
||||
webSearchBar.isHidden != false {
|
||||
defaultSearchBar.isHidden = true
|
||||
rnSearchBar.isHidden = true
|
||||
webSearchBar.isHidden = false
|
||||
}
|
||||
|
||||
if defaultTableView.isHidden != true ||
|
||||
rnTableView.isHidden != true ||
|
||||
webTableView.isHidden != false {
|
||||
defaultTableView.isHidden = true
|
||||
rnTableView.isHidden = true
|
||||
webTableView.isHidden = false
|
||||
}
|
||||
|
||||
if needReloadData == false && webModels.count > 0 {return}
|
||||
|
||||
if let arr = _OCLogStoreManager.shared().webLogArray {
|
||||
webModels = arr as! [_OCLogModel]
|
||||
}
|
||||
|
||||
self.webCacheModels = self.webModels
|
||||
|
||||
self.searchLogic(CocoaDebugSettings.shared.logSearchWordWeb ?? "")
|
||||
|
||||
// dispatch_main_async_safe { [weak self] in
|
||||
self.webReloadDataFinish = false
|
||||
self.webTableView.reloadData {
|
||||
self.webReloadDataFinish = true
|
||||
}
|
||||
|
||||
if needScrollToEnd == false {return}
|
||||
|
||||
//table下滑到底部
|
||||
// guard let count = self.webModels.count else {return}
|
||||
if self.webModels.count > 0 {
|
||||
// guard let firstInWeb = self.firstInWeb else {return}
|
||||
self.webTableView.tableViewScrollToBottom(animated: !firstInWeb)
|
||||
self.firstInWeb = false
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//MARK: - init
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
let tap = UITapGestureRecognizer.init(target: self, action: #selector(didTapView))
|
||||
tap.cancelsTouchesInView = false
|
||||
view.addGestureRecognizer(tap)
|
||||
|
||||
|
||||
deleteItem.tintColor = Color.mainGreen
|
||||
segmentedControl.tintColor = Color.mainGreen
|
||||
|
||||
if UIScreen.main.bounds.size.width == 320 {
|
||||
segmentedControl.setTitleTextAttributes([NSAttributedString.Key.font: UIFont.systemFont(ofSize: 11)], for: .normal)
|
||||
} else {
|
||||
segmentedControl.setTitleTextAttributes([NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13)], for: .normal)
|
||||
}
|
||||
|
||||
//notification
|
||||
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "refreshLogs_CocoaDebug"), object: nil, queue: OperationQueue.main) { [weak self] _ in
|
||||
self?.refreshLogs_notification()
|
||||
}
|
||||
|
||||
|
||||
defaultTableView.tableFooterView = UIView()
|
||||
defaultTableView.delegate = self
|
||||
defaultTableView.dataSource = self
|
||||
// defaultTableView.rowHeight = UITableViewAutomaticDimension
|
||||
defaultSearchBar.delegate = self
|
||||
defaultSearchBar.text = CocoaDebugSettings.shared.logSearchWordNormal
|
||||
defaultSearchBar.isHidden = true
|
||||
//抖动bug
|
||||
defaultTableView.estimatedRowHeight = 0
|
||||
defaultTableView.estimatedSectionHeaderHeight = 0
|
||||
defaultTableView.estimatedSectionFooterHeight = 0
|
||||
|
||||
|
||||
|
||||
rnTableView.tableFooterView = UIView()
|
||||
rnTableView.delegate = self
|
||||
rnTableView.dataSource = self
|
||||
// rnTableView.rowHeight = UITableViewAutomaticDimension
|
||||
rnSearchBar.delegate = self
|
||||
rnSearchBar.text = CocoaDebugSettings.shared.logSearchWordRN
|
||||
rnSearchBar.isHidden = true
|
||||
//抖动bug
|
||||
rnTableView.estimatedRowHeight = 0
|
||||
rnTableView.estimatedSectionHeaderHeight = 0
|
||||
rnTableView.estimatedSectionFooterHeight = 0
|
||||
|
||||
|
||||
|
||||
webTableView.tableFooterView = UIView()
|
||||
webTableView.delegate = self
|
||||
webTableView.dataSource = self
|
||||
// webTableView.rowHeight = UITableViewAutomaticDimension
|
||||
webSearchBar.delegate = self
|
||||
webSearchBar.text = CocoaDebugSettings.shared.logSearchWordWeb
|
||||
webSearchBar.isHidden = true
|
||||
//抖动bug
|
||||
webTableView.estimatedRowHeight = 0
|
||||
webTableView.estimatedSectionHeaderHeight = 0
|
||||
webTableView.estimatedSectionFooterHeight = 0
|
||||
|
||||
|
||||
|
||||
//segmentedControl
|
||||
selectedSegmentIndex = CocoaDebugSettings.shared.logSelectIndex
|
||||
segmentedControl.selectedSegmentIndex = selectedSegmentIndex
|
||||
|
||||
if selectedSegmentIndex == 0 {
|
||||
selectedSegment_0 = true
|
||||
} else if selectedSegmentIndex == 1 {
|
||||
selectedSegment_1 = true
|
||||
} else {
|
||||
selectedSegment_2 = true
|
||||
}
|
||||
|
||||
reloadLogs(needScrollToEnd: true, needReloadData: true)
|
||||
|
||||
|
||||
|
||||
//hide searchBar icon
|
||||
let textFieldInsideSearchBar = defaultSearchBar.value(forKey: "searchField") as! UITextField
|
||||
textFieldInsideSearchBar.leftViewMode = .never
|
||||
textFieldInsideSearchBar.leftView = nil
|
||||
textFieldInsideSearchBar.backgroundColor = .white
|
||||
textFieldInsideSearchBar.returnKeyType = .default
|
||||
|
||||
let textFieldInsideSearchBar2 = rnSearchBar.value(forKey: "searchField") as! UITextField
|
||||
textFieldInsideSearchBar2.leftViewMode = .never
|
||||
textFieldInsideSearchBar2.leftView = nil
|
||||
textFieldInsideSearchBar2.backgroundColor = .white
|
||||
textFieldInsideSearchBar2.returnKeyType = .default
|
||||
|
||||
let textFieldInsideSearchBar3 = webSearchBar.value(forKey: "searchField") as! UITextField
|
||||
textFieldInsideSearchBar3.leftViewMode = .never
|
||||
textFieldInsideSearchBar3.leftView = nil
|
||||
textFieldInsideSearchBar3.backgroundColor = .white
|
||||
textFieldInsideSearchBar3.returnKeyType = .default
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
defaultSearchBar.resignFirstResponder()
|
||||
rnSearchBar.resignFirstResponder()
|
||||
webSearchBar.resignFirstResponder()
|
||||
}
|
||||
|
||||
deinit {
|
||||
//notification
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
|
||||
//MARK: - target action
|
||||
@IBAction func didTapDown(_ sender: Any) {
|
||||
if selectedSegmentIndex == 0
|
||||
{
|
||||
defaultTableView.tableViewScrollToBottom(animated: true)
|
||||
defaultSearchBar.resignFirstResponder()
|
||||
reachEndDefault = true
|
||||
}
|
||||
else if selectedSegmentIndex == 1
|
||||
{
|
||||
rnTableView.tableViewScrollToBottom(animated: true)
|
||||
rnSearchBar.resignFirstResponder()
|
||||
reachEndRN = true
|
||||
}
|
||||
else
|
||||
{
|
||||
webTableView.tableViewScrollToBottom(animated: true)
|
||||
webSearchBar.resignFirstResponder()
|
||||
reachEndWeb = true
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func didTapUp(_ sender: Any) {
|
||||
if selectedSegmentIndex == 0
|
||||
{
|
||||
defaultTableView.tableViewScrollToHeader(animated: true)
|
||||
defaultSearchBar.resignFirstResponder()
|
||||
reachEndDefault = false
|
||||
}
|
||||
else if selectedSegmentIndex == 1
|
||||
{
|
||||
rnTableView.tableViewScrollToHeader(animated: true)
|
||||
rnSearchBar.resignFirstResponder()
|
||||
reachEndRN = false
|
||||
}
|
||||
else
|
||||
{
|
||||
webTableView.tableViewScrollToHeader(animated: true)
|
||||
webSearchBar.resignFirstResponder()
|
||||
reachEndWeb = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@IBAction func resetLogs(_ sender: Any) {
|
||||
if selectedSegmentIndex == 0
|
||||
{
|
||||
defaultModels = []
|
||||
defaultCacheModels = []
|
||||
// defaultSearchBar.text = nil
|
||||
defaultSearchBar.resignFirstResponder()
|
||||
// CocoaDebugSettings.shared.logSearchWordNormal = nil
|
||||
|
||||
_OCLogStoreManager.shared()?.resetNormalLogs()
|
||||
|
||||
// dispatch_main_async_safe { [weak self] in
|
||||
self.defaultTableView.reloadData()
|
||||
// }
|
||||
}
|
||||
else if selectedSegmentIndex == 1
|
||||
{
|
||||
rnModels = []
|
||||
rnCacheModels = []
|
||||
// rnSearchBar.text = nil
|
||||
rnSearchBar.resignFirstResponder()
|
||||
// CocoaDebugSettings.shared.logSearchWordRN = nil
|
||||
|
||||
_OCLogStoreManager.shared()?.resetRNLogs()
|
||||
|
||||
// dispatch_main_async_safe { [weak self] in
|
||||
self.rnTableView.reloadData()
|
||||
// }
|
||||
}
|
||||
else
|
||||
{
|
||||
webModels = []
|
||||
webCacheModels = []
|
||||
// webSearchBar.text = nil
|
||||
webSearchBar.resignFirstResponder()
|
||||
// CocoaDebugSettings.shared.logSearchWordWeb = nil
|
||||
|
||||
_OCLogStoreManager.shared().resetWebLogs()
|
||||
|
||||
// dispatch_main_async_safe { [weak self] in
|
||||
self.webTableView.reloadData()
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func segmentedControlAction(_ sender: UISegmentedControl) {
|
||||
selectedSegmentIndex = segmentedControl.selectedSegmentIndex
|
||||
CocoaDebugSettings.shared.logSelectIndex = selectedSegmentIndex
|
||||
|
||||
if selectedSegmentIndex == 0 {
|
||||
rnSearchBar.resignFirstResponder()
|
||||
webSearchBar.resignFirstResponder()
|
||||
} else if selectedSegmentIndex == 1 {
|
||||
defaultSearchBar.resignFirstResponder()
|
||||
webSearchBar.resignFirstResponder()
|
||||
} else {
|
||||
defaultSearchBar.resignFirstResponder()
|
||||
rnSearchBar.resignFirstResponder()
|
||||
}
|
||||
|
||||
if selectedSegmentIndex == 0 && selectedSegment_0 == false {
|
||||
selectedSegment_0 = true
|
||||
reloadLogs(needScrollToEnd: true, needReloadData: true)
|
||||
return
|
||||
}
|
||||
|
||||
if selectedSegmentIndex == 1 && selectedSegment_1 == false {
|
||||
selectedSegment_1 = true
|
||||
reloadLogs(needScrollToEnd: true, needReloadData: true)
|
||||
return
|
||||
}
|
||||
|
||||
if selectedSegmentIndex == 2 && selectedSegment_2 == false {
|
||||
selectedSegment_2 = true
|
||||
reloadLogs(needScrollToEnd: true, needReloadData: true)
|
||||
return
|
||||
}
|
||||
|
||||
reloadLogs(needScrollToEnd: false, needReloadData: false)
|
||||
}
|
||||
|
||||
@objc func didTapView() {
|
||||
if selectedSegmentIndex == 0 {
|
||||
defaultSearchBar.resignFirstResponder()
|
||||
} else if selectedSegmentIndex == 1 {
|
||||
rnSearchBar.resignFirstResponder()
|
||||
} else {
|
||||
webSearchBar.resignFirstResponder()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//MARK: - notification
|
||||
@objc func refreshLogs_notification() {
|
||||
if self.selectedSegmentIndex == 0 {
|
||||
self.reloadLogs(needScrollToEnd: self.reachEndDefault , needReloadData: true)
|
||||
} else if self.selectedSegmentIndex == 1 {
|
||||
self.reloadLogs(needScrollToEnd: self.reachEndRN , needReloadData: true)
|
||||
} else {
|
||||
self.reloadLogs(needScrollToEnd: self.reachEndWeb , needReloadData: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - UITableViewDataSource
|
||||
extension LogViewController: UITableViewDataSource {
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
if tableView == defaultTableView {
|
||||
return defaultModels.count
|
||||
} else if tableView == rnTableView {
|
||||
return rnModels.count
|
||||
} else {
|
||||
return webModels.count
|
||||
}
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "LogCell", for: indexPath) as! LogCell
|
||||
|
||||
if tableView == defaultTableView
|
||||
{
|
||||
cell.model = defaultModels[indexPath.row]
|
||||
}
|
||||
else if tableView == rnTableView
|
||||
{
|
||||
cell.model = rnModels[indexPath.row]
|
||||
}
|
||||
else
|
||||
{
|
||||
cell.model = webModels[indexPath.row]
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - UITableViewDelegate
|
||||
extension LogViewController: UITableViewDelegate {
|
||||
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
|
||||
var logTitleString = ""
|
||||
var models_: [_OCLogModel]?
|
||||
|
||||
if tableView == defaultTableView
|
||||
{
|
||||
defaultSearchBar.resignFirstResponder()
|
||||
reachEndDefault = false
|
||||
logTitleString = "Log"
|
||||
models_ = defaultModels
|
||||
}
|
||||
else if tableView == rnTableView
|
||||
{
|
||||
rnSearchBar.resignFirstResponder()
|
||||
reachEndRN = false
|
||||
logTitleString = "RN"
|
||||
models_ = rnModels
|
||||
}
|
||||
else
|
||||
{
|
||||
webSearchBar.resignFirstResponder()
|
||||
reachEndWeb = false
|
||||
logTitleString = "Web"
|
||||
models_ = webModels
|
||||
}
|
||||
|
||||
//
|
||||
guard let models = models_ else {return}
|
||||
|
||||
let vc = JsonViewController.instanceFromStoryBoard()
|
||||
vc.editType = .log
|
||||
vc.logTitleString = logTitleString
|
||||
vc.logModels = models
|
||||
vc.logModel = models[indexPath.row]
|
||||
|
||||
navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
vc.justCancelCallback = {
|
||||
tableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||
|
||||
var model: _OCLogModel
|
||||
|
||||
if tableView == defaultTableView {
|
||||
model = defaultModels[indexPath.row]
|
||||
|
||||
} else if tableView == rnTableView {
|
||||
model = rnModels[indexPath.row]
|
||||
|
||||
} else {
|
||||
model = webModels[indexPath.row]
|
||||
}
|
||||
|
||||
if let height = model.str?.height(with: UIFont.boldSystemFont(ofSize: 12), constraintToWidth: UIScreen.main.bounds.size.width) {
|
||||
return height + 10;
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - UIScrollViewDelegate
|
||||
extension LogViewController: UIScrollViewDelegate {
|
||||
|
||||
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
|
||||
if scrollView == defaultTableView {
|
||||
defaultSearchBar.resignFirstResponder()
|
||||
reachEndDefault = false
|
||||
} else if scrollView == rnTableView {
|
||||
rnSearchBar.resignFirstResponder()
|
||||
reachEndRN = false
|
||||
} else {
|
||||
webSearchBar.resignFirstResponder()
|
||||
reachEndWeb = false
|
||||
}
|
||||
}
|
||||
|
||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
if (scrollView.contentOffset.y + 1) >= (scrollView.contentSize.height - scrollView.frame.size.height) {
|
||||
//bottom reached
|
||||
if scrollView == defaultTableView {
|
||||
reachEndDefault = true
|
||||
} else if scrollView == rnTableView {
|
||||
reachEndRN = true
|
||||
} else {
|
||||
reachEndWeb = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - UISearchBarDelegate
|
||||
extension LogViewController: UISearchBarDelegate {
|
||||
|
||||
func searchBarSearchButtonClicked(_ searchBar: UISearchBar)
|
||||
{
|
||||
searchBar.resignFirstResponder()
|
||||
}
|
||||
|
||||
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)
|
||||
{
|
||||
if searchBar == defaultSearchBar
|
||||
{
|
||||
CocoaDebugSettings.shared.logSearchWordNormal = searchText
|
||||
searchLogic(searchText)
|
||||
|
||||
// dispatch_main_async_safe { [weak self] in
|
||||
self.defaultTableView.reloadData()
|
||||
// }
|
||||
}
|
||||
else if searchBar == rnSearchBar
|
||||
{
|
||||
CocoaDebugSettings.shared.logSearchWordRN = searchText
|
||||
searchLogic(searchText)
|
||||
|
||||
// dispatch_main_async_safe { [weak self] in
|
||||
self.rnTableView.reloadData()
|
||||
// }
|
||||
}
|
||||
else
|
||||
{
|
||||
CocoaDebugSettings.shared.logSearchWordWeb = searchText
|
||||
searchLogic(searchText)
|
||||
|
||||
// dispatch_main_async_safe { [weak self] in
|
||||
self.webTableView.reloadData()
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
96
Pods/CocoaDebug/Sources/Logs/_NSLogHook.m
generated
Normal file
96
Pods/CocoaDebug/Sources/Logs/_NSLogHook.m
generated
Normal file
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// _NSLogHook.m
|
||||
// Example_Swift
|
||||
//
|
||||
// Created by man 7/26/19.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "_OCLogHelper.h"
|
||||
#import "_fishhook.h"
|
||||
//#import <React/RCTLog.h>
|
||||
//#import "RCTLog.h"
|
||||
|
||||
@interface _NSLogHook : NSObject
|
||||
|
||||
@end
|
||||
|
||||
@implementation _NSLogHook
|
||||
|
||||
static void (*_original_nslog)(NSString *format, ...);
|
||||
|
||||
#pragma mark - hooks
|
||||
void cocoadebug_nslog(NSString *format, ...)
|
||||
{
|
||||
if (![format isKindOfClass:[NSString class]]) {return;}
|
||||
|
||||
va_list vl;
|
||||
va_start(vl, format);
|
||||
NSString *str = [[NSString alloc] initWithFormat:format arguments:vl];
|
||||
|
||||
@try {
|
||||
_original_nslog(str);
|
||||
} @catch(NSException *exception) {
|
||||
|
||||
} @finally {
|
||||
|
||||
}
|
||||
|
||||
@try {
|
||||
[_OCLogHelper.shared handleLogWithFile:@"" function:@"" line:999999999 message:str color:[UIColor whiteColor] type:CocoaDebugToolTypeNone];
|
||||
} @catch(NSException *exception) {
|
||||
|
||||
} @finally {
|
||||
|
||||
}
|
||||
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
#pragma mark - load
|
||||
+ (void)load
|
||||
{
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"enableLogMonitoring_CocoaDebug"]) {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
struct rebinding nslog_rebinding = {"NSLog",cocoadebug_nslog,(void*)&_original_nslog};
|
||||
rebind_symbols((struct rebinding[1]){nslog_rebinding}, 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//#pragma mark - RN
|
||||
//void _RCTLogJavaScriptInternal(RCTLogLevel level, NSString *message)
|
||||
//{
|
||||
// if ([[NSUserDefaults standardUserDefaults] boolForKey:@"enableRNMonitoring_CocoaDebug"]) {return;}
|
||||
// if (![message isKindOfClass:[NSString class]]) {return;}
|
||||
//// if (level != RCTLogLevelError && level != RCTLogLevelInfo) {return;}
|
||||
//
|
||||
// NSString *levelStr = @"";
|
||||
//
|
||||
// switch (level) {
|
||||
//// case RCTLogLevelTrace:
|
||||
//// levelStr = @"[RCTLogTrace]";
|
||||
//// break;
|
||||
// case RCTLogLevelInfo:
|
||||
// levelStr = @"[RCTLogInfo]";
|
||||
// break;
|
||||
// case RCTLogLevelWarning:
|
||||
// levelStr = @"[RCTLogWarn]";
|
||||
// break;
|
||||
// case RCTLogLevelError:
|
||||
// levelStr = @"[RCTLogError]";
|
||||
// break;
|
||||
//// case RCTLogLevelFatal:
|
||||
//// levelStr = @"[RCTLogFatal]";
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// [_OCLogHelper.shared handleLogWithFile:[NSString stringWithFormat:@"%@\n", levelStr] function:@"" line:-1 message:message color:[UIColor whiteColor] type:CocoaDebugToolTypeRN];
|
||||
//}
|
||||
|
||||
@end
|
||||
|
||||
21
Pods/CocoaDebug/Sources/Logs/_OCLogHelper.h
generated
Normal file
21
Pods/CocoaDebug/Sources/Logs/_OCLogHelper.h
generated
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// Example
|
||||
// man
|
||||
//
|
||||
// Created by man 11/11/2018.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "_OCLogModel.h"
|
||||
|
||||
@interface _OCLogHelper : NSObject
|
||||
|
||||
//@property (nonatomic, assign) BOOL enable;
|
||||
|
||||
+ (instancetype)shared;
|
||||
|
||||
- (void)handleLogWithFile:(NSString *)file function:(NSString *)function line:(NSInteger)line message:(NSString *)message color:(UIColor *)color type:(CocoaDebugToolType)type;
|
||||
|
||||
@end
|
||||
91
Pods/CocoaDebug/Sources/Logs/_OCLogHelper.m
generated
Normal file
91
Pods/CocoaDebug/Sources/Logs/_OCLogHelper.m
generated
Normal file
@@ -0,0 +1,91 @@
|
||||
//
|
||||
// Example
|
||||
// man
|
||||
//
|
||||
// Created by man 11/11/2018.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
#import "_OCLogHelper.h"
|
||||
#import "_OCLogStoreManager.h"
|
||||
|
||||
@implementation _OCLogHelper
|
||||
|
||||
+ (instancetype)shared
|
||||
{
|
||||
static id sharedInstance = nil;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[self alloc] init];
|
||||
});
|
||||
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
//default value for @property
|
||||
//- (id)init {
|
||||
// if (self = [super init]) {
|
||||
// self.enable = YES;
|
||||
// }
|
||||
// return self;
|
||||
//}
|
||||
|
||||
- (NSString *)parseFileInfo:(NSString *)file function:(NSString *)function line:(NSInteger)line
|
||||
{
|
||||
if (![file isKindOfClass:[NSString class]] || ![function isKindOfClass:[NSString class]]) {
|
||||
return @"\n";
|
||||
}
|
||||
|
||||
if ([file isEqualToString:@"XXX"] && [function isEqualToString:@"XXX"] && line == 1) {
|
||||
return @"XXX|XXX|1";
|
||||
}
|
||||
|
||||
if (line == 0) { //web
|
||||
NSString *fileName = [[file componentsSeparatedByString:@"/"] lastObject] ?: @"";
|
||||
return [NSString stringWithFormat:@"%@ %@\n", fileName, function];
|
||||
}
|
||||
|
||||
if (line == 999999999) { //nslog
|
||||
NSString *fileName = [[file componentsSeparatedByString:@"/"] lastObject] ?: @"";
|
||||
return [NSString stringWithFormat:@"%@ %@\n", fileName, function];
|
||||
}
|
||||
|
||||
if (line == -1) { //RN
|
||||
return file;
|
||||
}
|
||||
|
||||
NSString *fileName = [[file componentsSeparatedByString:@"/"] lastObject] ?: @"";
|
||||
return [NSString stringWithFormat:@"%@[%ld]%@\n", fileName, (long)line, function];
|
||||
}
|
||||
|
||||
- (void)handleLogWithFile:(NSString *)file function:(NSString *)function line:(NSInteger)line message:(NSString *)message color:(UIColor *)color type:(CocoaDebugToolType)type
|
||||
{
|
||||
// if (!self.enable && type != CocoaDebugToolTypeRN) {return;}
|
||||
if (!file || !function || !message || !color) {return;}
|
||||
|
||||
//1.
|
||||
NSString *fileInfo = [self parseFileInfo:file function:function line:line];
|
||||
|
||||
//2.
|
||||
_OCLogModel *newLog = [[_OCLogModel alloc] initWithContent:message color:color fileInfo:fileInfo isTag:NO type:type];
|
||||
|
||||
// if (line == 0 && ![fileInfo isEqualToString:@"XXX|XXX|1"]) {
|
||||
// newLog.logType = CocoaDebugLogType...
|
||||
// }
|
||||
|
||||
if (type == CocoaDebugToolTypeRN) {
|
||||
newLog.logType = CocoaDebugLogTypeRN;
|
||||
}
|
||||
|
||||
if ([file isEqualToString:@"[WKWebView]"]) {
|
||||
newLog.logType = CocoaDebugLogTypeWeb;
|
||||
}
|
||||
|
||||
[[_OCLogStoreManager shared] addLog:newLog];
|
||||
|
||||
//3.
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"refreshLogs_CocoaDebug" object:nil userInfo:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
44
Pods/CocoaDebug/Sources/Logs/_OCLogModel.h
generated
Normal file
44
Pods/CocoaDebug/Sources/Logs/_OCLogModel.h
generated
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// Example
|
||||
// man
|
||||
//
|
||||
// Created by man 11/11/2018.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
typedef NS_ENUM(NSInteger, CocoaDebugLogType) {
|
||||
CocoaDebugLogTypeNormal = 0,
|
||||
CocoaDebugLogTypeRN,
|
||||
CocoaDebugLogTypeWeb
|
||||
};
|
||||
|
||||
typedef NS_ENUM (NSInteger, CocoaDebugToolType) {
|
||||
CocoaDebugToolTypeNone,
|
||||
CocoaDebugToolTypeRN,
|
||||
CocoaDebugToolTypeJson,
|
||||
CocoaDebugToolTypeProtobuf
|
||||
};
|
||||
|
||||
@interface _OCLogModel : NSObject
|
||||
|
||||
@property (nonatomic, copy) NSData *contentData;
|
||||
|
||||
@property (nonatomic, copy) NSString *Id;
|
||||
@property (nonatomic, copy) NSString *fileInfo;
|
||||
@property (nonatomic, copy) NSString *content;
|
||||
@property (nonatomic, strong) NSDate *date;
|
||||
@property (nonatomic, strong) UIColor *color;
|
||||
|
||||
@property (nonatomic, assign) BOOL isTag;
|
||||
@property (nonatomic, assign) BOOL isSelected;
|
||||
@property (nonatomic, copy) NSString *str;
|
||||
@property (nonatomic, copy) NSAttributedString *attr;
|
||||
|
||||
@property (nonatomic, assign) CocoaDebugLogType logType;
|
||||
|
||||
- (instancetype)initWithContent:(NSString *)content color:(UIColor *)color fileInfo:(NSString *)fileInfo isTag:(BOOL)isTag type:(CocoaDebugToolType)type;
|
||||
|
||||
@end
|
||||
110
Pods/CocoaDebug/Sources/Logs/_OCLogModel.m
generated
Normal file
110
Pods/CocoaDebug/Sources/Logs/_OCLogModel.m
generated
Normal file
@@ -0,0 +1,110 @@
|
||||
//
|
||||
// Example
|
||||
// man
|
||||
//
|
||||
// Created by man 11/11/2018.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
#import "_OCLogModel.h"
|
||||
#import "_OCLoggerFormat.h"
|
||||
#import "_NetworkHelper.h"
|
||||
|
||||
@implementation _OCLogModel
|
||||
|
||||
- (instancetype)initWithContent:(NSString *)content color:(UIColor *)color fileInfo:(NSString *)fileInfo isTag:(BOOL)isTag type:(CocoaDebugToolType)type
|
||||
{
|
||||
if (self = [super init]) {
|
||||
|
||||
if ([fileInfo isEqualToString:@"XXX|XXX|1"]) {
|
||||
if (type == CocoaDebugToolTypeProtobuf) {
|
||||
fileInfo = @"Protobuf\n";
|
||||
} else {
|
||||
fileInfo = @"\n";
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
if (type == CocoaDebugToolTypeNone) {
|
||||
if ([fileInfo isEqualToString:@" \n"]) {//nslog
|
||||
fileInfo = @"NSLog\n";
|
||||
} else if ([fileInfo isEqualToString:@"\n"]) {//color
|
||||
fileInfo = @"\n";
|
||||
}
|
||||
}
|
||||
|
||||
//RN (java script)
|
||||
if ([fileInfo isEqualToString:@"[RCTLogError]\n"]) {
|
||||
fileInfo = @"[error]\n";
|
||||
} else if ([fileInfo isEqualToString:@"[RCTLogInfo]\n"]) {
|
||||
fileInfo = @"[log]\n";
|
||||
}
|
||||
|
||||
//
|
||||
self.Id = [[NSUUID UUID] UUIDString];
|
||||
self.fileInfo = fileInfo;
|
||||
self.date = [NSDate date];
|
||||
self.color = color;
|
||||
self.isTag = isTag;
|
||||
|
||||
if ([content isKindOfClass:[NSString class]]) {
|
||||
self.contentData = [content dataUsingEncoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
//避免日志数量过多导致卡顿
|
||||
if (content.length > 1000) {
|
||||
content = [content substringToIndex:1000];
|
||||
}
|
||||
self.content = content;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NSInteger startIndex = 0;
|
||||
NSInteger lenghtDate = 0;
|
||||
NSString *stringContent = @"";
|
||||
|
||||
stringContent = [stringContent stringByAppendingFormat:@"[%@]", [_OCLoggerFormat formatDate:self.date]];
|
||||
lenghtDate = [stringContent length];
|
||||
startIndex = [stringContent length];
|
||||
|
||||
if (self.fileInfo) {
|
||||
stringContent = [stringContent stringByAppendingFormat:@"%@%@", self.fileInfo, self.content];
|
||||
} else {
|
||||
stringContent = [stringContent stringByAppendingFormat:@"%@", self.content];
|
||||
}
|
||||
|
||||
NSMutableAttributedString *attstr = [[NSMutableAttributedString alloc] initWithString:stringContent];
|
||||
[attstr addAttribute:NSForegroundColorAttributeName value:self.color range:NSMakeRange(0, [stringContent length])];
|
||||
|
||||
NSRange range = NSMakeRange(0, lenghtDate);
|
||||
[attstr addAttribute:NSForegroundColorAttributeName value: [[_NetworkHelper shared] mainColor] range: range];
|
||||
[attstr addAttribute:NSFontAttributeName value: [UIFont boldSystemFontOfSize:12] range: range];
|
||||
|
||||
NSRange range2 = NSMakeRange(startIndex, self.fileInfo.length);
|
||||
|
||||
if ([self.fileInfo isEqualToString:@"[error]\n"]) {
|
||||
[attstr addAttribute: NSForegroundColorAttributeName value: [UIColor systemRedColor] range: range2];
|
||||
} else {
|
||||
[attstr addAttribute: NSForegroundColorAttributeName value: [UIColor systemGrayColor] range: range2];
|
||||
}
|
||||
|
||||
[attstr addAttribute: NSFontAttributeName value: [UIFont boldSystemFontOfSize:12] range: range2];
|
||||
|
||||
|
||||
//换行
|
||||
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
|
||||
paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping;
|
||||
|
||||
NSRange rang3 = NSMakeRange(0, attstr.length);
|
||||
[attstr addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:rang3];
|
||||
|
||||
|
||||
//
|
||||
self.str = stringContent;
|
||||
self.attr = [attstr copy];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
28
Pods/CocoaDebug/Sources/Logs/_OCLogStoreManager.h
generated
Normal file
28
Pods/CocoaDebug/Sources/Logs/_OCLogStoreManager.h
generated
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// Example
|
||||
// man
|
||||
//
|
||||
// Created by man 11/11/2018.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "_OCLogModel.h"
|
||||
|
||||
@interface _OCLogStoreManager : NSObject
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray<_OCLogModel *> *normalLogArray;
|
||||
@property (nonatomic, strong) NSMutableArray<_OCLogModel *> *rnLogArray;
|
||||
@property (nonatomic, strong) NSMutableArray<_OCLogModel *> *webLogArray;
|
||||
|
||||
+ (instancetype)shared;
|
||||
|
||||
- (void)addLog:(_OCLogModel *)log;
|
||||
- (void)removeLog:(_OCLogModel *)log;
|
||||
|
||||
- (void)resetNormalLogs;
|
||||
- (void)resetRNLogs;
|
||||
- (void)resetWebLogs;
|
||||
|
||||
@end
|
||||
|
||||
127
Pods/CocoaDebug/Sources/Logs/_OCLogStoreManager.m
generated
Normal file
127
Pods/CocoaDebug/Sources/Logs/_OCLogStoreManager.m
generated
Normal file
@@ -0,0 +1,127 @@
|
||||
//
|
||||
// Example
|
||||
// man
|
||||
//
|
||||
// Created by man 11/11/2018.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
#import "_OCLogStoreManager.h"
|
||||
#import "_NetworkHelper.h"
|
||||
|
||||
@implementation _OCLogStoreManager
|
||||
|
||||
+ (instancetype)shared
|
||||
{
|
||||
static id sharedInstance = nil;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[self alloc] init];
|
||||
});
|
||||
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.normalLogArray = [NSMutableArray arrayWithCapacity:1000 + 100];
|
||||
self.rnLogArray = [NSMutableArray arrayWithCapacity:1000 + 100];
|
||||
self.webLogArray = [NSMutableArray arrayWithCapacity:1000 + 100];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)addLog:(_OCLogModel *)log
|
||||
{
|
||||
if (![log.content isKindOfClass:[NSString class]]) {return;}
|
||||
|
||||
//log过滤, 忽略大小写
|
||||
for (NSString *prefixStr in [_NetworkHelper shared].onlyPrefixLogs) {
|
||||
if (![log.content hasPrefix:prefixStr]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
//log过滤, 忽略大小写
|
||||
for (NSString *prefixStr in [_NetworkHelper shared].ignoredPrefixLogs) {
|
||||
if ([log.content hasPrefix:prefixStr]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
if (log.logType == CocoaDebugLogTypeNormal)
|
||||
{
|
||||
//normal
|
||||
if ([self.normalLogArray count] >= 1000) {
|
||||
if (self.normalLogArray.count > 0) {
|
||||
[self.normalLogArray removeObjectAtIndex:0];
|
||||
}
|
||||
}
|
||||
|
||||
[self.normalLogArray addObject:log];
|
||||
}
|
||||
else if (log.logType == CocoaDebugLogTypeRN)
|
||||
{
|
||||
//rn
|
||||
if ([self.rnLogArray count] >= 1000) {
|
||||
if (self.rnLogArray.count > 0) {
|
||||
[self.rnLogArray removeObjectAtIndex:0];
|
||||
}
|
||||
}
|
||||
|
||||
[self.rnLogArray addObject:log];
|
||||
}
|
||||
else
|
||||
{
|
||||
//web
|
||||
if ([self.webLogArray count] >= 1000) {
|
||||
if (self.webLogArray.count > 0) {
|
||||
[self.webLogArray removeObjectAtIndex:0];
|
||||
}
|
||||
}
|
||||
|
||||
[self.webLogArray addObject:log];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeLog:(_OCLogModel *)log
|
||||
{
|
||||
if (log.logType == CocoaDebugLogTypeNormal)
|
||||
{
|
||||
//normal
|
||||
[self.normalLogArray removeObject:log];
|
||||
}
|
||||
else if (log.logType == CocoaDebugLogTypeNormal)
|
||||
{
|
||||
//rn
|
||||
[self.rnLogArray removeObject:log];
|
||||
}
|
||||
else
|
||||
{
|
||||
//web
|
||||
[self.webLogArray removeObject:log];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)resetNormalLogs
|
||||
{
|
||||
[self.normalLogArray removeAllObjects];
|
||||
}
|
||||
|
||||
- (void)resetRNLogs
|
||||
{
|
||||
[self.rnLogArray removeAllObjects];
|
||||
}
|
||||
|
||||
- (void)resetWebLogs
|
||||
{
|
||||
[self.webLogArray removeAllObjects];
|
||||
}
|
||||
|
||||
@end
|
||||
15
Pods/CocoaDebug/Sources/Logs/_OCLoggerFormat.h
generated
Normal file
15
Pods/CocoaDebug/Sources/Logs/_OCLoggerFormat.h
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// Example
|
||||
// man
|
||||
//
|
||||
// Created by man 11/11/2018.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface _OCLoggerFormat : NSObject
|
||||
|
||||
+ (NSString *)formatDate:(NSDate *)date;
|
||||
|
||||
@end
|
||||
21
Pods/CocoaDebug/Sources/Logs/_OCLoggerFormat.m
generated
Normal file
21
Pods/CocoaDebug/Sources/Logs/_OCLoggerFormat.m
generated
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// Example
|
||||
// man
|
||||
//
|
||||
// Created by man 11/11/2018.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
#import "_OCLoggerFormat.h"
|
||||
|
||||
@implementation _OCLoggerFormat
|
||||
|
||||
+ (NSString *)formatDate:(NSDate *)date
|
||||
{
|
||||
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
|
||||
formatter.timeZone = [NSTimeZone systemTimeZone];
|
||||
formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS";
|
||||
return [formatter stringFromDate:date];
|
||||
}
|
||||
|
||||
@end
|
||||
20
Pods/CocoaDebug/Sources/Logs/_ObjcLog.h
generated
Normal file
20
Pods/CocoaDebug/Sources/Logs/_ObjcLog.h
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Example
|
||||
// man
|
||||
//
|
||||
// Created by man 11/11/2018.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface _ObjcLog : NSObject
|
||||
|
||||
+ (void)logWithFile:(const char *)file
|
||||
function:(const char *)function
|
||||
line:(NSUInteger)line
|
||||
color:(UIColor *)color
|
||||
message:(id)format, ...;
|
||||
|
||||
@end
|
||||
57
Pods/CocoaDebug/Sources/Logs/_ObjcLog.m
generated
Normal file
57
Pods/CocoaDebug/Sources/Logs/_ObjcLog.m
generated
Normal file
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// Example
|
||||
// man
|
||||
//
|
||||
// Created by man 11/11/2018.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
#import "_ObjcLog.h"
|
||||
#import "_OCLogHelper.h"
|
||||
#import "NSObject+CocoaDebug.h"
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
|
||||
@implementation _ObjcLog
|
||||
|
||||
+ (void)logWithFile:(const char *)file
|
||||
function:(const char *)function
|
||||
line:(NSUInteger)line
|
||||
color:(UIColor *)color
|
||||
message:(id)format, ...
|
||||
{
|
||||
if (format)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
if ([format isKindOfClass:[NSString class]])
|
||||
{
|
||||
// NSLogv(format, args);
|
||||
[_OCLogHelper.shared handleLogWithFile:[NSString stringWithUTF8String:file] function:[NSString stringWithUTF8String:function] line:line message:[[NSString alloc] initWithFormat:format arguments:args] color:color type:CocoaDebugToolTypeNone];
|
||||
}
|
||||
else if ([format isKindOfClass:[JSValue class]])
|
||||
{
|
||||
id format_ = [format toString];
|
||||
if ([format_ isEqualToString:@"[object Object]"])
|
||||
{
|
||||
format_ = [format toDictionary];
|
||||
// NSLogv([NSString stringWithFormat:@"%@",format_], args);
|
||||
[_OCLogHelper.shared handleLogWithFile:[NSString stringWithUTF8String:file] function:[NSString stringWithUTF8String:function] line:line message:[NSString stringWithFormat:@"%@",format_] color:color type:CocoaDebugToolTypeNone];
|
||||
}
|
||||
else
|
||||
{
|
||||
// NSLogv([NSString stringWithFormat:@"%@",format], args);
|
||||
[_OCLogHelper.shared handleLogWithFile:[NSString stringWithUTF8String:file] function:[NSString stringWithUTF8String:function] line:line message:[NSString stringWithFormat:@"%@",format] color:color type:CocoaDebugToolTypeNone];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// NSLogv([NSString stringWithFormat:@"%@",format], args);
|
||||
[_OCLogHelper.shared handleLogWithFile:[NSString stringWithUTF8String:file] function:[NSString stringWithUTF8String:function] line:line message:[NSString stringWithFormat:@"%@",format] color:color type:CocoaDebugToolTypeNone];
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
49
Pods/CocoaDebug/Sources/Logs/_SwiftLogHelper.swift
generated
Normal file
49
Pods/CocoaDebug/Sources/Logs/_SwiftLogHelper.swift
generated
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Example
|
||||
// man
|
||||
//
|
||||
// Created by man 11/11/2018.
|
||||
// Copyright © 2020 man. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class _SwiftLogHelper: NSObject {
|
||||
|
||||
var enable: Bool = true
|
||||
|
||||
@objc public static let shared = _SwiftLogHelper()
|
||||
private override init() {}
|
||||
|
||||
|
||||
fileprivate func parseFileInfo(file: String?, function: String?, line: Int?) -> String? {
|
||||
guard let file = file, let function = function, let line = line, let fileName = file.components(separatedBy: "/").last else {return nil}
|
||||
return "\(fileName)[\(line)]\(function)\n"
|
||||
}
|
||||
|
||||
|
||||
public func handleLog(file: String?, function: String?, line: Int?, message: Any..., color: UIColor?) {
|
||||
let stringContent = message.reduce("") { result, next -> String in
|
||||
return "\(result)\(result.count > 0 ? " " : "")\(next)"
|
||||
}
|
||||
commonHandleLog(file: file, function: function, line: (line ?? 0), message: stringContent, color: color)
|
||||
}
|
||||
|
||||
|
||||
private func commonHandleLog(file: String?, function: String?, line: Int, message: String, color: UIColor?) {
|
||||
guard enable else {
|
||||
return
|
||||
}
|
||||
|
||||
//1.
|
||||
let fileInfo = parseFileInfo(file: file, function: function, line: line)
|
||||
|
||||
//2.
|
||||
if let newLog = _OCLogModel.init(content: message, color: color, fileInfo: fileInfo, isTag: false, type: .none) {
|
||||
_OCLogStoreManager.shared().addLog(newLog)
|
||||
}
|
||||
|
||||
//3.
|
||||
NotificationCenter.default.post(name: NSNotification.Name("refreshLogs_CocoaDebug"), object: nil, userInfo: nil)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user