feat: 최근 들은 콘텐츠 로컬 DB 추가
This commit is contained in:
		
							
								
								
									
										123
									
								
								SodaLive/Sources/MyPage/Recent/DB/RecentContentService.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								SodaLive/Sources/MyPage/Recent/DB/RecentContentService.swift
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,123 @@
 | 
			
		||||
//
 | 
			
		||||
//  RecentContentService.swift
 | 
			
		||||
//  SodaLive
 | 
			
		||||
//
 | 
			
		||||
//  Created by klaus on 7/28/25.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
import CoreData
 | 
			
		||||
import Combine
 | 
			
		||||
 | 
			
		||||
class RecentContentService {
 | 
			
		||||
    private let viewContext: NSManagedObjectContext
 | 
			
		||||
    
 | 
			
		||||
    init(context: NSManagedObjectContext = PersistenceController.shared.container.viewContext) {
 | 
			
		||||
        self.viewContext = context
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    func getRecentContents(limit: Int = 10) -> [RecentContent] {
 | 
			
		||||
        let request = RecentContent.fetchRequest()
 | 
			
		||||
        request.sortDescriptors = [NSSortDescriptor(key: "listenedAt", ascending: false)]
 | 
			
		||||
        request.fetchLimit = limit
 | 
			
		||||
        
 | 
			
		||||
        do {
 | 
			
		||||
            return try viewContext.fetch(request)
 | 
			
		||||
        } catch {
 | 
			
		||||
            print("Error fetching recent contents: \(error)")
 | 
			
		||||
            return []
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    func insertRecentContent(contentId: Int64, coverImageUrl: String, title: String, creatorNickname: String) {
 | 
			
		||||
        // Check if content already exists
 | 
			
		||||
        if let existingContent = findContent(byId: contentId) {
 | 
			
		||||
            // Update timestamp
 | 
			
		||||
            existingContent.listenedAt = Date()
 | 
			
		||||
            saveContext()
 | 
			
		||||
        } else {
 | 
			
		||||
            // Create new content
 | 
			
		||||
            let newContent = RecentContent(context: viewContext)
 | 
			
		||||
            newContent.contentId = contentId
 | 
			
		||||
            newContent.coverImageUrl = coverImageUrl
 | 
			
		||||
            newContent.title = title
 | 
			
		||||
            newContent.creatorNickname = creatorNickname
 | 
			
		||||
            newContent.listenedAt = Date()
 | 
			
		||||
            saveContext()
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Keep only most recent 10 items
 | 
			
		||||
        keepMostRecent(limit: 10)
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    func deleteByContentId(contentId: Int64) {
 | 
			
		||||
        if let content = findContent(byId: contentId) {
 | 
			
		||||
            viewContext.delete(content)
 | 
			
		||||
            saveContext()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    func getCount() -> Int {
 | 
			
		||||
        let request = RecentContent.fetchRequest()
 | 
			
		||||
        
 | 
			
		||||
        do {
 | 
			
		||||
            return try viewContext.count(for: request)
 | 
			
		||||
        } catch {
 | 
			
		||||
            print("Error counting recent contents: \(error)")
 | 
			
		||||
            return 0
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    func truncate() {
 | 
			
		||||
        let fetchRequest: NSFetchRequest<NSFetchRequestResult> = RecentContent.fetchRequest()
 | 
			
		||||
        let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
 | 
			
		||||
        
 | 
			
		||||
        do {
 | 
			
		||||
            try viewContext.execute(deleteRequest)
 | 
			
		||||
            saveContext()
 | 
			
		||||
        } catch {
 | 
			
		||||
            print("Error truncating recent contents: \(error)")
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private func keepMostRecent(limit: Int) {
 | 
			
		||||
        let count = getCount()
 | 
			
		||||
        if count <= limit { return }
 | 
			
		||||
        
 | 
			
		||||
        let request = RecentContent.fetchRequest()
 | 
			
		||||
        request.sortDescriptors = [NSSortDescriptor(key: "listenedAt", ascending: false)]
 | 
			
		||||
        
 | 
			
		||||
        do {
 | 
			
		||||
            let allContents = try viewContext.fetch(request)
 | 
			
		||||
            for i in limit..<allContents.count {
 | 
			
		||||
                viewContext.delete(allContents[i])
 | 
			
		||||
            }
 | 
			
		||||
            saveContext()
 | 
			
		||||
        } catch {
 | 
			
		||||
            print("Error keeping most recent contents: \(error)")
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private func findContent(byId contentId: Int64) -> RecentContent? {
 | 
			
		||||
        let request = RecentContent.fetchRequest()
 | 
			
		||||
        request.predicate = NSPredicate(format: "contentId == %lld", contentId)
 | 
			
		||||
        request.fetchLimit = 1
 | 
			
		||||
        
 | 
			
		||||
        do {
 | 
			
		||||
            let results = try viewContext.fetch(request)
 | 
			
		||||
            return results.first
 | 
			
		||||
        } catch {
 | 
			
		||||
            print("Error finding content by ID: \(error)")
 | 
			
		||||
            return nil
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private func saveContext() {
 | 
			
		||||
        if viewContext.hasChanges {
 | 
			
		||||
            do {
 | 
			
		||||
                try viewContext.save()
 | 
			
		||||
            } catch {
 | 
			
		||||
                print("Error saving context: \(error)")
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user