@MainActor @available(iOS 16.0, *)
class QuoteBox: ObservableObject {
@Published var isLiked: Bool = false
@Published var isBookmarked: Bool = false
@Published var likes: Int = 0
@Published var isLiking: Bool = false
@MainActor func toggleBookmark(for quote: Quote) {
isBookmarked.toggle()
var bookmarkedQuotes = getBookmarkedQuotes()
if isBookmarked {
bookmarkedQuotes.append(quote)
} else {
bookmarkedQuotes.removeAll { $0.id == quote.id }
}
saveBookmarkedQuotes(bookmarkedQuotes)
interactionsIncrease()
}
@MainActor func toggleLike(for quote: Quote) {
isLiked.toggle()
var likedQuotes = getLikedQuotes()
if isLiked {
likedQuotes.append(quote)
} else {
likedQuotes.removeAll { $0.id == quote.id }
}
saveLikedQuotes(likedQuotes)
interactionsIncrease()
}
func getQuoteLikeCountMethod(for quote: Quote, completion: @escaping (Int) -> Void) {
getLikeCountForQuote(quoteGiven: quote) { likeCount in
completion(likeCount)
}
}
func likeQuoteAction(for quote: Quote) {
guard !isLiking else { return }
isLiking = true
// Check if the quote is already liked
let isAlreadyLiked = isQuoteLiked(quote)
// Call the like/unlike API based on the current like status
if isAlreadyLiked {
unlikeQuote(quoteID: quote.id) { updatedQuote, error in
DispatchQueue.main.async {
if let updatedQuote = updatedQuote {
// Update likes count
self.likes = updatedQuote.likes ?? 0
}
self.isLiking = false
}
}
} else {
likeQuote(quoteID: quote.id) { updatedQuote, error in
DispatchQueue.main.async {
if let updatedQuote = updatedQuote {
// Update likes count
self.likes = updatedQuote.likes ?? 0
}
self.isLiking = false
}
}
}
}
}
I’m getting the following purple warning in XCode: “Publishing changes from background threads is not allowed; make sure to publish values from the main thread (via operators like receive(on:)) on model updates.”
I thought that adding the @MainActor
wrapper would resolve this issue, as this comment on another answer states. Thus, I’m confused why this issue is still stemming, from what seems to be the @Published
variable definitions in this class.
I’ve tried to remove the inner @MainActor
wrappers, and add DispatchQueue.main.async{}
around asynchronous operations like so (but this doesn’t remove aforementioned the XCode warning):
import SwiftUI
import WidgetKit
import UserNotifications
import UIKit
import Foundation
import StoreKit
@MainActor @available(iOS 16.0, *)
class QuoteBox: ObservableObject {
@Published var isLiked: Bool = false
@Published var isBookmarked: Bool = false
@Published var likes: Int = 0
@Published var isLiking: Bool = false
func toggleBookmark(for quote: Quote) {
DispatchQueue.main.async {
self.isBookmarked.toggle()
var bookmarkedQuotes = getBookmarkedQuotes()
if self.isBookmarked {
bookmarkedQuotes.append(quote)
} else {
bookmarkedQuotes.removeAll { $0.id == quote.id }
}
saveBookmarkedQuotes(bookmarkedQuotes)
interactionsIncrease()
}
}
func toggleLike(for quote: Quote) {
DispatchQueue.main.async {
self.isLiked.toggle()
var likedQuotes = getLikedQuotes()
if self.isLiked {
likedQuotes.append(quote)
} else {
likedQuotes.removeAll { $0.id == quote.id }
}
saveLikedQuotes(likedQuotes)
interactionsIncrease()
}
}
func getQuoteLikeCountMethod(for quote: Quote, completion: @escaping (Int) -> Void) {
getLikeCountForQuote(quoteGiven: quote) { likeCount in
DispatchQueue.main.async {
completion(likeCount)
}
}
}
func likeQuoteAction(for quote: Quote) {
guard !isLiking else { return }
DispatchQueue.main.async {
self.isLiking = true
}
// Check if the quote is already liked
let isAlreadyLiked = isQuoteLiked(quote)
// Call the like/unlike API based on the current like status
if isAlreadyLiked {
unlikeQuote(quoteID: quote.id) { updatedQuote, error in
DispatchQueue.main.async {
if let updatedQuote = updatedQuote {
// Update likes count
self.likes = updatedQuote.likes ?? 0
}
self.isLiking = false
}
}
} else {
likeQuote(quoteID: quote.id) { updatedQuote, error in
DispatchQueue.main.async {
if let updatedQuote = updatedQuote {
// Update likes count
self.likes = updatedQuote.likes ?? 0
}
self.isLiking = false
}
}
}
}
}
4