You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
9.2 KiB
299 lines
9.2 KiB
import Foundation
|
|
import UIKit
|
|
import Combine
|
|
|
|
// MARK: - 内存监控器
|
|
class MemoryMonitor: ObservableObject {
|
|
static let shared = MemoryMonitor()
|
|
|
|
@Published var currentMemoryUsage: String = "Unknown"
|
|
@Published var memoryWarningCount: Int = 0
|
|
|
|
private var memoryCheckTimer: Timer?
|
|
|
|
init() {
|
|
// 监听内存警告
|
|
NotificationCenter.default.addObserver(
|
|
self,
|
|
selector: #selector(handleMemoryWarning),
|
|
name: UIApplication.didReceiveMemoryWarningNotification,
|
|
object: nil
|
|
)
|
|
|
|
// 启动内存监控
|
|
startMemoryMonitoring()
|
|
}
|
|
|
|
deinit {
|
|
NotificationCenter.default.removeObserver(self)
|
|
stopMemoryMonitoring()
|
|
}
|
|
|
|
// MARK: - 内存使用监控
|
|
|
|
/// 获取当前内存使用情况
|
|
func getMemoryUsage() -> String {
|
|
var info = mach_task_basic_info()
|
|
var count = mach_msg_type_number_t(MemoryLayout<mach_task_basic_info>.size)/4
|
|
|
|
let kerr: kern_return_t = withUnsafeMutablePointer(to: &info) {
|
|
$0.withMemoryRebound(to: integer_t.self, capacity: 1) {
|
|
task_info(mach_task_self_,
|
|
task_flavor_t(MACH_TASK_BASIC_INFO),
|
|
$0,
|
|
&count)
|
|
}
|
|
}
|
|
|
|
if kerr == KERN_SUCCESS {
|
|
let usedMB = Double(info.resident_size) / 1024.0 / 1024.0
|
|
return String(format: "%.1f MB", usedMB)
|
|
} else {
|
|
return "Unknown"
|
|
}
|
|
}
|
|
|
|
/// 获取内存使用详情
|
|
func getMemoryUsageDetails() -> (usedMB: Double, totalMB: Double, percentage: Double) {
|
|
var info = mach_task_basic_info()
|
|
var count = mach_msg_type_number_t(MemoryLayout<mach_task_basic_info>.size)/4
|
|
|
|
let kerr: kern_return_t = withUnsafeMutablePointer(to: &info) {
|
|
$0.withMemoryRebound(to: integer_t.self, capacity: 1) {
|
|
task_info(mach_task_self_,
|
|
task_flavor_t(MACH_TASK_BASIC_INFO),
|
|
$0,
|
|
&count)
|
|
}
|
|
}
|
|
|
|
if kerr == KERN_SUCCESS {
|
|
let usedMB = Double(info.resident_size) / 1024.0 / 1024.0
|
|
let totalMB = Double(ProcessInfo.processInfo.physicalMemory) / 1024.0 / 1024.0
|
|
let percentage = (usedMB / totalMB) * 100.0
|
|
|
|
return (usedMB, totalMB, percentage)
|
|
} else {
|
|
return (0, 0, 0)
|
|
}
|
|
}
|
|
|
|
// MARK: - 内存压力检查
|
|
|
|
/// 检查内存压力
|
|
func checkMemoryPressure() {
|
|
let memoryUsage = getMemoryUsage()
|
|
currentMemoryUsage = memoryUsage
|
|
|
|
print("📊 当前内存使用: \(memoryUsage)")
|
|
|
|
// 解析内存使用量
|
|
if let usage = Double(memoryUsage.replacingOccurrences(of: " MB", with: "")) {
|
|
if usage > 200 { // 超过200MB
|
|
print("⚠️ 内存使用过高,执行清理操作")
|
|
performMemoryCleanup()
|
|
} else if usage > 150 { // 超过150MB
|
|
print("⚠️ 内存使用较高,建议清理")
|
|
suggestMemoryCleanup()
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 执行内存清理
|
|
func performMemoryCleanup() {
|
|
print("🧹 执行内存清理操作")
|
|
|
|
// 清理图片缓存
|
|
ImageCacheManager.shared.clearCache()
|
|
|
|
// 清理临时文件
|
|
cleanupTempFiles()
|
|
|
|
// 通知其他组件进行清理
|
|
NotificationCenter.default.post(name: .memoryCleanup, object: nil)
|
|
|
|
// 强制垃圾回收
|
|
autoreleasepool {
|
|
// 执行一些内存密集型操作来触发垃圾回收
|
|
}
|
|
}
|
|
|
|
/// 建议内存清理
|
|
func suggestMemoryCleanup() {
|
|
print("💡 建议执行内存清理")
|
|
|
|
// 只清理非关键缓存
|
|
ImageCacheManager.shared.clearCache()
|
|
|
|
// 通知其他组件进行轻度清理
|
|
NotificationCenter.default.post(name: .memoryCleanupSuggestion, object: nil)
|
|
}
|
|
|
|
// MARK: - 临时文件清理
|
|
|
|
/// 清理临时文件
|
|
private func cleanupTempFiles() {
|
|
let tempPath = NSTemporaryDirectory()
|
|
let fileManager = FileManager.default
|
|
|
|
do {
|
|
let tempFiles = try fileManager.contentsOfDirectory(atPath: tempPath)
|
|
var cleanedCount = 0
|
|
|
|
for file in tempFiles {
|
|
let filePath = (tempPath as NSString).appendingPathComponent(file)
|
|
|
|
// 只删除图片相关的临时文件
|
|
if file.hasSuffix(".jpg") || file.hasSuffix(".png") || file.hasSuffix(".tmp") {
|
|
try fileManager.removeItem(atPath: filePath)
|
|
cleanedCount += 1
|
|
}
|
|
}
|
|
|
|
print("🗑️ 清理了 \(cleanedCount) 个临时文件")
|
|
} catch {
|
|
print("❌ 清理临时文件失败: \(error)")
|
|
}
|
|
}
|
|
|
|
// MARK: - 监控控制
|
|
|
|
/// 启动内存监控
|
|
func startMemoryMonitoring() {
|
|
stopMemoryMonitoring() // 先停止之前的监控
|
|
|
|
// 每30秒检查一次内存使用情况
|
|
memoryCheckTimer = Timer.scheduledTimer(withTimeInterval: 30.0, repeats: true) { [weak self] _ in
|
|
self?.checkMemoryPressure()
|
|
}
|
|
|
|
print("📊 内存监控已启动")
|
|
}
|
|
|
|
/// 停止内存监控
|
|
func stopMemoryMonitoring() {
|
|
memoryCheckTimer?.invalidate()
|
|
memoryCheckTimer = nil
|
|
print("📊 内存监控已停止")
|
|
}
|
|
|
|
// MARK: - 内存警告处理
|
|
|
|
@objc private func handleMemoryWarning() {
|
|
memoryWarningCount += 1
|
|
print("🚨 收到内存警告 #\(memoryWarningCount)")
|
|
|
|
// 立即执行内存清理
|
|
performMemoryCleanup()
|
|
|
|
// 通知其他组件
|
|
NotificationCenter.default.post(name: .memoryWarning, object: nil)
|
|
}
|
|
|
|
// MARK: - 内存统计
|
|
|
|
/// 获取内存统计信息
|
|
func getMemoryStatistics() -> MemoryStatistics {
|
|
let details = getMemoryUsageDetails()
|
|
|
|
return MemoryStatistics(
|
|
usedMB: details.usedMB,
|
|
totalMB: details.totalMB,
|
|
percentage: details.percentage,
|
|
warningCount: memoryWarningCount,
|
|
timestamp: Date()
|
|
)
|
|
}
|
|
|
|
/// 打印内存统计信息
|
|
func printMemoryStatistics() {
|
|
let stats = getMemoryStatistics()
|
|
print("📊 内存统计信息:")
|
|
print(" - 已使用: \(String(format: "%.1f MB", stats.usedMB))")
|
|
print(" - 总内存: \(String(format: "%.1f MB", stats.totalMB))")
|
|
print(" - 使用率: \(String(format: "%.1f%%", stats.percentage))")
|
|
print(" - 警告次数: \(stats.warningCount)")
|
|
print(" - 检查时间: \(stats.timestamp)")
|
|
}
|
|
}
|
|
|
|
// MARK: - 内存统计结构
|
|
struct MemoryStatistics {
|
|
let usedMB: Double
|
|
let totalMB: Double
|
|
let percentage: Double
|
|
let warningCount: Int
|
|
let timestamp: Date
|
|
}
|
|
|
|
// MARK: - 通知名称扩展
|
|
extension Notification.Name {
|
|
static let memoryWarning = Notification.Name("memoryWarning")
|
|
static let memoryCleanup = Notification.Name("memoryCleanup")
|
|
static let memoryCleanupSuggestion = Notification.Name("memoryCleanupSuggestion")
|
|
}
|
|
|
|
// MARK: - 内存优化工具
|
|
extension MemoryMonitor {
|
|
|
|
/// 检查是否需要进行内存优化
|
|
func shouldOptimizeMemory() -> Bool {
|
|
let details = getMemoryUsageDetails()
|
|
return details.percentage > 70.0 || details.usedMB > 200.0
|
|
}
|
|
|
|
/// 获取内存优化建议
|
|
func getMemoryOptimizationSuggestions() -> [String] {
|
|
var suggestions: [String] = []
|
|
let details = getMemoryUsageDetails()
|
|
|
|
if details.percentage > 80.0 {
|
|
suggestions.append("内存使用率过高,建议关闭其他应用")
|
|
}
|
|
|
|
if details.usedMB > 250.0 {
|
|
suggestions.append("内存使用量过大,建议重启应用")
|
|
}
|
|
|
|
if memoryWarningCount > 3 {
|
|
suggestions.append("频繁收到内存警告,建议检查内存泄漏")
|
|
}
|
|
|
|
if suggestions.isEmpty {
|
|
suggestions.append("内存使用正常")
|
|
}
|
|
|
|
return suggestions
|
|
}
|
|
|
|
/// 执行深度内存清理
|
|
func performDeepMemoryCleanup() {
|
|
print("🧹 执行深度内存清理")
|
|
|
|
// 1. 清理所有缓存
|
|
ImageCacheManager.shared.clearCache()
|
|
|
|
// 2. 清理临时文件
|
|
cleanupTempFiles()
|
|
|
|
// 3. 清理系统缓存
|
|
URLCache.shared.removeAllCachedResponses()
|
|
|
|
// 4. 通知所有组件进行清理
|
|
NotificationCenter.default.post(name: .deepMemoryCleanup, object: nil)
|
|
|
|
// 5. 强制垃圾回收
|
|
autoreleasepool {
|
|
// 执行内存密集型操作
|
|
let _ = Array(0..<1000).map { _ in String(repeating: "x", count: 1000) }
|
|
}
|
|
|
|
print("✅ 深度内存清理完成")
|
|
}
|
|
}
|
|
|
|
// MARK: - 深度清理通知
|
|
extension Notification.Name {
|
|
static let deepMemoryCleanup = Notification.Name("deepMemoryCleanup")
|
|
}
|