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

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")
}