Skip to content

Commit

Permalink
Merge pull request #2241 from onevcat/fix/strict-concurrency
Browse files Browse the repository at this point in the history
Implement full support for strict concurrency
  • Loading branch information
onevcat committed Apr 28, 2024
2 parents 8f928de + e3d19ad commit 893f933
Show file tree
Hide file tree
Showing 65 changed files with 1,164 additions and 577 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
import UIKit
import Kingfisher

protocol MainDataViewReloadable {
func reload()
protocol MainDataViewReloadable: Sendable {
@MainActor func reload()
}

extension UITableViewController: MainDataViewReloadable {
Expand All @@ -44,25 +44,26 @@ extension UICollectionViewController: MainDataViewReloadable {
}

protocol KingfisherActionAlertPopup {
@MainActor
func alertPopup(_ sender: Any) -> UIAlertController
}

func cleanCacheAction() -> UIAlertAction {
@MainActor func cleanCacheAction() -> UIAlertAction {
return UIAlertAction(title: "Clean Cache", style: .default) { _ in
KingfisherManager.shared.cache.clearMemoryCache()
KingfisherManager.shared.cache.clearDiskCache()
}
}

func reloadAction(_ reloadable: MainDataViewReloadable) -> UIAlertAction {
@MainActor func reloadAction(_ reloadable: MainDataViewReloadable) -> UIAlertAction {
return UIAlertAction(title: "Reload", style: .default) { _ in
reloadable.reload()
}
}

let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
@MainActor let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)

func createAlert(_ sender: Any, actions: [UIAlertAction]) -> UIAlertController {
@MainActor func createAlert(_ sender: Any, actions: [UIAlertAction]) -> UIAlertController {
let alert = UIAlertController(title: "Action", message: nil, preferredStyle: .actionSheet)
alert.popoverPresentationController?.barButtonItem = sender as? UIBarButtonItem
alert.popoverPresentationController?.permittedArrowDirections = .any
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ class IndicatorCollectionViewController: UICollectionViewController {
func startAnimatingView() {
view.isHidden = false
timer = Timer.scheduledTimer(withTimeInterval: 0.3, repeats: true) { _ in
UIView.animate(withDuration: 0.2, animations: {
if self.view.backgroundColor == .red {
self.view.backgroundColor = .orange
} else {
self.view.backgroundColor = .red
}
})
Task { @MainActor in
UIView.animate(withDuration: 0.2, animations: {
if self.view.backgroundColor == .red {
self.view.backgroundColor = .orange
} else {
self.view.backgroundColor = .red
}
})
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class ProgressiveJPEGViewController: UIViewController {
processorIdentifier: self.processor.identifier,
callbackQueue: .mainAsync,
completionHandler: {
self.loadImage()
Task { @MainActor in self.loadImage() }
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,11 @@ class TextAttachmentViewController: UIViewController {
attributedText.replaceCharacters(in: NSRange(), with: NSAttributedString(attachment: textAttachment))
label.attributedText = attributedText

let label = getLabel()
KF.url(URL(string: "https://onevcat.com/assets/images/avatar.jpg")!)
.resizing(referenceSize: CGSize(width: 30, height: 30))
.roundCorner(radius: .point(15))
.set(to: textAttachment, attributedView: self.getLabel())
.set(to: textAttachment, attributedView: label)
}

func getLabel() -> UILabel {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import WatchKit
import Foundation
import Kingfisher

var count = 0
@MainActor var count = 0

class InterfaceController: WKInterfaceController {

Expand All @@ -48,9 +48,9 @@ class InterfaceController: WKInterfaceController {
func refreshImage() {
let url = URL(string: "https://raw.githubusercontent.com/onevcat/Kingfisher/master/images/kingfisher-\(currentIndex! + 1).jpg")!
print("Start loading... \(url)")
interfaceImage.kf.setImage(with: url) { r in
interfaceImage.kf.setImage(with: url, completionHandler: { r in
print(r)
}
})
}

override func willActivate() {
Expand Down
2 changes: 2 additions & 0 deletions Demo/Kingfisher-Demo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1027,6 +1027,7 @@
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TVOS_DEPLOYMENT_TARGET = 13.0;
Expand Down Expand Up @@ -1084,6 +1085,7 @@
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TVOS_DEPLOYMENT_TARGET = 13.0;
Expand Down
4 changes: 3 additions & 1 deletion Kingfisher.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1087,8 +1087,8 @@
CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE;
CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES;
CURRENT_PROJECT_VERSION = 2700;
DEFINES_MODULE = YES;
DEAD_CODE_STRIPPING = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 2700;
DYLIB_INSTALL_NAME_BASE = "@rpath";
Expand Down Expand Up @@ -1125,6 +1125,7 @@
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_INSTALL_OBJC_HEADER = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_STRICT_CONCURRENCY = complete;
TARGETED_DEVICE_FAMILY = "1,2,3,4,7";
VERSIONING_SYSTEM = "apple-generic";
};
Expand Down Expand Up @@ -1185,6 +1186,7 @@
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_INSTALL_OBJC_HEADER = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_STRICT_CONCURRENCY = complete;
TARGETED_DEVICE_FAMILY = "1,2,3,4,7";
VERSIONING_SYSTEM = "apple-generic";
};
Expand Down
2 changes: 1 addition & 1 deletion Sources/Cache/CacheSerializer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import UIKit

/// A `CacheSerializer` is used to convert some data to an image object after retrieving it from disk storage,
/// and vice versa, to convert an image to a data object for storing it to the disk storage.
public protocol CacheSerializer {
public protocol CacheSerializer: Sendable {

/// Retrieves the serialized data from a provided image and optional original data for caching to disk.
///
Expand Down
18 changes: 12 additions & 6 deletions Sources/Cache/DiskStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,18 @@ public enum DiskStorage {
/// ``DiskStorage/Config`` value or by modifying the ``DiskStorage/Backend/config`` property after it has been
/// created. The ``DiskStorage/Backend`` will use the file's attributes to keep track of a file for its expiration
/// or size limitation.
public class Backend<T: DataTransformable> {
public class Backend<T: DataTransformable>: @unchecked Sendable {

private let propertyQueue = DispatchQueue(label: "com.onevcat.kingfisher.DiskStorage.Backend.propertyQueue")

private var _config: Config
/// The configuration used for this disk storage.
///
/// It is a value you can set and use to configure the storage as needed.
public var config: Config
public var config: Config {
get { propertyQueue.sync { _config } }
set { propertyQueue.sync { _config = newValue } }
}

/// The final storage URL on disk of the disk storage ``DiskStorage/Backend``, considering the
/// ``DiskStorage/Config/name`` and the ``DiskStorage/Config/cachePathBlock``.
Expand Down Expand Up @@ -83,7 +89,7 @@ public enum DiskStorage {

// Break any possible retain cycle set by outside.
config.cachePathBlock = nil
self.config = config
_config = config

metaChangingQueue = DispatchQueue(label: creation.cacheName)
setupCacheChecking()
Expand Down Expand Up @@ -255,7 +261,7 @@ public enum DiskStorage {
let data = try Data(contentsOf: fileURL)
let obj = try T.fromData(data)
metaChangingQueue.async {
meta.extendExpiration(with: fileManager, extendingExpiration: extendingExpiration)
meta.extendExpiration(with: self.config.fileManager, extendingExpiration: extendingExpiration)
}
return obj
} catch {
Expand Down Expand Up @@ -463,7 +469,7 @@ public enum DiskStorage {
extension DiskStorage {

/// Represents the configuration used in a ``DiskStorage/Backend``.
public struct Config {
public struct Config: @unchecked Sendable {

/// The file size limit on disk of the storage in bytes.
///
Expand Down Expand Up @@ -496,7 +502,7 @@ extension DiskStorage {
/// A closure that takes in the initial directory path and generates the final disk cache path.
///
/// You can use it to fully customize your cache path.
public var cachePathBlock: ((_ directory: URL, _ cacheName: String) -> URL)! = {
public var cachePathBlock: (@Sendable (_ directory: URL, _ cacheName: String) -> URL)! = {
(directory, cacheName) in
return directory.appendingPathComponent(cacheName, isDirectory: true)
}
Expand Down

0 comments on commit 893f933

Please sign in to comment.