mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-31 21:41:33 +00:00
#1607 (widget is slow to reload)
- Added logging to help check performance (look in Console, filter on "🚧")
This commit is contained in:
parent
742ae95501
commit
64d1e83af7
8 changed files with 153 additions and 25 deletions
|
@ -32,7 +32,7 @@
|
|||
173CB31126BCE94700BA872A /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 173CB31026BCE94700BA872A /* SwiftUI.framework */; };
|
||||
173CB31426BCE94700BA872A /* WidgetExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 173CB31326BCE94700BA872A /* WidgetExtension.swift */; };
|
||||
173CB31626BCE94A00BA872A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 173CB31526BCE94A00BA872A /* Assets.xcassets */; };
|
||||
173CB31A26BCE94A00BA872A /* Widget Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 173CB30D26BCE94700BA872A /* Widget Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
173CB31A26BCE94A00BA872A /* NewsBlur Widget.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 173CB30D26BCE94700BA872A /* NewsBlur Widget.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
1740C6881C10FD75005EA453 /* theme_color_dark.png in Resources */ = {isa = PBXBuildFile; fileRef = 1740C6841C10FD75005EA453 /* theme_color_dark.png */; };
|
||||
1740C6891C10FD75005EA453 /* theme_color_light.png in Resources */ = {isa = PBXBuildFile; fileRef = 1740C6851C10FD75005EA453 /* theme_color_light.png */; };
|
||||
1740C68A1C10FD75005EA453 /* theme_color_medium.png in Resources */ = {isa = PBXBuildFile; fileRef = 1740C6861C10FD75005EA453 /* theme_color_medium.png */; };
|
||||
|
@ -90,6 +90,7 @@
|
|||
17876BA51C99137B0055DD15 /* accessory_disclosure@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 17876BA31C99137B0055DD15 /* accessory_disclosure@2x.png */; };
|
||||
1788939D249332E6004CBA4E /* g_icn_search.png in Resources */ = {isa = PBXBuildFile; fileRef = 1788939C249332E6004CBA4E /* g_icn_search.png */; };
|
||||
1791C21526C4C7BC00D815AA /* WidgetStoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1791C21426C4C7BC00D815AA /* WidgetStoryView.swift */; };
|
||||
17997C5827A8FDD100483E69 /* WidgetDebugTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17997C5727A8FDD100483E69 /* WidgetDebugTimer.swift */; };
|
||||
179DD9CF23DFDD51007BFD21 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 179DD9CE23DFDD51007BFD21 /* CloudKit.framework */; };
|
||||
17A396D924F86A8F0023C9E2 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 17A396D824F86A8F0023C9E2 /* MainInterface.storyboard */; };
|
||||
17AACFE122279A3C00DE6EA4 /* autoscroll_resume@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 17AACFD722279A3900DE6EA4 /* autoscroll_resume@2x.png */; };
|
||||
|
@ -702,7 +703,7 @@
|
|||
files = (
|
||||
177551DF238E228A00E27818 /* Old NewsBlur Latest.appex in Embed App Extensions */,
|
||||
1749391B1C251BFE003D98AA /* Share Extension.appex in Embed App Extensions */,
|
||||
173CB31A26BCE94A00BA872A /* Widget Extension.appex in Embed App Extensions */,
|
||||
173CB31A26BCE94A00BA872A /* NewsBlur Widget.appex in Embed App Extensions */,
|
||||
);
|
||||
name = "Embed App Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -734,7 +735,7 @@
|
|||
172AD273251D9F40000BB264 /* Storyboards.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storyboards.swift; sourceTree = "<group>"; };
|
||||
17362ADB23639B4E00A0FCCC /* OfflineFetchText.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OfflineFetchText.h; path = offline/OfflineFetchText.h; sourceTree = "<group>"; };
|
||||
17362ADC23639B4E00A0FCCC /* OfflineFetchText.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OfflineFetchText.m; path = offline/OfflineFetchText.m; sourceTree = "<group>"; };
|
||||
173CB30D26BCE94700BA872A /* Widget Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Widget Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
173CB30D26BCE94700BA872A /* NewsBlur Widget.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "NewsBlur Widget.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
173CB30E26BCE94700BA872A /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
|
||||
173CB31026BCE94700BA872A /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
|
||||
173CB31326BCE94700BA872A /* WidgetExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetExtension.swift; sourceTree = "<group>"; };
|
||||
|
@ -805,6 +806,7 @@
|
|||
17876BA31C99137B0055DD15 /* accessory_disclosure@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "accessory_disclosure@2x.png"; sourceTree = "<group>"; };
|
||||
1788939C249332E6004CBA4E /* g_icn_search.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = g_icn_search.png; sourceTree = "<group>"; };
|
||||
1791C21426C4C7BC00D815AA /* WidgetStoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetStoryView.swift; sourceTree = "<group>"; };
|
||||
17997C5727A8FDD100483E69 /* WidgetDebugTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetDebugTimer.swift; sourceTree = "<group>"; };
|
||||
179DD9CC23DFD20E007BFD21 /* BridgingHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BridgingHeader.h; path = "Other Sources/BridgingHeader.h"; sourceTree = "<group>"; };
|
||||
179DD9CE23DFDD51007BFD21 /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };
|
||||
17A396D824F86A8F0023C9E2 /* MainInterface.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = MainInterface.storyboard; sourceTree = "<group>"; };
|
||||
|
@ -1657,6 +1659,7 @@
|
|||
1723388D26BE440400610784 /* WidgetFeed.swift */,
|
||||
1723388C26BE440400610784 /* WidgetStory.swift */,
|
||||
1723388A26BE43EB00610784 /* WidgetLoader.swift */,
|
||||
17997C5727A8FDD100483E69 /* WidgetDebugTimer.swift */,
|
||||
173CB31526BCE94A00BA872A /* Assets.xcassets */,
|
||||
173CB31726BCE94A00BA872A /* Info.plist */,
|
||||
173CB31B26BCE94A00BA872A /* WidgetExtension.entitlements */,
|
||||
|
@ -1756,7 +1759,7 @@
|
|||
174939101C251BFE003D98AA /* Share Extension.appex */,
|
||||
FF8A94971DE3BB77000A4C31 /* Story Notification Service Extension.appex */,
|
||||
177551D3238E228A00E27818 /* Old NewsBlur Latest.appex */,
|
||||
173CB30D26BCE94700BA872A /* Widget Extension.appex */,
|
||||
173CB30D26BCE94700BA872A /* NewsBlur Widget.appex */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
@ -2867,9 +2870,9 @@
|
|||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
173CB30C26BCE94700BA872A /* Widget Extension */ = {
|
||||
173CB30C26BCE94700BA872A /* NewsBlur Widget */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 173CB31C26BCE94A00BA872A /* Build configuration list for PBXNativeTarget "Widget Extension" */;
|
||||
buildConfigurationList = 173CB31C26BCE94A00BA872A /* Build configuration list for PBXNativeTarget "NewsBlur Widget" */;
|
||||
buildPhases = (
|
||||
173CB30926BCE94700BA872A /* Sources */,
|
||||
173CB30A26BCE94700BA872A /* Frameworks */,
|
||||
|
@ -2879,9 +2882,9 @@
|
|||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "Widget Extension";
|
||||
name = "NewsBlur Widget";
|
||||
productName = WidgetExtension;
|
||||
productReference = 173CB30D26BCE94700BA872A /* Widget Extension.appex */;
|
||||
productReference = 173CB30D26BCE94700BA872A /* NewsBlur Widget.appex */;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
};
|
||||
1749390F1C251BFE003D98AA /* Share Extension */ = {
|
||||
|
@ -3051,7 +3054,7 @@
|
|||
1749390F1C251BFE003D98AA /* Share Extension */,
|
||||
FF8A94961DE3BB77000A4C31 /* Story Notification Service Extension */,
|
||||
177551D2238E228A00E27818 /* Old Widget Extension */,
|
||||
173CB30C26BCE94700BA872A /* Widget Extension */,
|
||||
173CB30C26BCE94700BA872A /* NewsBlur Widget */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
@ -3540,6 +3543,7 @@
|
|||
173CB31426BCE94700BA872A /* WidgetExtension.swift in Sources */,
|
||||
1723388E26BE440400610784 /* WidgetStory.swift in Sources */,
|
||||
1723389426C3775B00610784 /* WidgetBarView.swift in Sources */,
|
||||
17997C5827A8FDD100483E69 /* WidgetDebugTimer.swift in Sources */,
|
||||
1723388F26BE440400610784 /* WidgetFeed.swift in Sources */,
|
||||
1791C21526C4C7BC00D815AA /* WidgetStoryView.swift in Sources */,
|
||||
);
|
||||
|
@ -3745,7 +3749,7 @@
|
|||
/* Begin PBXTargetDependency section */
|
||||
173CB31926BCE94A00BA872A /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 173CB30C26BCE94700BA872A /* Widget Extension */;
|
||||
target = 173CB30C26BCE94700BA872A /* NewsBlur Widget */;
|
||||
targetProxy = 173CB31826BCE94A00BA872A /* PBXContainerItemProxy */;
|
||||
};
|
||||
1749391A1C251BFE003D98AA /* PBXTargetDependency */ = {
|
||||
|
@ -4415,7 +4419,7 @@
|
|||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
173CB31C26BCE94A00BA872A /* Build configuration list for PBXNativeTarget "Widget Extension" */ = {
|
||||
173CB31C26BCE94A00BA872A /* Build configuration list for PBXNativeTarget "NewsBlur Widget" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
173CB31D26BCE94A00BA872A /* Debug */,
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "173CB30C26BCE94700BA872A"
|
||||
BuildableName = "Widget Extension.appex"
|
||||
BlueprintName = "Widget Extension"
|
||||
BuildableName = "NewsBlur Widget.appex"
|
||||
BlueprintName = "NewsBlur Widget"
|
||||
ReferencedContainer = "container:NewsBlur.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<objects>
|
||||
<viewController storyboardIdentifier="DetailViewController" useStoryboardIdentifierAsRestorationIdentifier="YES" id="djW-7k-haK" customClass="DetailViewController" customModule="NewsBlur" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jTZ-4O-xyT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="818.5" height="834"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="1194" height="834"/>
|
||||
<subviews>
|
||||
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bPa-u1-Aml">
|
||||
<rect key="frame" x="0.0" y="74" width="1194" height="580"/>
|
||||
|
|
|
@ -248,7 +248,7 @@ class WidgetCache {
|
|||
|
||||
stories = try decoder.decode([Story].self, from: json)
|
||||
} catch {
|
||||
print("Error \(error)")
|
||||
NSLog("Error \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,7 +269,7 @@ class WidgetCache {
|
|||
|
||||
try json.write(to: url)
|
||||
} catch {
|
||||
print("Error \(error)")
|
||||
NSLog("Error \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,7 +295,7 @@ class WidgetCache {
|
|||
|
||||
try image.pngData()?.write(to: imageURL)
|
||||
} catch {
|
||||
print("Image error: \(error)")
|
||||
NSLog("Image saving error: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,7 +319,7 @@ class WidgetCache {
|
|||
storyImageCache[identifier] = nil
|
||||
}
|
||||
} catch {
|
||||
print("Flush story images error: \(error)")
|
||||
NSLog("Flush story images error: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -446,7 +446,7 @@ class WidgetCache {
|
|||
|
||||
return image
|
||||
} catch {
|
||||
print("Image error: \(error)")
|
||||
NSLog("Cached image loading error: \(error)")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
110
clients/ios/Widget Extension/WidgetDebugTimer.swift
Normal file
110
clients/ios/Widget Extension/WidgetDebugTimer.swift
Normal file
|
@ -0,0 +1,110 @@
|
|||
//
|
||||
// WidgetDebugTimer.swift
|
||||
// Widget Extension
|
||||
//
|
||||
// Created by David Sinclair on 2022-01-31.
|
||||
// Based on Dejal code.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Timer for debugging performance.
|
||||
class WidgetDebugTimer {
|
||||
/// Private singleton shared instance. Access via the class functions.
|
||||
private static let shared = WidgetDebugTimer()
|
||||
|
||||
/// Private initializer to prevent others constructing a new instance.
|
||||
private init() {
|
||||
formatter = NumberFormatter()
|
||||
formatter.minimumIntegerDigits = 1
|
||||
formatter.minimumFractionDigits = 6
|
||||
formatter.maximumFractionDigits = 6
|
||||
}
|
||||
|
||||
/// Information about each timer operation.
|
||||
private struct Info {
|
||||
/// The date the operation was started.
|
||||
var start: Date
|
||||
|
||||
/// The date this step was started.
|
||||
var step: Date
|
||||
|
||||
/// The indentation level.
|
||||
var level: Int
|
||||
|
||||
// If I ever add the closure-based long-running timers, add those properties.
|
||||
}
|
||||
|
||||
/// A dictionary of operation info, keyed on the operation string.
|
||||
private typealias InfoDictionary = [String : Info]
|
||||
|
||||
/// A dictionary of operation info, keyed on the operation string.
|
||||
private var info = InfoDictionary()
|
||||
|
||||
/// A number formatter for the number of seconds.
|
||||
private var formatter: NumberFormatter
|
||||
|
||||
/// Given an operation name, starts a debug timer. Use `print(_:step:)` after the code to time.
|
||||
///
|
||||
/// - Parameter operation: The name of the operation to time (used as both a key to group timers, and a debug label).
|
||||
/// - Parameter level: How much to indent the operation, for nested timers. Defaults to zero (no indentation).
|
||||
/// - Returns: The operation name, so it can be assigned to a variable instead of typing it again. Discardable.
|
||||
@discardableResult
|
||||
class func start(_ operation: String, level: Int = 0) -> String {
|
||||
let date = Date()
|
||||
|
||||
shared.info[operation] = Info(start: date, step: date, level: level)
|
||||
|
||||
return operation
|
||||
}
|
||||
|
||||
/// Given an operation name, that must have been previously started via `start(_:)`, prints the total time so far and (if a step is provided) the time since that this step took, i.e. since the start or the previous step.
|
||||
///
|
||||
/// - Parameter operation: The name of the operation to time.
|
||||
/// - Parameter step: The name of the step of the operation. May be omitted if there's only one interesting step.
|
||||
class func print(_ operation: String, step: String? = nil) {
|
||||
let date = Date()
|
||||
|
||||
guard let currentInfo = shared.info[operation] else {
|
||||
NSLog("\(operation): forgot to call start(_:) first!")
|
||||
return
|
||||
}
|
||||
|
||||
let totalDuration = date.timeIntervalSince(currentInfo.start)
|
||||
|
||||
guard let step = step else {
|
||||
NSLog("\(String(repeating: " ", count: currentInfo.level * 2))\(operation) took \(shared.formatter.string(from: NSNumber(value: totalDuration)) ?? "?") seconds")
|
||||
return
|
||||
}
|
||||
|
||||
let stepDuration = date.timeIntervalSince(currentInfo.step)
|
||||
var newInfo = currentInfo
|
||||
let alert = stepDuration < 0.001 ? "" : stepDuration < 0.01 ? " 🚨" : stepDuration < 0.1 ? " 🚨🚨" : stepDuration < 1.0 ? " 🚨🚨🚨" : " 🚨🚨🚨🚨"
|
||||
|
||||
NSLog("\(String(repeating: " ", count: currentInfo.level * 2))\(operation): \(step) took \(shared.formatter.string(from: NSNumber(value: stepDuration)) ?? "?") seconds (total \(shared.formatter.string(from: NSNumber(value: totalDuration)) ?? "?") seconds)\(alert)")
|
||||
|
||||
newInfo.step = date
|
||||
|
||||
shared.info[operation] = newInfo
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience timer for debugging performance of a code scope; automatically prints the info when exiting the scope.
|
||||
class DebugScopeTimer {
|
||||
/// The current operation.
|
||||
let operation: String
|
||||
|
||||
/// Initializer. Assign this to a variable to establish the scope, e.g. `let debug = DebugScopeTimer("Thing")` (this will result in a warning, but that can be useful to remind me to remove the timer; can't assign to underscore, as that is immediately released).
|
||||
///
|
||||
/// - Parameter operation: The name of the operation to time.
|
||||
init(_ operation: String) {
|
||||
self.operation = operation
|
||||
|
||||
WidgetDebugTimer.start(operation)
|
||||
}
|
||||
|
||||
/// Deinitializer. Prints the info when exiting the scope.
|
||||
deinit {
|
||||
WidgetDebugTimer.print(operation)
|
||||
}
|
||||
}
|
|
@ -23,13 +23,19 @@ struct Provider: TimelineProvider {
|
|||
}
|
||||
|
||||
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
|
||||
let operation = WidgetDebugTimer.start("🚧 getTimeline")
|
||||
|
||||
cache.loadCachedStories()
|
||||
|
||||
WidgetDebugTimer.print(operation, step: "loadCachedStories")
|
||||
|
||||
if context.isPreview && !cache.stories.isEmpty {
|
||||
return
|
||||
}
|
||||
|
||||
cache.load {
|
||||
WidgetDebugTimer.print(operation, step: "cache.load()")
|
||||
|
||||
var entries: [SimpleEntry] = []
|
||||
|
||||
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
|
||||
|
@ -47,6 +53,8 @@ struct Provider: TimelineProvider {
|
|||
|
||||
let timeline = Timeline(entries: entries, policy: .atEnd)
|
||||
|
||||
WidgetDebugTimer.print(operation, step: "making timeline")
|
||||
|
||||
let imageRequestGroup = DispatchGroup()
|
||||
|
||||
for feed in cache.feeds {
|
||||
|
@ -66,6 +74,8 @@ struct Provider: TimelineProvider {
|
|||
}
|
||||
|
||||
imageRequestGroup.notify(queue: .main) {
|
||||
WidgetDebugTimer.print(operation, step: "requesting images")
|
||||
|
||||
completion(timeline)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ struct Feed: Identifiable {
|
|||
///
|
||||
/// - Parameter dictionary: Dictionary representation.
|
||||
init(from dictionary: Dictionary) {
|
||||
let operation = WidgetDebugTimer.start("reading feed")
|
||||
|
||||
id = dictionary[DictionaryKeys.id] as? String ?? ""
|
||||
title = dictionary[DictionaryKeys.title] as? String ?? ""
|
||||
|
||||
|
@ -51,6 +53,8 @@ struct Feed: Identifiable {
|
|||
} else {
|
||||
rightColor = Self.from(hexString: "505050")
|
||||
}
|
||||
|
||||
WidgetDebugTimer.print(operation, step: "title: \(title)")
|
||||
}
|
||||
|
||||
/// Initializer for a sample.
|
||||
|
@ -93,7 +97,7 @@ struct Feed: Identifiable {
|
|||
blue = Double( hex & 0x0000FF) / 255
|
||||
}
|
||||
|
||||
print("Reading color from '\(hexString)': red: \(red), green: \(green), blue: \(blue), alpha: \(alpha)")
|
||||
NSLog("Reading color from '\(hexString)': red: \(red), green: \(green), blue: \(blue), alpha: \(alpha)")
|
||||
|
||||
return Color(.sRGB, red: red, green: green, blue: blue, opacity: alpha)
|
||||
}
|
||||
|
|
|
@ -46,17 +46,17 @@ class Loader: NSObject, URLSessionDataDelegate {
|
|||
|
||||
completionHandler(.allow)
|
||||
}
|
||||
|
||||
|
||||
func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
|
||||
print("error: \(error.debugDescription)")
|
||||
NSLog("error: \(error.debugDescription)")
|
||||
}
|
||||
|
||||
|
||||
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
|
||||
print("data: \(data)")
|
||||
NSLog("🚧 \(dataTask.currentRequest?.url?.path ?? "?") data: \(data)")
|
||||
|
||||
receivedData.append(data)
|
||||
}
|
||||
|
||||
|
||||
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
|
||||
if let error = error {
|
||||
completion(.failure(error))
|
||||
|
|
Loading…
Add table
Reference in a new issue