chore(deps): update
This commit is contained in:
parent
1540f2c1d7
commit
01f3e3da2e
|
@ -13,7 +13,9 @@ class Logger {
|
|||
var fileLogger: DDFileLogger = DDFileLogger()
|
||||
|
||||
private init() {
|
||||
DDLog.add(DDTTYLogger.sharedInstance) // TTY = Xcode console
|
||||
if let tty = DDTTYLogger.sharedInstance {
|
||||
DDLog.add(tty) // TTY = Xcode console
|
||||
}
|
||||
fileLogger.rollingFrequency = TimeInterval(60 * 60 * 24) // 24 hours
|
||||
fileLogger.logFileManager.maximumNumberOfLogFiles = 3
|
||||
DDLog.add(fileLogger)
|
||||
|
|
2
Podfile
2
Podfile
|
@ -14,7 +14,7 @@ target 'ClashX' do
|
|||
inhibit_all_warnings!
|
||||
use_frameworks!
|
||||
pod 'LetsMove'
|
||||
pod 'Alamofire', '~> 5.0.0-rc.3'
|
||||
pod 'Alamofire', '~> 5.0'
|
||||
pod 'SwiftyJSON'
|
||||
pod 'RxSwift'
|
||||
pod 'RxCocoa'
|
||||
|
|
35
Podfile.lock
35
Podfile.lock
|
@ -1,25 +1,25 @@
|
|||
PODS:
|
||||
- Alamofire (5.0.0-rc.3)
|
||||
- CocoaLumberjack/Core (3.6.0)
|
||||
- CocoaLumberjack/Swift (3.6.0):
|
||||
- Alamofire (5.0.2)
|
||||
- CocoaLumberjack/Core (3.6.1)
|
||||
- CocoaLumberjack/Swift (3.6.1):
|
||||
- CocoaLumberjack/Core
|
||||
- Crashlytics (3.14.0):
|
||||
- Fabric (~> 1.10.2)
|
||||
- Fabric (1.10.2)
|
||||
- LetsMove (1.24)
|
||||
- RxCocoa (5.0.1):
|
||||
- RxCocoa (5.1.0):
|
||||
- RxRelay (~> 5)
|
||||
- RxSwift (~> 5)
|
||||
- RxRelay (5.0.1):
|
||||
- RxRelay (5.1.0):
|
||||
- RxSwift (~> 5)
|
||||
- RxSwift (5.0.1)
|
||||
- Sparkle (1.22.0)
|
||||
- RxSwift (5.1.0)
|
||||
- Sparkle (1.23.0)
|
||||
- Starscream (3.1.1)
|
||||
- SwiftyJSON (5.0.0)
|
||||
- WebViewJavascriptBridge (6.0.3)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Alamofire (~> 5.0.0-rc.3)
|
||||
- Alamofire (~> 5.0)
|
||||
- CocoaLumberjack/Swift
|
||||
- Crashlytics
|
||||
- Fabric
|
||||
|
@ -36,31 +36,30 @@ SPEC REPOS:
|
|||
- Alamofire
|
||||
- CocoaLumberjack
|
||||
- Crashlytics
|
||||
- Fabric
|
||||
- LetsMove
|
||||
- RxCocoa
|
||||
- RxRelay
|
||||
- RxSwift
|
||||
- Sparkle
|
||||
- Starscream
|
||||
- SwiftyJSON
|
||||
- WebViewJavascriptBridge
|
||||
https://github.com/cocoapods/specs.git:
|
||||
- Fabric
|
||||
- RxSwift
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Alamofire: ca8c0de6906873be89d6deec5c8de279e00bf872
|
||||
CocoaLumberjack: 78b0c238666f4f58db069738ec176f4519557516
|
||||
Alamofire: 3ba7a4db18b4f62c4a1c0e1cb39d7f3d52e10ada
|
||||
CocoaLumberjack: b17ae15142558d08bbacf69775fa10c4abbebcc9
|
||||
Crashlytics: 540b7e5f5da5a042647227a5e3ac51d85eed06df
|
||||
Fabric: 706c8b8098fff96c33c0db69cbf81f9c551d0d74
|
||||
LetsMove: fefe56bc7bc7fb7d37049e28a14f297961229fc5
|
||||
RxCocoa: e741b9749968e8a143e2b787f1dfbff2b63d0a5c
|
||||
RxRelay: 89d54507f4fd4d969e6ec1d4bd7f3673640b4640
|
||||
RxSwift: e2dc62b366a3adf6a0be44ba9f405efd4c94e0c4
|
||||
Sparkle: 593ac2e677c07bcb6c3b22d621240e7cbedaab57
|
||||
RxCocoa: 13d2a4d7546a34b8ececae8c281e4ea1dbb94f2b
|
||||
RxRelay: a168bd6caf712d00c676ac344e9295afc93b418e
|
||||
RxSwift: ad5874f24bb0dbffd1e9bb8443604e3578796c7a
|
||||
Sparkle: 55b1a87ba69d56913375a281546b7c82dec95bb0
|
||||
Starscream: 4bb2f9942274833f7b4d296a55504dcfc7edb7b0
|
||||
SwiftyJSON: 36413e04c44ee145039d332b4f4e2d3e8d6c4db7
|
||||
WebViewJavascriptBridge: 7f5bc4d3581e672e8f32bd0f812d54bc69bb8e29
|
||||
|
||||
PODFILE CHECKSUM: 8dd9c30013fa97b5c735e427620c41790488a2a1
|
||||
PODFILE CHECKSUM: b104b5e59f0be7cdf17282b19ab5917132171e6f
|
||||
|
||||
COCOAPODS: 1.7.5
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
|
||||
Copyright (c) 2014-2020 Alamofire Software Foundation (http://alamofire.org/)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||

|
||||
|
||||
[](https://travis-ci.org/Alamofire/Alamofire)
|
||||
[](https://github.com/Alamofire/Alamofire/actions)
|
||||
[](https://img.shields.io/cocoapods/v/Alamofire.svg)
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](https://alamofire.github.io/Alamofire)
|
||||
|
@ -10,8 +10,6 @@
|
|||
|
||||
Alamofire is an HTTP networking library written in Swift.
|
||||
|
||||
**⚠️⚠️⚠️ WARNING ⚠️⚠️⚠️** This documentation is out of date during the Alamofire 5 beta process.
|
||||
|
||||
- [Features](#features)
|
||||
- [Component Libraries](#component-libraries)
|
||||
- [Requirements](#requirements)
|
||||
|
@ -24,7 +22,7 @@ Alamofire is an HTTP networking library written in Swift.
|
|||
- **Large Data -** [Downloading Data to a File](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#downloading-data-to-a-file), [Uploading Data to a Server](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#uploading-data-to-a-server)
|
||||
- **Tools -** [Statistical Metrics](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#statistical-metrics), [cURL Command Output](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#curl-command-output)
|
||||
- [Advanced Usage](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md)
|
||||
- **URL Session -** [Session Manager](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#session-manager), [Session Delegate](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#session-delegate), [Request](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#request)
|
||||
- **URL Session -** [Session Manager](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#session), [Session Delegate](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#sessiondelegate), [Request](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#request)
|
||||
- **Routing -** [Routing Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#routing-requests), [Adapting and Retrying Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#adapting-and-retrying-requests)
|
||||
- **Model Objects -** [Custom Response Serialization](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#custom-response-serialization)
|
||||
- **Connection -** [Security](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#security), [Network Reachability](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#network-reachability)
|
||||
|
@ -37,7 +35,7 @@ Alamofire is an HTTP networking library written in Swift.
|
|||
## Features
|
||||
|
||||
- [x] Chainable Request / Response Methods
|
||||
- [x] URL / JSON / plist Parameter Encoding
|
||||
- [x] URL / JSON Parameter Encoding
|
||||
- [x] Upload File / Data / Stream / MultipartFormData
|
||||
- [x] Download File using Request or Resume Data
|
||||
- [x] Authentication with URLCredential
|
||||
|
@ -65,7 +63,7 @@ In order to keep Alamofire focused specifically on core networking implementatio
|
|||
|
||||
## Migration Guides
|
||||
|
||||
- Alamofire 5.0 Migration Guide: To be written!
|
||||
- [Alamofire 5.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%205.0%20Migration%20Guide.md)
|
||||
- [Alamofire 4.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%204.0%20Migration%20Guide.md)
|
||||
- [Alamofire 3.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%203.0%20Migration%20Guide.md)
|
||||
- [Alamofire 2.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%202.0%20Migration%20Guide.md)
|
||||
|
@ -77,7 +75,7 @@ In order to keep Alamofire focused specifically on core networking implementatio
|
|||
- If you'd like to **discuss Alamofire best practices**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
|
||||
- If you'd like to **discuss a feature request**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
|
||||
- If you **found a bug**, open an issue here on GitHub and follow the guide. The more detail the better!
|
||||
- If you **want to contribute**, submit a pull request.
|
||||
- If you **want to contribute**, submit a pull request!
|
||||
|
||||
## Installation
|
||||
|
||||
|
@ -86,7 +84,7 @@ In order to keep Alamofire focused specifically on core networking implementatio
|
|||
[CocoaPods](https://cocoapods.org) is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate Alamofire into your Xcode project using CocoaPods, specify it in your `Podfile`:
|
||||
|
||||
```ruby
|
||||
pod 'Alamofire', '~> 5.0.0-rc.3'
|
||||
pod 'Alamofire', '~> 5.0'
|
||||
```
|
||||
|
||||
### Carthage
|
||||
|
@ -94,7 +92,7 @@ pod 'Alamofire', '~> 5.0.0-rc.3'
|
|||
[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate Alamofire into your Xcode project using Carthage, specify it in your `Cartfile`:
|
||||
|
||||
```ogdl
|
||||
github "Alamofire/Alamofire" "5.0.0-rc.3"
|
||||
github "Alamofire/Alamofire" "5.0"
|
||||
```
|
||||
|
||||
### Swift Package Manager
|
||||
|
@ -105,7 +103,7 @@ Once you have your Swift package set up, adding Alamofire as a dependency is as
|
|||
|
||||
```swift
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.0.0-rc.3")
|
||||
.package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.0")
|
||||
]
|
||||
```
|
||||
|
||||
|
@ -181,7 +179,7 @@ If you believe you have identified a security vulnerability with Alamofire, you
|
|||
## Donations
|
||||
|
||||
The [ASF](https://github.com/Alamofire/Foundation#members) is looking to raise money to officially stay registered as a federal non-profit organization.
|
||||
Registering will allow us members to gain some legal protections and also allow us to put donations to use, tax free.
|
||||
Registering will allow us members to gain some legal protections and also allow us to put donations to use, tax-free.
|
||||
Donating to the ASF will enable us to:
|
||||
|
||||
- Pay our yearly legal fees to keep the non-profit in good status
|
||||
|
@ -190,7 +188,7 @@ Donating to the ASF will enable us to:
|
|||
- Potentially fund developers to work on one of our projects full-time
|
||||
|
||||
The community adoption of the ASF libraries has been amazing.
|
||||
We are greatly humbled by your enthusiasm around the projects, and want to continue to do everything we can to move the needle forward.
|
||||
We are greatly humbled by your enthusiasm around the projects and want to continue to do everything we can to move the needle forward.
|
||||
With your continued support, the ASF will be able to improve its reach and also provide better legal safety for the core members.
|
||||
If you use any of our libraries for work, see if your employers would be interested in donating.
|
||||
Any amount you can donate today to help us reach our goal would be greatly appreciated.
|
||||
|
|
|
@ -22,499 +22,8 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
/// Reference to `Session.default` for quick bootstrapping and examples.
|
||||
public let AF = Session.default
|
||||
|
||||
/// Global namespace containing API for the `default` `Session` instance.
|
||||
public enum AF {
|
||||
/// Current Alamofire version. Necessary since SPM doesn't use dynamic libraries. Plus this will be more accurate.
|
||||
static let version = "5.0.0-rc.3"
|
||||
|
||||
// MARK: - Data Request
|
||||
|
||||
/// Creates a `DataRequest` using `Session.default` to retrieve the contents of the specified `url` using the
|
||||
/// `method`, `parameters`, `encoding`, and `headers` provided.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - url: The `URLConvertible` value.
|
||||
/// - method: The `HTTPMethod`, `.get` by default.
|
||||
/// - parameters: The `Parameters`, `nil` by default.
|
||||
/// - encoding: The `ParameterEncoding`, `URLEncoding.default` by default.
|
||||
/// - headers: The `HTTPHeaders`, `nil` by default.
|
||||
/// - interceptor: The `RequestInterceptor`, `nil` by default.
|
||||
///
|
||||
/// - Returns: The created `DataRequest`.
|
||||
public static func request(_ url: URLConvertible,
|
||||
method: HTTPMethod = .get,
|
||||
parameters: Parameters? = nil,
|
||||
encoding: ParameterEncoding = URLEncoding.default,
|
||||
headers: HTTPHeaders? = nil,
|
||||
interceptor: RequestInterceptor? = nil) -> DataRequest {
|
||||
return Session.default.request(url,
|
||||
method: method,
|
||||
parameters: parameters,
|
||||
encoding: encoding,
|
||||
headers: headers,
|
||||
interceptor: interceptor)
|
||||
}
|
||||
|
||||
/// Creates a `DataRequest` using `Session.default` to retrieve the contents of the specified `url` using the
|
||||
/// `method`, `parameters`, `encoding`, and `headers` provided.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - url: The `URLConvertible` value.
|
||||
/// - method: The `HTTPMethod`, `.get` by default.
|
||||
/// - parameters: The `Encodable` parameters, `nil` by default.
|
||||
/// - encoding: The `ParameterEncoder`, `URLEncodedFormParameterEncoder.default` by default.
|
||||
/// - headers: The `HTTPHeaders`, `nil` by default.
|
||||
/// - interceptor: The `RequestInterceptor`, `nil` by default.
|
||||
///
|
||||
/// - Returns: The created `DataRequest`.
|
||||
public static func request<Parameters: Encodable>(_ url: URLConvertible,
|
||||
method: HTTPMethod = .get,
|
||||
parameters: Parameters? = nil,
|
||||
encoder: ParameterEncoder = URLEncodedFormParameterEncoder.default,
|
||||
headers: HTTPHeaders? = nil,
|
||||
interceptor: RequestInterceptor? = nil) -> DataRequest {
|
||||
return Session.default.request(url,
|
||||
method: method,
|
||||
parameters: parameters,
|
||||
encoder: encoder,
|
||||
headers: headers,
|
||||
interceptor: interceptor)
|
||||
}
|
||||
|
||||
/// Creates a `DataRequest` using `Session.default` to execute the specified `urlRequest`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - urlRequest: The `URLRequestConvertible` value.
|
||||
/// - interceptor: The `RequestInterceptor`, `nil` by default.
|
||||
///
|
||||
/// - Returns: The created `DataRequest`.
|
||||
public static func request(_ urlRequest: URLRequestConvertible, interceptor: RequestInterceptor? = nil) -> DataRequest {
|
||||
return Session.default.request(urlRequest, interceptor: interceptor)
|
||||
}
|
||||
|
||||
// MARK: - Download Request
|
||||
|
||||
/// Creates a `DownloadRequest` using `Session.default` to download the contents of the specified `url` to
|
||||
/// the provided `destination` using the `method`, `parameters`, `encoding`, and `headers` provided.
|
||||
///
|
||||
/// If `destination` is not specified, the download will be moved to a temporary location determined by Alamofire.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - url: The `URLConvertible` value.
|
||||
/// - method: The `HTTPMethod`, `.get` by default.
|
||||
/// - parameters: The `Parameters`, `nil` by default.
|
||||
/// - encoding: The `ParameterEncoding`, `URLEncoding.default` by default.
|
||||
/// - headers: The `HTTPHeaders`, `nil` by default.
|
||||
/// - interceptor: The `RequestInterceptor`, `nil` by default.
|
||||
/// - destination: The `DownloadRequest.Destination` closure used the determine the destination of the
|
||||
/// downloaded file. `nil` by default.
|
||||
///
|
||||
/// - Returns: The created `DownloadRequest`.
|
||||
public static func download(_ url: URLConvertible,
|
||||
method: HTTPMethod = .get,
|
||||
parameters: Parameters? = nil,
|
||||
encoding: ParameterEncoding = URLEncoding.default,
|
||||
headers: HTTPHeaders? = nil,
|
||||
interceptor: RequestInterceptor? = nil,
|
||||
to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
|
||||
return Session.default.download(url,
|
||||
method: method,
|
||||
parameters: parameters,
|
||||
encoding: encoding,
|
||||
headers: headers,
|
||||
interceptor: interceptor,
|
||||
to: destination)
|
||||
}
|
||||
|
||||
/// Creates a `DownloadRequest` using `Session.default` to download the contents of the specified `url` to the
|
||||
/// provided `destination` using the `method`, encodable `parameters`, `encoder`, and `headers` provided.
|
||||
///
|
||||
/// - Note: If `destination` is not specified, the download will be moved to a temporary location determined by
|
||||
/// Alamofire.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - url: The `URLConvertible` value.
|
||||
/// - method: The `HTTPMethod`, `.get` by default.
|
||||
/// - parameters: The `Encodable` parameters, `nil` by default.
|
||||
/// - encoder: The `ParameterEncoder`, `URLEncodedFormParameterEncoder.default` by default.
|
||||
/// - headers: The `HTTPHeaders`, `nil` by default.
|
||||
/// - interceptor: The `RequestInterceptor`, `nil` by default.
|
||||
/// - destination: The `DownloadRequest.Destination` closure used the determine the destination of the
|
||||
/// downloaded file. `nil` by default.
|
||||
///
|
||||
/// - Returns: The created `DownloadRequest`.
|
||||
public static func download<Parameters: Encodable>(_ url: URLConvertible,
|
||||
method: HTTPMethod = .get,
|
||||
parameters: Parameters? = nil,
|
||||
encoder: ParameterEncoder = URLEncodedFormParameterEncoder.default,
|
||||
headers: HTTPHeaders? = nil,
|
||||
interceptor: RequestInterceptor? = nil,
|
||||
to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
|
||||
return Session.default.download(url,
|
||||
method: method,
|
||||
parameters: parameters,
|
||||
encoder: encoder,
|
||||
headers: headers,
|
||||
interceptor: interceptor,
|
||||
to: destination)
|
||||
}
|
||||
|
||||
// MARK: URLRequest
|
||||
|
||||
/// Creates a `DownloadRequest` using `Session.default` to execute the specified `urlRequest` and download
|
||||
/// the result to the provided `destination`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - urlRequest: The `URLRequestConvertible` value.
|
||||
/// - interceptor: The `RequestInterceptor`, `nil` by default.
|
||||
/// - destination: The `DownloadRequest.Destination` closure used the determine the destination of the
|
||||
/// downloaded file. `nil` by default.
|
||||
///
|
||||
/// - Returns: The created `DownloadRequest`.
|
||||
public static func download(_ urlRequest: URLRequestConvertible,
|
||||
interceptor: RequestInterceptor? = nil,
|
||||
to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
|
||||
return Session.default.download(urlRequest, interceptor: interceptor, to: destination)
|
||||
}
|
||||
|
||||
// MARK: Resume Data
|
||||
|
||||
/// Creates a `DownloadRequest` using the `Session.default` from the `resumeData` produced from a previous
|
||||
/// `DownloadRequest` cancellation to retrieve the contents of the original request and save them to the `destination`.
|
||||
///
|
||||
/// - Note: If `destination` is not specified, the download will be moved to a temporary location determined by
|
||||
/// Alamofire.
|
||||
///
|
||||
/// - Note: On some versions of all Apple platforms (iOS 10 - 10.2, macOS 10.12 - 10.12.2, tvOS 10 - 10.1, watchOS 3 - 3.1.1),
|
||||
/// `resumeData` is broken on background URL session configurations. There's an underlying bug in the `resumeData`
|
||||
/// generation logic where the data is written incorrectly and will always fail to resume the download. For more
|
||||
/// information about the bug and possible workarounds, please refer to the [this Stack Overflow post](http://stackoverflow.com/a/39347461/1342462).
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - resumeData: The resume `Data`. This is an opaque blob produced by `URLSessionDownloadTask` when a task is
|
||||
/// cancelled. See [Apple's documentation](https://developer.apple.com/documentation/foundation/urlsessiondownloadtask/1411634-cancel)
|
||||
/// for more information.
|
||||
/// - interceptor: The `RequestInterceptor`, `nil` by default.
|
||||
/// - destination: The `DownloadRequest.Destination` closure used to determine the destination of the downloaded
|
||||
/// file. `nil` by default.
|
||||
///
|
||||
/// - Returns: The created `DownloadRequest`.
|
||||
public static func download(resumingWith resumeData: Data,
|
||||
interceptor: RequestInterceptor? = nil,
|
||||
to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
|
||||
return Session.default.download(resumingWith: resumeData, interceptor: interceptor, to: destination)
|
||||
}
|
||||
|
||||
// MARK: - Upload Request
|
||||
|
||||
// MARK: Data
|
||||
|
||||
/// Creates an `UploadRequest` for the given `Data`, `URLRequest` components, and `RequestInterceptor`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - data: The `Data` to upload.
|
||||
/// - convertible: `URLConvertible` value to be used as the `URLRequest`'s `URL`.
|
||||
/// - method: `HTTPMethod` for the `URLRequest`. `.post` by default.
|
||||
/// - headers: `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
|
||||
/// - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
|
||||
/// - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
|
||||
/// default.
|
||||
///
|
||||
/// - Returns: The created `UploadRequest`.
|
||||
public static func upload(_ data: Data,
|
||||
to convertible: URLConvertible,
|
||||
method: HTTPMethod = .post,
|
||||
headers: HTTPHeaders? = nil,
|
||||
interceptor: RequestInterceptor? = nil,
|
||||
fileManager: FileManager = .default) -> UploadRequest {
|
||||
return Session.default.upload(data,
|
||||
to: convertible,
|
||||
method: method,
|
||||
headers: headers,
|
||||
interceptor: interceptor,
|
||||
fileManager: fileManager)
|
||||
}
|
||||
|
||||
/// Creates an `UploadRequest` for the given `Data` using the `URLRequestConvertible` value and `RequestInterceptor`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - data: The `Data` to upload.
|
||||
/// - convertible: `URLRequestConvertible` value to be used to create the `URLRequest`.
|
||||
/// - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
|
||||
/// - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
|
||||
/// default.
|
||||
///
|
||||
/// - Returns: The created `UploadRequest`.
|
||||
public static func upload(_ data: Data,
|
||||
with convertible: URLRequestConvertible,
|
||||
interceptor: RequestInterceptor? = nil,
|
||||
fileManager: FileManager = .default) -> UploadRequest {
|
||||
return Session.default.upload(data, with: convertible, interceptor: interceptor, fileManager: fileManager)
|
||||
}
|
||||
|
||||
// MARK: File
|
||||
|
||||
/// Creates an `UploadRequest` for the file at the given file `URL`, using a `URLRequest` from the provided
|
||||
/// components and `RequestInterceptor`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - fileURL: The `URL` of the file to upload.
|
||||
/// - convertible: `URLConvertible` value to be used as the `URLRequest`'s `URL`.
|
||||
/// - method: `HTTPMethod` for the `URLRequest`. `.post` by default.
|
||||
/// - headers: `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
|
||||
/// - interceptor: `RequestInterceptor` value to be used by the returned `UploadRequest`. `nil` by default.
|
||||
/// - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
|
||||
/// default.
|
||||
///
|
||||
/// - Returns: The created `UploadRequest`.
|
||||
public static func upload(_ fileURL: URL,
|
||||
to convertible: URLConvertible,
|
||||
method: HTTPMethod = .post,
|
||||
headers: HTTPHeaders? = nil,
|
||||
interceptor: RequestInterceptor? = nil,
|
||||
fileManager: FileManager = .default) -> UploadRequest {
|
||||
return Session.default.upload(fileURL,
|
||||
to: convertible,
|
||||
method: method,
|
||||
headers: headers,
|
||||
interceptor: interceptor,
|
||||
fileManager: fileManager)
|
||||
}
|
||||
|
||||
/// Creates an `UploadRequest` for the file at the given file `URL` using the `URLRequestConvertible` value and
|
||||
/// `RequestInterceptor`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - fileURL: The `URL` of the file to upload.
|
||||
/// - convertible: `URLRequestConvertible` value to be used to create the `URLRequest`.
|
||||
/// - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
|
||||
/// - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
|
||||
/// default.
|
||||
///
|
||||
/// - Returns: The created `UploadRequest`.
|
||||
public static func upload(_ fileURL: URL,
|
||||
with convertible: URLRequestConvertible,
|
||||
interceptor: RequestInterceptor? = nil,
|
||||
fileManager: FileManager = .default) -> UploadRequest {
|
||||
return Session.default.upload(fileURL, with: convertible, interceptor: interceptor, fileManager: fileManager)
|
||||
}
|
||||
|
||||
// MARK: InputStream
|
||||
|
||||
/// Creates an `UploadRequest` from the `InputStream` provided using a `URLRequest` from the provided components and
|
||||
/// `RequestInterceptor`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - stream: The `InputStream` that provides the data to upload.
|
||||
/// - convertible: `URLConvertible` value to be used as the `URLRequest`'s `URL`.
|
||||
/// - method: `HTTPMethod` for the `URLRequest`. `.post` by default.
|
||||
/// - headers: `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
|
||||
/// - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
|
||||
/// - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
|
||||
/// default.
|
||||
///
|
||||
/// - Returns: The created `UploadRequest`.
|
||||
public static func upload(_ stream: InputStream,
|
||||
to convertible: URLConvertible,
|
||||
method: HTTPMethod = .post,
|
||||
headers: HTTPHeaders? = nil,
|
||||
interceptor: RequestInterceptor? = nil,
|
||||
fileManager: FileManager = .default) -> UploadRequest {
|
||||
return Session.default.upload(stream,
|
||||
to: convertible,
|
||||
method: method,
|
||||
headers: headers,
|
||||
interceptor: interceptor,
|
||||
fileManager: fileManager)
|
||||
}
|
||||
|
||||
/// Creates an `UploadRequest` from the provided `InputStream` using the `URLRequestConvertible` value and
|
||||
/// `RequestInterceptor`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - stream: The `InputStream` that provides the data to upload.
|
||||
/// - convertible: `URLRequestConvertible` value to be used to create the `URLRequest`.
|
||||
/// - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
|
||||
/// - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
|
||||
/// default.
|
||||
///
|
||||
/// - Returns: The created `UploadRequest`.
|
||||
public static func upload(_ stream: InputStream,
|
||||
with convertible: URLRequestConvertible,
|
||||
interceptor: RequestInterceptor? = nil,
|
||||
fileManager: FileManager = .default) -> UploadRequest {
|
||||
return Session.default.upload(stream, with: convertible, interceptor: interceptor, fileManager: fileManager)
|
||||
}
|
||||
|
||||
// MARK: MultipartFormData
|
||||
|
||||
/// Creates an `UploadRequest` for the multipart form data built using a closure and sent using the provided
|
||||
/// `URLRequest` components and `RequestInterceptor`.
|
||||
///
|
||||
/// It is important to understand the memory implications of uploading `MultipartFormData`. If the cumulative
|
||||
/// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
|
||||
/// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
|
||||
/// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
|
||||
/// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
|
||||
/// used for larger payloads such as video content.
|
||||
///
|
||||
/// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
|
||||
/// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
|
||||
/// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
|
||||
/// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
|
||||
/// technique was used.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - multipartFormData: `MultipartFormData` building closure.
|
||||
/// - convertible: `URLConvertible` value to be used as the `URLRequest`'s `URL`.
|
||||
/// - encodingMemoryThreshold: Byte threshold used to determine whether the form data is encoded into memory or
|
||||
/// onto disk before being uploaded. `MultipartFormData.encodingMemoryThreshold` by
|
||||
/// default.
|
||||
/// - method: `HTTPMethod` for the `URLRequest`. `.post` by default.
|
||||
/// - headers: `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
|
||||
/// - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
|
||||
/// - fileManager: `FileManager` to be used if the form data exceeds the memory threshold and is
|
||||
/// written to disk before being uploaded. `.default` instance by default.
|
||||
///
|
||||
/// - Returns: The created `UploadRequest`.
|
||||
public static func upload(multipartFormData: @escaping (MultipartFormData) -> Void,
|
||||
to url: URLConvertible,
|
||||
usingThreshold encodingMemoryThreshold: UInt64 = MultipartFormData.encodingMemoryThreshold,
|
||||
method: HTTPMethod = .post,
|
||||
headers: HTTPHeaders? = nil,
|
||||
interceptor: RequestInterceptor? = nil,
|
||||
fileManager: FileManager = .default) -> UploadRequest {
|
||||
return Session.default.upload(multipartFormData: multipartFormData,
|
||||
to: url,
|
||||
usingThreshold: encodingMemoryThreshold,
|
||||
method: method,
|
||||
headers: headers,
|
||||
interceptor: interceptor,
|
||||
fileManager: fileManager)
|
||||
}
|
||||
|
||||
/// Creates an `UploadRequest` using a `MultipartFormData` building closure, the provided `URLRequestConvertible`
|
||||
/// value, and a `RequestInterceptor`.
|
||||
///
|
||||
/// It is important to understand the memory implications of uploading `MultipartFormData`. If the cumulative
|
||||
/// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
|
||||
/// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
|
||||
/// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
|
||||
/// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
|
||||
/// used for larger payloads such as video content.
|
||||
///
|
||||
/// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
|
||||
/// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
|
||||
/// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
|
||||
/// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
|
||||
/// technique was used.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - multipartFormData: `MultipartFormData` building closure.
|
||||
/// - request: `URLRequestConvertible` value to be used to create the `URLRequest`.
|
||||
/// - encodingMemoryThreshold: Byte threshold used to determine whether the form data is encoded into memory or
|
||||
/// onto disk before being uploaded. `MultipartFormData.encodingMemoryThreshold` by
|
||||
/// default.
|
||||
/// - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
|
||||
/// - fileManager: `FileManager` to be used if the form data exceeds the memory threshold and is
|
||||
/// written to disk before being uploaded. `.default` instance by default.
|
||||
///
|
||||
/// - Returns: The created `UploadRequest`.
|
||||
public static func upload(multipartFormData: @escaping (MultipartFormData) -> Void,
|
||||
with request: URLRequestConvertible,
|
||||
usingThreshold encodingMemoryThreshold: UInt64 = MultipartFormData.encodingMemoryThreshold,
|
||||
interceptor: RequestInterceptor? = nil,
|
||||
fileManager: FileManager = .default) -> UploadRequest {
|
||||
return Session.default.upload(multipartFormData: multipartFormData,
|
||||
with: request,
|
||||
usingThreshold: encodingMemoryThreshold,
|
||||
interceptor: interceptor,
|
||||
fileManager: fileManager)
|
||||
}
|
||||
|
||||
/// Creates an `UploadRequest` for the prebuilt `MultipartFormData` value using the provided `URLRequest` components
|
||||
/// and `RequestInterceptor`.
|
||||
///
|
||||
/// It is important to understand the memory implications of uploading `MultipartFormData`. If the cumulative
|
||||
/// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
|
||||
/// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
|
||||
/// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
|
||||
/// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
|
||||
/// used for larger payloads such as video content.
|
||||
///
|
||||
/// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
|
||||
/// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
|
||||
/// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
|
||||
/// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
|
||||
/// technique was used.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - multipartFormData: `MultipartFormData` instance to upload.
|
||||
/// - url: `URLConvertible` value to be used as the `URLRequest`'s `URL`.
|
||||
/// - encodingMemoryThreshold: Byte threshold used to determine whether the form data is encoded into memory or
|
||||
/// onto disk before being uploaded. `MultipartFormData.encodingMemoryThreshold` by
|
||||
/// default.
|
||||
/// - method: `HTTPMethod` for the `URLRequest`. `.post` by default.
|
||||
/// - headers: `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
|
||||
/// - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
|
||||
/// - fileManager: `FileManager` to be used if the form data exceeds the memory threshold and is
|
||||
/// written to disk before being uploaded. `.default` instance by default.
|
||||
///
|
||||
/// - Returns: The created `UploadRequest`.
|
||||
public static func upload(multipartFormData: MultipartFormData,
|
||||
to url: URLConvertible,
|
||||
usingThreshold encodingMemoryThreshold: UInt64 = MultipartFormData.encodingMemoryThreshold,
|
||||
method: HTTPMethod = .post,
|
||||
headers: HTTPHeaders? = nil,
|
||||
interceptor: RequestInterceptor? = nil,
|
||||
fileManager: FileManager = .default) -> UploadRequest {
|
||||
return Session.default.upload(multipartFormData: multipartFormData,
|
||||
to: url,
|
||||
usingThreshold: encodingMemoryThreshold,
|
||||
method: method,
|
||||
headers: headers,
|
||||
interceptor: interceptor,
|
||||
fileManager: fileManager)
|
||||
}
|
||||
|
||||
/// Creates an `UploadRequest` for the prebuilt `MultipartFormData` value using the providing `URLRequestConvertible`
|
||||
/// value and `RequestInterceptor`.
|
||||
///
|
||||
/// It is important to understand the memory implications of uploading `MultipartFormData`. If the cumulative
|
||||
/// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
|
||||
/// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
|
||||
/// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
|
||||
/// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
|
||||
/// used for larger payloads such as video content.
|
||||
///
|
||||
/// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
|
||||
/// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
|
||||
/// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
|
||||
/// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
|
||||
/// technique was used.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - multipartFormData: `MultipartFormData` instance to upload.
|
||||
/// - request: `URLRequestConvertible` value to be used to create the `URLRequest`.
|
||||
/// - encodingMemoryThreshold: Byte threshold used to determine whether the form data is encoded into memory or
|
||||
/// onto disk before being uploaded. `MultipartFormData.encodingMemoryThreshold` by
|
||||
/// default.
|
||||
/// - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
|
||||
/// - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
|
||||
/// default.
|
||||
///
|
||||
/// - Returns: The created `UploadRequest`.
|
||||
public static func upload(multipartFormData: MultipartFormData,
|
||||
with request: URLRequestConvertible,
|
||||
usingThreshold encodingMemoryThreshold: UInt64 = MultipartFormData.encodingMemoryThreshold,
|
||||
interceptor: RequestInterceptor? = nil,
|
||||
fileManager: FileManager = .default) -> UploadRequest {
|
||||
return Session.default.upload(multipartFormData: multipartFormData,
|
||||
with: request,
|
||||
usingThreshold: encodingMemoryThreshold,
|
||||
interceptor: interceptor,
|
||||
fileManager: fileManager)
|
||||
}
|
||||
}
|
||||
/// Current Alamofire version. Necessary since SPM doesn't use dynamic libraries. Plus this will be more accurate.
|
||||
let version = "5.0.2"
|
||||
|
|
|
@ -24,10 +24,13 @@
|
|||
|
||||
/// Type that acts as a generic extension point for all `AlamofireExtended` types.
|
||||
public struct AlamofireExtension<ExtendedType> {
|
||||
/// Stores the type or metatype of any extended type.
|
||||
let type: ExtendedType
|
||||
/// Stores the type or meta-type of any extended type.
|
||||
public private(set) var type: ExtendedType
|
||||
|
||||
init(_ type: ExtendedType) {
|
||||
/// Create an instance from the provided value.
|
||||
///
|
||||
/// - Parameter type: Instance being extended.
|
||||
public init(_ type: ExtendedType) {
|
||||
self.type = type
|
||||
}
|
||||
}
|
||||
|
|
|
@ -398,7 +398,7 @@ extension HTTPHeader {
|
|||
return "\(osName) \(versionString)"
|
||||
}()
|
||||
|
||||
let alamofireVersion = "Alamofire/\(AF.version)"
|
||||
let alamofireVersion = "Alamofire/\(version)"
|
||||
|
||||
return "\(executable)/\(appVersion) (\(bundle); build:\(appBuild); \(osNameVersion)) \(alamofireVersion)"
|
||||
}
|
||||
|
|
|
@ -240,11 +240,11 @@ extension SCNetworkReachabilityFlags {
|
|||
var canConnectWithoutUserInteraction: Bool { return canConnectAutomatically && !contains(.interventionRequired) }
|
||||
var isActuallyReachable: Bool { return isReachable && (!isConnectionRequired || canConnectWithoutUserInteraction) }
|
||||
var isCellular: Bool {
|
||||
#if os(iOS) || os(tvOS)
|
||||
#if os(iOS) || os(tvOS)
|
||||
return contains(.isWWAN)
|
||||
#else
|
||||
#else
|
||||
return false
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Human readable `String` for all states, to help with debugging.
|
||||
|
|
|
@ -35,10 +35,10 @@ public protocol RedirectHandler {
|
|||
/// 3. A `nil` value to deny the redirect request and return the body of the redirect response.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - task: The task whose request resulted in a redirect.
|
||||
/// - request: The URL request object to the new location specified by the redirect response.
|
||||
/// - response: The response containing the server's response to the original request.
|
||||
/// - completion: The closure to execute containing the new request, a modified request, or `nil`.
|
||||
/// - task: The `URLSessionTask` whose request resulted in a redirect.
|
||||
/// - request: The `URLRequest` to the new location specified by the redirect response.
|
||||
/// - response: The `HTTPURLResponse` containing the server's response to the original request.
|
||||
/// - completion: The closure to execute containing the new `URLRequest`, a modified `URLRequest`, or `nil`.
|
||||
func task(_ task: URLSessionTask,
|
||||
willBeRedirectedTo request: URLRequest,
|
||||
for response: HTTPURLResponse,
|
||||
|
|
|
@ -1045,7 +1045,6 @@ public class DownloadRequest: Request {
|
|||
/// Specifies that any previous file at the destination `URL` should be removed.
|
||||
public static let removePreviousFile = Options(rawValue: 1 << 1)
|
||||
|
||||
/// Returns the raw bitmask value of the option and satisfies the `RawRepresentable` protocol.
|
||||
public let rawValue: Int
|
||||
|
||||
public init(rawValue: Int) {
|
||||
|
@ -1055,15 +1054,13 @@ public class DownloadRequest: Request {
|
|||
|
||||
// MARK: Destination
|
||||
|
||||
/// A closure executed once a download request has successfully completed in order to determine where to move the
|
||||
/// A closure executed once a `DownloadRequest` has successfully completed in order to determine where to move the
|
||||
/// temporary file written to during the download process. The closure takes two arguments: the temporary file URL
|
||||
/// and the URL response, and returns a two arguments: the file URL where the temporary file should be moved and
|
||||
/// the options defining how the file should be moved.
|
||||
public typealias Destination = (_ temporaryURL: URL,
|
||||
_ response: HTTPURLResponse) -> (destinationURL: URL, options: Options)
|
||||
|
||||
// MARK: Destination
|
||||
|
||||
/// Creates a download file destination closure which uses the default file manager to move the temporary file to a
|
||||
/// file URL in the first available directory with the specified search path directory and search path domain mask.
|
||||
///
|
||||
|
@ -1095,6 +1092,8 @@ public class DownloadRequest: Request {
|
|||
return (destination, [])
|
||||
}
|
||||
|
||||
// MARK: Downloadable
|
||||
|
||||
/// Type describing the source used to create the underlying `URLSessionDownloadTask`.
|
||||
public enum Downloadable {
|
||||
/// Download should be started from the `URLRequest` produced by the associated `URLRequestConvertible` value.
|
||||
|
|
|
@ -45,7 +45,7 @@ public enum RetryResult {
|
|||
case retryWithDelay(TimeInterval)
|
||||
/// Do not retry.
|
||||
case doNotRetry
|
||||
/// Do not retry due to the associated `AFError`.
|
||||
/// Do not retry due to the associated `Error`.
|
||||
case doNotRetryWithError(Error)
|
||||
}
|
||||
|
||||
|
|
|
@ -323,14 +323,14 @@ extension DownloadRequest {
|
|||
///
|
||||
/// - Returns: The request.
|
||||
@discardableResult
|
||||
public func response<T: DownloadResponseSerializerProtocol>(queue: DispatchQueue = .main,
|
||||
responseSerializer: T,
|
||||
completionHandler: @escaping (AFDownloadResponse<T.SerializedObject>) -> Void)
|
||||
public func response<Serializer: DownloadResponseSerializerProtocol>(queue: DispatchQueue = .main,
|
||||
responseSerializer: Serializer,
|
||||
completionHandler: @escaping (AFDownloadResponse<Serializer.SerializedObject>) -> Void)
|
||||
-> Self {
|
||||
appendResponseSerializer {
|
||||
// Start work that should be on the serialization queue.
|
||||
let start = CFAbsoluteTimeGetCurrent()
|
||||
let result: AFResult<T.SerializedObject> = Result {
|
||||
let result: AFResult<Serializer.SerializedObject> = Result {
|
||||
try responseSerializer.serializeDownload(request: self.request,
|
||||
response: self.response,
|
||||
fileURL: self.fileURL,
|
||||
|
@ -371,7 +371,7 @@ extension DownloadRequest {
|
|||
didComplete = { completionHandler(response) }
|
||||
|
||||
case let .doNotRetryWithError(retryError):
|
||||
let result: AFResult<T.SerializedObject> = .failure(retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
|
||||
let result: AFResult<Serializer.SerializedObject> = .failure(retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
|
||||
|
||||
let response = DownloadResponse(request: self.request,
|
||||
response: self.response,
|
||||
|
@ -777,3 +777,24 @@ extension DataRequest {
|
|||
completionHandler: completionHandler)
|
||||
}
|
||||
}
|
||||
|
||||
extension DownloadRequest {
|
||||
/// Adds a handler to be called once the request has finished.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - type: `Decodable` type to decode from response data.
|
||||
/// - queue: The queue on which the completion handler is dispatched. `.main` by default.
|
||||
/// - decoder: `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
|
||||
/// - completionHandler: A closure to be executed once the request has finished.
|
||||
///
|
||||
/// - Returns: The request.
|
||||
@discardableResult
|
||||
public func responseDecodable<T: Decodable>(of type: T.Type = T.self,
|
||||
queue: DispatchQueue = .main,
|
||||
decoder: DataDecoder = JSONDecoder(),
|
||||
completionHandler: @escaping (AFDownloadResponse<T>) -> Void) -> Self {
|
||||
return response(queue: queue,
|
||||
responseSerializer: DecodableResponseSerializer(decoder: decoder),
|
||||
completionHandler: completionHandler)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,9 +73,9 @@ open class ServerTrustManager {
|
|||
|
||||
/// A protocol describing the API used to evaluate server trusts.
|
||||
public protocol ServerTrustEvaluating {
|
||||
#if os(Linux)
|
||||
// Implement this once Linux has API for evaluating server trusts.
|
||||
#else
|
||||
#if os(Linux)
|
||||
// Implement this once Linux has API for evaluating server trusts.
|
||||
#else
|
||||
/// Evaluates the given `SecTrust` value for the given `host`.
|
||||
///
|
||||
/// - Parameters:
|
||||
|
@ -84,7 +84,7 @@ public protocol ServerTrustEvaluating {
|
|||
///
|
||||
/// - Returns: A `Bool` indicating whether the evaluator considers the `SecTrust` value valid for `host`.
|
||||
func evaluate(_ trust: SecTrust, forHost host: String) throws
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
// MARK: - Server Trust Evaluators
|
||||
|
@ -345,9 +345,9 @@ public final class DisabledEvaluator: ServerTrustEvaluating {
|
|||
// MARK: - Extensions
|
||||
|
||||
public extension Array where Element == ServerTrustEvaluating {
|
||||
#if os(Linux)
|
||||
// Add this same convenience method for Linux.
|
||||
#else
|
||||
#if os(Linux)
|
||||
// Add this same convenience method for Linux.
|
||||
#else
|
||||
/// Evaluates the given `SecTrust` value for the given `host`.
|
||||
///
|
||||
/// - Parameters:
|
||||
|
@ -360,7 +360,7 @@ public extension Array where Element == ServerTrustEvaluating {
|
|||
try evaluator.evaluate(trust, forHost: host)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
extension Bundle: AlamofireExtended {}
|
||||
|
|
|
@ -38,6 +38,24 @@ open class SessionDelegate: NSObject {
|
|||
public init(fileManager: FileManager = .default) {
|
||||
self.fileManager = fileManager
|
||||
}
|
||||
|
||||
/// Internal method to find and cast requests while maintaining some integrity checking.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - task: The `URLSessionTask` for which to find the associated `Request`.
|
||||
/// - type: The `Request` subclass type to cast any `Request` associate with `task`.
|
||||
func request<R: Request>(for task: URLSessionTask, as type: R.Type) -> R? {
|
||||
guard let provider = stateProvider else {
|
||||
assertionFailure("StateProvider is nil.")
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let request = provider.request(for: task) as? R else {
|
||||
fatalError("Returned Request is not of expected type: \(R.self).")
|
||||
}
|
||||
|
||||
return request
|
||||
}
|
||||
}
|
||||
|
||||
/// Type which provides various `Session` state values.
|
||||
|
@ -79,10 +97,9 @@ extension SessionDelegate: URLSessionTaskDelegate {
|
|||
switch challenge.protectionSpace.authenticationMethod {
|
||||
case NSURLAuthenticationMethodServerTrust:
|
||||
evaluation = attemptServerTrustAuthentication(with: challenge)
|
||||
case NSURLAuthenticationMethodHTTPBasic, NSURLAuthenticationMethodHTTPDigest, NSURLAuthenticationMethodNTLM, NSURLAuthenticationMethodNegotiate:
|
||||
case NSURLAuthenticationMethodHTTPBasic, NSURLAuthenticationMethodHTTPDigest, NSURLAuthenticationMethodNTLM,
|
||||
NSURLAuthenticationMethodNegotiate, NSURLAuthenticationMethodClientCertificate:
|
||||
evaluation = attemptCredentialAuthentication(for: challenge, belongingTo: task)
|
||||
// case NSURLAuthenticationMethodClientCertificate:
|
||||
// Alamofire doesn't currently support client certificate validation.
|
||||
default:
|
||||
evaluation = (.performDefaultHandling, nil, nil)
|
||||
}
|
||||
|
@ -161,8 +178,10 @@ extension SessionDelegate: URLSessionTaskDelegate {
|
|||
needNewBodyStream completionHandler: @escaping (InputStream?) -> Void) {
|
||||
eventMonitor?.urlSession(session, taskNeedsNewBodyStream: task)
|
||||
|
||||
guard let request = stateProvider?.request(for: task) as? UploadRequest else {
|
||||
fatalError("needNewBodyStream for request that isn't UploadRequest.")
|
||||
guard let request = request(for: task, as: UploadRequest.self) else {
|
||||
assertionFailure("needNewBodyStream did not find UploadRequest.")
|
||||
completionHandler(nil)
|
||||
return
|
||||
}
|
||||
|
||||
completionHandler(request.inputStream())
|
||||
|
@ -210,8 +229,9 @@ extension SessionDelegate: URLSessionDataDelegate {
|
|||
open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
|
||||
eventMonitor?.urlSession(session, dataTask: dataTask, didReceive: data)
|
||||
|
||||
guard let request = stateProvider?.request(for: dataTask) as? DataRequest else {
|
||||
fatalError("dataTask received data for incorrect Request subclass: \(String(describing: stateProvider?.request(for: dataTask)))")
|
||||
guard let request = request(for: dataTask, as: DataRequest.self) else {
|
||||
assertionFailure("dataTask did not find DataRequest.")
|
||||
return
|
||||
}
|
||||
|
||||
request.didReceive(data: data)
|
||||
|
@ -242,9 +262,9 @@ extension SessionDelegate: URLSessionDownloadDelegate {
|
|||
downloadTask: downloadTask,
|
||||
didResumeAtOffset: fileOffset,
|
||||
expectedTotalBytes: expectedTotalBytes)
|
||||
|
||||
guard let downloadRequest = stateProvider?.request(for: downloadTask) as? DownloadRequest else {
|
||||
fatalError("No DownloadRequest found for downloadTask: \(downloadTask)")
|
||||
guard let downloadRequest = request(for: downloadTask, as: DownloadRequest.self) else {
|
||||
assertionFailure("downloadTask did not find DownloadRequest.")
|
||||
return
|
||||
}
|
||||
|
||||
downloadRequest.updateDownloadProgress(bytesWritten: fileOffset,
|
||||
|
@ -261,9 +281,9 @@ extension SessionDelegate: URLSessionDownloadDelegate {
|
|||
didWriteData: bytesWritten,
|
||||
totalBytesWritten: totalBytesWritten,
|
||||
totalBytesExpectedToWrite: totalBytesExpectedToWrite)
|
||||
|
||||
guard let downloadRequest = stateProvider?.request(for: downloadTask) as? DownloadRequest else {
|
||||
fatalError("No DownloadRequest found for downloadTask: \(downloadTask)")
|
||||
guard let downloadRequest = request(for: downloadTask, as: DownloadRequest.self) else {
|
||||
assertionFailure("downloadTask did not find DownloadRequest.")
|
||||
return
|
||||
}
|
||||
|
||||
downloadRequest.updateDownloadProgress(bytesWritten: bytesWritten,
|
||||
|
@ -273,8 +293,9 @@ extension SessionDelegate: URLSessionDownloadDelegate {
|
|||
open func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
|
||||
eventMonitor?.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: location)
|
||||
|
||||
guard let request = stateProvider?.request(for: downloadTask) as? DownloadRequest else {
|
||||
fatalError("Download finished but either no request found or request wasn't DownloadRequest")
|
||||
guard let request = request(for: downloadTask, as: DownloadRequest.self) else {
|
||||
assertionFailure("downloadTask did not find DownloadRequest.")
|
||||
return
|
||||
}
|
||||
|
||||
guard let response = request.response else {
|
||||
|
|
|
@ -411,7 +411,7 @@ final class _URLEncodedFormEncoder {
|
|||
private let dataEncoding: URLEncodedFormEncoder.DataEncoding
|
||||
private let dateEncoding: URLEncodedFormEncoder.DateEncoding
|
||||
|
||||
public init(context: URLEncodedFormContext,
|
||||
init(context: URLEncodedFormContext,
|
||||
codingPath: [CodingKey] = [],
|
||||
boolEncoding: URLEncodedFormEncoder.BoolEncoding,
|
||||
dataEncoding: URLEncodedFormEncoder.DataEncoding,
|
||||
|
|
|
@ -97,7 +97,7 @@ extension Request {
|
|||
data: Data?)
|
||||
-> ValidationResult
|
||||
where S.Iterator.Element == String {
|
||||
guard let data = data, data.count > 0 else { return .success(Void()) }
|
||||
guard let data = data, !data.isEmpty else { return .success(Void()) }
|
||||
|
||||
guard
|
||||
let responseContentType = response.mimeType,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2010-2019, Deusty, LLC
|
||||
Copyright (c) 2010-2020, Deusty, LLC
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
|
|
@ -16,14 +16,15 @@ CocoaLumberjack
|
|||
**CocoaLumberjack** is a fast & simple, yet powerful & flexible logging framework for Mac and iOS.
|
||||
|
||||
### How to get started
|
||||
- install via [CocoaPods](http://cocoapods.org)
|
||||
- use `DDOSLogger` for iOS 10 and later, `DDTTYLogger` and `DDASLLogger` for earlier versions.
|
||||
|
||||
##### Swift version via CocoaPods
|
||||
First, install CocoaLumberjack via [CocoaPods](http://cocoapods.org), [Carthage](https://github.com/Carthage/Carthage), [Swift Package Manager](https://swift.org/package-manager/) or manually.
|
||||
Then use `DDOSLogger` for iOS 10 and later, or `DDTTYLogger` and `DDASLLogger` for earlier versions to begin logging messages.
|
||||
|
||||
#### CocoaPods
|
||||
|
||||
```ruby
|
||||
platform :ios, '8.0'
|
||||
|
||||
# You need to set target when you use CocoaPods 1.0.0 or later.
|
||||
target 'SampleTarget' do
|
||||
use_frameworks!
|
||||
pod 'CocoaLumberjack/Swift'
|
||||
|
@ -32,13 +33,44 @@ end
|
|||
Note: `Swift` is a subspec which will include all the Obj-C code plus the Swift one, so this is sufficient.
|
||||
For more details about how to use Swift with Lumberjack, see [this conversation](https://github.com/CocoaLumberjack/CocoaLumberjack/issues/405).
|
||||
|
||||
##### Swift Usage
|
||||
For Objective-C use the following:
|
||||
```ruby
|
||||
platform :ios, '8.0'
|
||||
|
||||
If you installed using CocoaPods or manually:
|
||||
```swift
|
||||
import CocoaLumberjackSwift
|
||||
target 'SampleTarget' do
|
||||
pod 'CocoaLumberjack'
|
||||
end
|
||||
```
|
||||
|
||||
#### Carthage
|
||||
|
||||
Carthage is a lightweight dependency manager for Swift and Objective-C. It leverages CocoaTouch modules and is less invasive than CocoaPods.
|
||||
|
||||
To install with Carthage, follow the instruction on [Carthage](https://github.com/Carthage/Carthage)
|
||||
|
||||
Cartfile
|
||||
```
|
||||
github "CocoaLumberjack/CocoaLumberjack"
|
||||
```
|
||||
|
||||
|
||||
#### Swift Package Manager
|
||||
|
||||
As of CocoaLumberjack 3.6.0, you can use the Swift Package Manager as integration method.
|
||||
If you want to use the Swift Package Manager as integration method, either use Xcode to add the package dependency or add the following dependency to your Package.swift:
|
||||
|
||||
```swift
|
||||
.package(url: "https://github.com/CocoaLumberjack/CocoaLumberjack.git", from: "3.6.0"),
|
||||
```
|
||||
|
||||
#### Install manually
|
||||
|
||||
If you want to install CocoaLumberjack manually, read the [manual installation](https://raw.githubusercontent.com/CocoaLumberjack/CocoaLumberjack/master/Documentation/GettingStarted.md#manual-installation) guide for more information.
|
||||
|
||||
#### Swift Usage
|
||||
|
||||
Usually, you can simply `import CocoaLumberjackSwift`. If you installed CocoaLumberjack using CocoaPods, you need to use `import CocoaLumberjack` instead.
|
||||
|
||||
```swift
|
||||
DDLog.add(DDOSLogger.sharedInstance) // Uses os_log
|
||||
|
||||
|
@ -56,16 +88,9 @@ DDLogWarn("Warn")
|
|||
DDLogError("Error")
|
||||
```
|
||||
|
||||
##### Obj-C version via CocoaPods
|
||||
#### Obj-C usage
|
||||
|
||||
```ruby
|
||||
platform :ios, '8.0'
|
||||
pod 'CocoaLumberjack'
|
||||
```
|
||||
|
||||
##### Obj-C usage
|
||||
If you're using Lumberjack as a framework, you can `@import CocoaLumberjack;`.
|
||||
|
||||
Otherwise, `#import <CocoaLumberjack/CocoaLumberjack.h>`
|
||||
|
||||
```objc
|
||||
|
@ -85,22 +110,13 @@ DDLogWarn(@"Warn");
|
|||
DDLogError(@"Error");
|
||||
```
|
||||
|
||||
##### Installation with Carthage (iOS 8+)
|
||||
#### More information
|
||||
|
||||
[Carthage](https://github.com/Carthage/Carthage) is a lightweight dependency manager for Swift and Objective-C. It leverages CocoaTouch modules and is less invasive than CocoaPods.
|
||||
|
||||
To install with Carthage, follow the instruction on [Carthage](https://github.com/Carthage/Carthage)
|
||||
|
||||
Cartfile
|
||||
```
|
||||
github "CocoaLumberjack/CocoaLumberjack"
|
||||
```
|
||||
|
||||
- or [install manually](https://raw.githubusercontent.com/CocoaLumberjack/CocoaLumberjack/master/Documentation/GettingStarted.md#manual-installation)
|
||||
- read the [Getting started](https://raw.githubusercontent.com/CocoaLumberjack/CocoaLumberjack/master/Documentation/GettingStarted.md) guide, check out the [FAQ](https://raw.githubusercontent.com/CocoaLumberjack/CocoaLumberjack/master/Documentation/FAQ.md) section or the other [docs](Documentation/)
|
||||
- if you find issues or want to suggest improvements, create an issue or a pull request
|
||||
- for all kinds of questions involving CocoaLumberjack, use the [Google group](http://groups.google.com/group/cocoalumberjack) or StackOverflow (use [#lumberjack](http://stackoverflow.com/questions/tagged/lumberjack)).
|
||||
|
||||
|
||||
### CocoaLumberjack 3
|
||||
|
||||
#### Migrating to 3.x
|
||||
|
@ -151,16 +167,16 @@ Configure your logging however you want. Change log levels per file (perfect for
|
|||
|
||||
### Requirements
|
||||
The current version of Lumberjack requires:
|
||||
- Xcode 10.2 or later
|
||||
- Xcode 11 or later
|
||||
- Swift 5.0 or later
|
||||
- iOS 8 or later
|
||||
- OS X 10.10 or later
|
||||
- WatchOS 3 or later
|
||||
- TVOS 9 or later
|
||||
- macOS 10.10 or later
|
||||
- watchOS 3 or later
|
||||
- tvOS 9 or later
|
||||
|
||||
#### Backwards compatibility
|
||||
- for Xcode 10 and Swift 4.2, use the 3.5.2 version
|
||||
- for iOS 6, iOS 7, OS X 10.8, OS 10.9 and Xcode 9, use the 3.4.2 version
|
||||
- for iOS 6, iOS 7, OS X 10.8, OS X 10.9 and Xcode 9, use the 3.4.2 version
|
||||
- for iOS 5 and OS X 10.7, use the 3.3 version
|
||||
- for Xcode 8 and Swift 3, use the 3.2 version
|
||||
- for Xcode 7.3 and Swift 2.3, use the 2.4.0 version
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -26,9 +26,8 @@
|
|||
|
||||
@implementation CLIColor
|
||||
|
||||
+ (CLIColor *)colorWithCalibratedRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha {
|
||||
+ (instancetype)colorWithCalibratedRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha {
|
||||
CLIColor *color = [CLIColor new];
|
||||
|
||||
color->_red = red;
|
||||
color->_green = green;
|
||||
color->_blue = blue;
|
||||
|
@ -40,15 +39,12 @@
|
|||
if (red) {
|
||||
*red = _red;
|
||||
}
|
||||
|
||||
if (green) {
|
||||
*green = _green;
|
||||
}
|
||||
|
||||
if (blue) {
|
||||
*blue = _blue;
|
||||
}
|
||||
|
||||
if (alpha) {
|
||||
*alpha = _alpha;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -62,6 +62,10 @@ static DDASLLogger *sharedInstance;
|
|||
return self;
|
||||
}
|
||||
|
||||
- (DDLoggerName)loggerName {
|
||||
return DDLoggerNameASL;
|
||||
}
|
||||
|
||||
- (void)logMessage:(DDLogMessage *)logMessage {
|
||||
// Skip captured log messages
|
||||
if ([logMessage->_fileName isEqualToString:@"DDASLLogCapture"]) {
|
||||
|
@ -116,10 +120,6 @@ static DDASLLogger *sharedInstance;
|
|||
}
|
||||
}
|
||||
|
||||
- (DDLoggerName)loggerName {
|
||||
return DDLoggerNameASL;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -16,6 +16,7 @@
|
|||
#import <CocoaLumberjack/DDFileLogger.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DDFileLogger (Internal)
|
||||
|
||||
- (void)logData:(NSData *)data;
|
||||
|
@ -23,7 +24,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
// Will assert if used outside logger's queue.
|
||||
- (void)lt_logData:(NSData *)data;
|
||||
|
||||
- (NSData *)lt_dataForMessage:(DDLogMessage *)message;
|
||||
- (nullable NSData *)lt_dataForMessage:(DDLogMessage *)message;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -50,11 +50,14 @@ NSTimeInterval const kDDDefaultLogRollingFrequency = 60 * 60 * 24; // 24
|
|||
NSUInteger const kDDDefaultLogMaxNumLogFiles = 5; // 5 Files
|
||||
unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20 MB
|
||||
|
||||
NSTimeInterval const kDDRollingLeeway = 1.0; // 1s
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@interface DDLogFileManagerDefault () {
|
||||
NSDateFormatter *_fileDateFormatter;
|
||||
NSUInteger _maximumNumberOfLogFiles;
|
||||
unsigned long long _logFilesDiskQuota;
|
||||
NSString *_logsDirectory;
|
||||
|
@ -70,15 +73,29 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
@synthesize maximumNumberOfLogFiles = _maximumNumberOfLogFiles;
|
||||
@synthesize logFilesDiskQuota = _logFilesDiskQuota;
|
||||
|
||||
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey {
|
||||
|
||||
if ([theKey isEqualToString:@"maximumNumberOfLogFiles"] || [theKey isEqualToString:@"logFilesDiskQuota"]) {
|
||||
return NO;
|
||||
} else {
|
||||
return [super automaticallyNotifiesObserversForKey:theKey];
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
return [self initWithLogsDirectory:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithLogsDirectory:(NSString * __nullable)aLogsDirectory {
|
||||
- (instancetype)initWithLogsDirectory:(nullable NSString *)aLogsDirectory {
|
||||
if ((self = [super init])) {
|
||||
_maximumNumberOfLogFiles = kDDDefaultLogMaxNumLogFiles;
|
||||
_logFilesDiskQuota = kDDDefaultLogFilesDiskQuota;
|
||||
|
||||
_fileDateFormatter = [[NSDateFormatter alloc] init];
|
||||
[_fileDateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]];
|
||||
[_fileDateFormatter setDateFormat: @"yyyy'-'MM'-'dd'--'HH'-'mm'-'ss'-'SSS'"];
|
||||
[_fileDateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
|
||||
|
||||
if (aLogsDirectory.length > 0) {
|
||||
_logsDirectory = [aLogsDirectory copy];
|
||||
} else {
|
||||
|
@ -97,15 +114,6 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
return self;
|
||||
}
|
||||
|
||||
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey {
|
||||
|
||||
if ([theKey isEqualToString:@"maximumNumberOfLogFiles"] || [theKey isEqualToString:@"logFilesDiskQuota"]) {
|
||||
return NO;
|
||||
} else {
|
||||
return [super automaticallyNotifiesObserversForKey:theKey];
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
- (instancetype)initWithLogsDirectory:(NSString *)logsDirectory
|
||||
defaultFileProtectionLevel:(NSFileProtectionType)fileProtectionLevel {
|
||||
|
@ -301,20 +309,7 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
|
||||
// if you change formatter, then change sortedLogFileInfos method also accordingly
|
||||
- (NSDateFormatter *)logFileDateFormatter {
|
||||
NSMutableDictionary *dictionary = [[NSThread currentThread] threadDictionary];
|
||||
NSString *dateFormat = @"yyyy'-'MM'-'dd'--'HH'-'mm'-'ss'-'SSS'";
|
||||
NSString *key = [NSString stringWithFormat:@"logFileDateFormatter.%@", dateFormat];
|
||||
NSDateFormatter *dateFormatter = dictionary[key];
|
||||
|
||||
if (dateFormatter == nil) {
|
||||
dateFormatter = [[NSDateFormatter alloc] init];
|
||||
[dateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]];
|
||||
[dateFormatter setDateFormat:dateFormat];
|
||||
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
|
||||
dictionary[key] = dateFormatter;
|
||||
}
|
||||
|
||||
return dateFormatter;
|
||||
return _fileDateFormatter;
|
||||
}
|
||||
|
||||
- (NSArray *)unsortedLogFilePaths {
|
||||
|
@ -326,19 +321,19 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
for (NSString *fileName in fileNames) {
|
||||
// Filter out any files that aren't log files. (Just for extra safety)
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
// This is only used on the iPhone simulator for backward compatibility reason.
|
||||
//
|
||||
// In case of iPhone simulator there can be 'archived' extension. isLogFile:
|
||||
// method knows nothing about it. Thus removing it for this method.
|
||||
//
|
||||
// See full explanation in the header file.
|
||||
NSString *theFileName = [fileName stringByReplacingOccurrencesOfString:@".archived"
|
||||
withString:@""];
|
||||
|
||||
if ([self isLogFile:theFileName])
|
||||
#else
|
||||
#else
|
||||
|
||||
if ([self isLogFile:fileName])
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
NSString *filePath = [logsDirectory stringByAppendingPathComponent:fileName];
|
||||
|
||||
|
@ -409,7 +404,10 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
if (arrayComponent.count > 0) {
|
||||
NSString *stringDate = arrayComponent.lastObject;
|
||||
stringDate = [stringDate stringByReplacingOccurrencesOfString:@".log" withString:@""];
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
// This is only used on the iPhone simulator for backward compatibility reason.
|
||||
stringDate = [stringDate stringByReplacingOccurrencesOfString:@".archived" withString:@""];
|
||||
#endif
|
||||
date1 = [[self logFileDateFormatter] dateFromString:stringDate] ?: [obj1 creationDate];
|
||||
}
|
||||
|
||||
|
@ -417,7 +415,10 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
if (arrayComponent.count > 0) {
|
||||
NSString *stringDate = arrayComponent.lastObject;
|
||||
stringDate = [stringDate stringByReplacingOccurrencesOfString:@".log" withString:@""];
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
// This is only used on the iPhone simulator for backward compatibility reason.
|
||||
stringDate = [stringDate stringByReplacingOccurrencesOfString:@".archived" withString:@""];
|
||||
#endif
|
||||
date2 = [[self logFileDateFormatter] dateFromString:stringDate] ?: [obj2 creationDate];
|
||||
}
|
||||
|
||||
|
@ -440,7 +441,7 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
return [NSString stringWithFormat:@"%@ %@.log", appName, formattedDate];
|
||||
}
|
||||
|
||||
- (NSString * __nullable)logFileHeader {
|
||||
- (nullable NSString *)logFileHeader {
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -458,7 +459,7 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
return [fileHeaderStr dataUsingEncoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
- (NSString *)createNewLogFile {
|
||||
- (NSString *)createNewLogFileWithError:(NSError *__autoreleasing _Nullable *)error {
|
||||
static NSUInteger MAX_ALLOWED_ERROR = 5;
|
||||
|
||||
NSString *fileName = [self newLogFileName];
|
||||
|
@ -470,16 +471,17 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
|
||||
NSUInteger attempt = 1;
|
||||
NSUInteger criticalErrors = 0;
|
||||
NSError *lastCriticalError;
|
||||
|
||||
do {
|
||||
if (criticalErrors >= MAX_ALLOWED_ERROR) {
|
||||
NSLogError(@"DDLogFileManagerDefault: Bailing file creation, encountered %ld errors.",
|
||||
(unsigned long)criticalErrors);
|
||||
*error = lastCriticalError;
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *actualFileName = fileName;
|
||||
|
||||
if (attempt > 1) {
|
||||
NSString *extension = [actualFileName pathExtension];
|
||||
|
||||
|
@ -493,8 +495,8 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
|
||||
NSString *filePath = [logsDirectory stringByAppendingPathComponent:actualFileName];
|
||||
|
||||
NSError *error = nil;
|
||||
BOOL success = [fileHeader writeToFile:filePath options:NSAtomicWrite error:&error];
|
||||
NSError *currentError = nil;
|
||||
BOOL success = [fileHeader writeToFile:filePath options:NSDataWritingAtomic error:¤tError];
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
if (success) {
|
||||
|
@ -506,23 +508,24 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
NSDictionary *attributes = @{NSFileProtectionKey: [self logFileProtection]};
|
||||
success = [[NSFileManager defaultManager] setAttributes:attributes
|
||||
ofItemAtPath:filePath
|
||||
error:&error];
|
||||
error:¤tError];
|
||||
}
|
||||
#endif
|
||||
|
||||
if (success) {
|
||||
NSLogVerbose(@"PURLogFileManagerDefault: Created new log file: %@", actualFileName);
|
||||
NSLogVerbose(@"DDLogFileManagerDefault: Created new log file: %@", actualFileName);
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
// Since we just created a new log file, we may need to delete some old log files
|
||||
[self deleteOldLogFiles];
|
||||
});
|
||||
return filePath;
|
||||
} else if (error.code == NSFileWriteFileExistsError) {
|
||||
} else if (currentError.code == NSFileWriteFileExistsError) {
|
||||
attempt++;
|
||||
continue;
|
||||
} else {
|
||||
NSLogError(@"PURLogFileManagerDefault: Critical error while creating log file: %@", error);
|
||||
NSLogError(@"DDLogFileManagerDefault: Critical error while creating log file: %@", currentError);
|
||||
criticalErrors++;
|
||||
lastCriticalError = currentError;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -571,7 +574,7 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
return [self initWithDateFormatter:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithDateFormatter:(NSDateFormatter * __nullable)aDateFormatter {
|
||||
- (instancetype)initWithDateFormatter:(nullable NSDateFormatter *)aDateFormatter {
|
||||
if ((self = [super init])) {
|
||||
if (aDateFormatter) {
|
||||
_dateFormatter = aDateFormatter;
|
||||
|
@ -630,7 +633,7 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
}
|
||||
|
||||
- (instancetype)initWithLogFileManager:(id <DDLogFileManager>)aLogFileManager
|
||||
completionQueue:(dispatch_queue_t __nullable)dispatchQueue {
|
||||
completionQueue:(nullable dispatch_queue_t)dispatchQueue {
|
||||
if ((self = [super init])) {
|
||||
_completionQueue = dispatchQueue ?: dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
|
||||
|
@ -833,7 +836,7 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
int64_t delay = (int64_t)(MIN([logFileRollingDate timeIntervalSinceNow], kDDMaxTimerDelay) * (NSTimeInterval) NSEC_PER_SEC);
|
||||
dispatch_time_t fireTime = dispatch_time(DISPATCH_TIME_NOW, delay);
|
||||
|
||||
dispatch_source_set_timer(_rollingTimer, fireTime, DISPATCH_TIME_FOREVER, 1ull * NSEC_PER_SEC);
|
||||
dispatch_source_set_timer(_rollingTimer, fireTime, DISPATCH_TIME_FOREVER, (uint64_t)kDDRollingLeeway * NSEC_PER_SEC);
|
||||
dispatch_resume(_rollingTimer);
|
||||
}
|
||||
|
||||
|
@ -841,7 +844,7 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
[self rollLogFileWithCompletionBlock:nil];
|
||||
}
|
||||
|
||||
- (void)rollLogFileWithCompletionBlock:(void (^ __nullable)(void))completionBlock {
|
||||
- (void)rollLogFileWithCompletionBlock:(nullable void (^)(void))completionBlock {
|
||||
// This method is public.
|
||||
// We need to execute the rolling on our logging thread/queue.
|
||||
|
||||
|
@ -885,10 +888,11 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
_currentLogFileHandle = nil;
|
||||
|
||||
_currentLogFileInfo.isArchived = YES;
|
||||
NSString *archivedFilePath = [_currentLogFileInfo.filePath copy];
|
||||
BOOL logFileManagerRespondsToSelector = [_logFileManager respondsToSelector:@selector(didRollAndArchiveLogFile:)];
|
||||
NSString *archivedFilePath = (logFileManagerRespondsToSelector) ? [_currentLogFileInfo.filePath copy] : nil;
|
||||
_currentLogFileInfo = nil;
|
||||
|
||||
if ([_logFileManager respondsToSelector:@selector(didRollAndArchiveLogFile:)]) {
|
||||
if (logFileManagerRespondsToSelector) {
|
||||
dispatch_async(_completionQueue, ^{
|
||||
[self->_logFileManager didRollAndArchiveLogFile:archivedFilePath];
|
||||
});
|
||||
|
@ -908,7 +912,7 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
- (void)lt_maybeRollLogFileDueToAge {
|
||||
NSAssert([self isOnInternalLoggerQueue], @"lt_ methods should be on logger queue.");
|
||||
|
||||
if (_rollingFrequency > 0.0 && _currentLogFileInfo.age >= _rollingFrequency) {
|
||||
if (_rollingFrequency > 0.0 && (_currentLogFileInfo.age + kDDRollingLeeway) >= _rollingFrequency) {
|
||||
NSLogVerbose(@"DDFileLogger: Rolling log file due to age...");
|
||||
[self lt_rollLogFileNow];
|
||||
} else {
|
||||
|
@ -1027,8 +1031,23 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
}
|
||||
_currentLogFileInfo = newCurrentLogFile;
|
||||
} else {
|
||||
NSString *currentLogFilePath = [_logFileManager createNewLogFile];
|
||||
_currentLogFileInfo = [[DDLogFileInfo alloc] initWithFilePath:currentLogFilePath];
|
||||
NSString *currentLogFilePath;
|
||||
if ([_logFileManager respondsToSelector:@selector(createNewLogFileWithError:)]) {
|
||||
__autoreleasing NSError *error;
|
||||
currentLogFilePath = [_logFileManager createNewLogFileWithError:&error];
|
||||
if (!currentLogFilePath) {
|
||||
NSLogError(@"DDFileLogger: Failed to create new log file: %@", error);
|
||||
}
|
||||
} else {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
NSAssert([_logFileManager respondsToSelector:@selector(createNewLogFile)],
|
||||
@"Invalid log file manager! Responds neither to `-createNewLogFileWithError:` nor `-createNewLogFile`!");
|
||||
currentLogFilePath = [_logFileManager createNewLogFile];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
// Use static factory method here, since it checks for nil (and is unavailable to Swift).
|
||||
_currentLogFileInfo = [DDLogFileInfo logFileWithPath:currentLogFilePath];
|
||||
}
|
||||
|
||||
return _currentLogFileInfo;
|
||||
|
@ -1046,11 +1065,11 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
// If we're resuming, we need to check if the log file is allowed for reuse or needs to be archived.
|
||||
if (isResuming && (_doNotReuseLogFiles || [self lt_shouldLogFileBeArchived:logFileInfo])) {
|
||||
logFileInfo.isArchived = YES;
|
||||
NSString *archivedLogFilePath = [logFileInfo.fileName copy];
|
||||
|
||||
if ([_logFileManager respondsToSelector:@selector(didArchiveLogFile:)]) {
|
||||
NSString *archivedFilePath = [logFileInfo.filePath copy];
|
||||
dispatch_async(_completionQueue, ^{
|
||||
[self->_logFileManager didArchiveLogFile:archivedLogFilePath];
|
||||
[self->_logFileManager didArchiveLogFile:archivedFilePath];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1111,26 +1130,14 @@ unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20
|
|||
static int exception_count = 0;
|
||||
|
||||
- (void)logMessage:(DDLogMessage *)logMessage {
|
||||
NSAssert([self isOnInternalLoggerQueue], @"logMessage should only be executed on internal queue.");
|
||||
// Don't need to check for isOnInternalLoggerQueue, -lt_dataForMessage: will do it for us.
|
||||
NSData *data = [self lt_dataForMessage:logMessage];
|
||||
|
||||
NSString *message = logMessage->_message;
|
||||
BOOL isFormatted = NO;
|
||||
|
||||
if (_logFormatter != nil) {
|
||||
message = [_logFormatter formatLogMessage:logMessage];
|
||||
isFormatted = message != logMessage->_message;
|
||||
}
|
||||
|
||||
if (message.length == 0) {
|
||||
if (data.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL shouldFormat = !isFormatted || _automaticallyAppendNewlineForCustomFormatters;
|
||||
if (shouldFormat && ![message hasSuffix:@"\n"]) {
|
||||
message = [message stringByAppendingString:@"\n"];
|
||||
}
|
||||
|
||||
[self lt_logData:[message dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[self lt_logData:data];
|
||||
}
|
||||
|
||||
- (void)willLogMessage:(DDLogFileInfo *)logFileInfo {
|
||||
|
@ -1293,7 +1300,7 @@ static int exception_count = 0;
|
|||
}
|
||||
|
||||
if (message.length == 0) {
|
||||
return [NSData new];
|
||||
return nil;
|
||||
}
|
||||
|
||||
BOOL shouldFormat = !isFormatted || _automaticallyAppendNewlineForCustomFormatters;
|
||||
|
@ -1310,11 +1317,7 @@ static int exception_count = 0;
|
|||
#pragma mark -
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
static NSString * const kDDXAttrArchivedName = @"archived";
|
||||
#else
|
||||
static NSString * const kDDXAttrArchivedName = @"lumberjack.log.archived";
|
||||
#endif
|
||||
static NSString * const kDDXAttrArchivedName = @"lumberjack.log.archived";
|
||||
|
||||
@interface DDLogFileInfo () {
|
||||
__strong NSString *_filePath;
|
||||
|
@ -1328,6 +1331,15 @@ static int exception_count = 0;
|
|||
unsigned long long _fileSize;
|
||||
}
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
|
||||
// Old implementation of extended attributes on the simulator.
|
||||
|
||||
- (BOOL)_hasExtensionAttributeWithName:(NSString *)attrName;
|
||||
- (void)_removeExtensionAttributeWithName:(NSString *)attrName;
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
@ -1344,14 +1356,15 @@ static int exception_count = 0;
|
|||
|
||||
@dynamic isArchived;
|
||||
|
||||
|
||||
#pragma mark Lifecycle
|
||||
|
||||
+ (instancetype)logFileWithPath:(NSString *)aFilePath {
|
||||
if (!aFilePath) return nil;
|
||||
return [[self alloc] initWithFilePath:aFilePath];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFilePath:(NSString *)aFilePath {
|
||||
NSParameterAssert(aFilePath);
|
||||
if ((self = [super init])) {
|
||||
filePath = [aFilePath copy];
|
||||
}
|
||||
|
@ -1428,43 +1441,15 @@ static int exception_count = 0;
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (BOOL)isArchived {
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
|
||||
// Extended attributes don't work properly on the simulator.
|
||||
// So we have to use a less attractive alternative.
|
||||
// See full explanation in the header file.
|
||||
|
||||
return [self hasExtensionAttributeWithName:kDDXAttrArchivedName];
|
||||
|
||||
#else
|
||||
|
||||
return [self hasExtendedAttributeWithName:kDDXAttrArchivedName];
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)setIsArchived:(BOOL)flag {
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
|
||||
// Extended attributes don't work properly on the simulator.
|
||||
// So we have to use a less attractive alternative.
|
||||
// See full explanation in the header file.
|
||||
|
||||
if (flag) {
|
||||
[self addExtensionAttributeWithName:kDDXAttrArchivedName];
|
||||
} else {
|
||||
[self removeExtensionAttributeWithName:kDDXAttrArchivedName];
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (flag) {
|
||||
[self addExtendedAttributeWithName:kDDXAttrArchivedName];
|
||||
} else {
|
||||
[self removeExtendedAttributeWithName:kDDXAttrArchivedName];
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1483,6 +1468,7 @@ static int exception_count = 0;
|
|||
// See full explanation in the header file.
|
||||
|
||||
if (![newFileName isEqualToString:[self fileName]]) {
|
||||
NSFileManager* fileManager = [NSFileManager defaultManager];
|
||||
NSString *fileDir = [filePath stringByDeletingLastPathComponent];
|
||||
NSString *newFilePath = [fileDir stringByAppendingPathComponent:newFileName];
|
||||
|
||||
|
@ -1490,28 +1476,29 @@ static int exception_count = 0;
|
|||
// (in which case the file might not exist anymore and neither does it parent folder).
|
||||
#if defined(DEBUG) && (!defined(TARGET_IPHONE_SIMULATOR) || !TARGET_IPHONE_SIMULATOR)
|
||||
BOOL directory = NO;
|
||||
[[NSFileManager defaultManager] fileExistsAtPath:fileDir isDirectory:&directory];
|
||||
[fileManager fileExistsAtPath:fileDir isDirectory:&directory];
|
||||
NSAssert(directory, @"Containing directory must exist.");
|
||||
#endif
|
||||
|
||||
NSError *error = nil;
|
||||
|
||||
BOOL success = [[NSFileManager defaultManager] removeItemAtPath:newFilePath error:&error];
|
||||
BOOL success = [fileManager removeItemAtPath:newFilePath error:&error];
|
||||
if (!success && error.code != NSFileNoSuchFileError) {
|
||||
NSLogError(@"DDLogFileInfo: Error deleting archive (%@): %@", self.fileName, error);
|
||||
}
|
||||
|
||||
success = [[NSFileManager defaultManager] moveItemAtPath:filePath toPath:newFilePath error:&error];
|
||||
success = [fileManager moveItemAtPath:filePath toPath:newFilePath error:&error];
|
||||
|
||||
// When a log file is deleted, moved or renamed on the simulator, we attempt to rename it as a
|
||||
// result of "archiving" it, but since the file doesn't exist anymore, needless error logs are printed
|
||||
// We therefore ignore this error, and assert that the directory we are copying into exists (which
|
||||
// is the only other case where this error code can come up).
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
if (!success && error.code != NSFileNoSuchFileError) {
|
||||
if (!success && error.code != NSFileNoSuchFileError)
|
||||
#else
|
||||
if (!success) {
|
||||
if (!success)
|
||||
#endif
|
||||
{
|
||||
NSLogError(@"DDLogFileInfo: Error renaming file (%@): %@", self.fileName, error);
|
||||
}
|
||||
|
||||
|
@ -1526,13 +1513,26 @@ static int exception_count = 0;
|
|||
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
|
||||
// Extended attributes don't work properly on the simulator.
|
||||
// So we have to use a less attractive alternative.
|
||||
// See full explanation in the header file.
|
||||
// Old implementation of extended attributes on the simulator.
|
||||
|
||||
- (BOOL)hasExtensionAttributeWithName:(NSString *)attrName {
|
||||
// This method is only used on the iPhone simulator, where normal extended attributes are broken.
|
||||
// See full explanation in the header file.
|
||||
// Extended attributes were not working properly on the simulator
|
||||
// due to misuse of setxattr() function.
|
||||
// Now that this is fixed in the new implementation, we want to keep
|
||||
// backward compatibility with previous simulator installations.
|
||||
|
||||
static NSString * const kDDExtensionSeparator = @".";
|
||||
|
||||
static NSString *_xattrToExtensionName(NSString *attrName) {
|
||||
static NSDictionary<NSString *, NSString *>* _xattrToExtensionNameMap;
|
||||
static dispatch_once_t _token;
|
||||
dispatch_once(&_token, ^{
|
||||
_xattrToExtensionNameMap = @{ kDDXAttrArchivedName: @"archived" };
|
||||
});
|
||||
return [_xattrToExtensionNameMap objectForKey:attrName];
|
||||
}
|
||||
|
||||
- (BOOL)_hasExtensionAttributeWithName:(NSString *)attrName {
|
||||
// This method is only used on the iPhone simulator for backward compatibility reason.
|
||||
|
||||
// Split the file name into components. File name may have various format, but generally
|
||||
// structure is same:
|
||||
|
@ -1543,7 +1543,7 @@ static int exception_count = 0;
|
|||
//
|
||||
// So we want to search for the attrName in the components (ignoring the first array index).
|
||||
|
||||
NSArray *components = [[self fileName] componentsSeparatedByString:@"."];
|
||||
NSArray *components = [[self fileName] componentsSeparatedByString:kDDExtensionSeparator];
|
||||
|
||||
// Watch out for file names without an extension
|
||||
|
||||
|
@ -1558,66 +1558,8 @@ static int exception_count = 0;
|
|||
return NO;
|
||||
}
|
||||
|
||||
- (void)addExtensionAttributeWithName:(NSString *)attrName {
|
||||
// This method is only used on the iPhone simulator, where normal extended attributes are broken.
|
||||
// See full explanation in the header file.
|
||||
|
||||
if ([attrName length] == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Example:
|
||||
// attrName = "archived"
|
||||
//
|
||||
// "mylog.txt" -> "mylog.archived.txt"
|
||||
// "mylog" -> "mylog.archived"
|
||||
|
||||
NSArray *components = [[self fileName] componentsSeparatedByString:@"."];
|
||||
|
||||
NSUInteger count = [components count];
|
||||
|
||||
NSUInteger estimatedNewLength = [[self fileName] length] + [attrName length] + 1;
|
||||
NSMutableString *newFileName = [NSMutableString stringWithCapacity:estimatedNewLength];
|
||||
|
||||
if (count > 0) {
|
||||
[newFileName appendString:components.firstObject];
|
||||
}
|
||||
|
||||
NSString *lastExt = @"";
|
||||
|
||||
NSUInteger i;
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
NSString *attr = components[i];
|
||||
|
||||
if ([attr length] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ([attrName isEqualToString:attr]) {
|
||||
// Extension attribute already exists in file name
|
||||
return;
|
||||
}
|
||||
|
||||
if ([lastExt length] > 0) {
|
||||
[newFileName appendFormat:@".%@", lastExt];
|
||||
}
|
||||
|
||||
lastExt = attr;
|
||||
}
|
||||
|
||||
[newFileName appendFormat:@".%@", attrName];
|
||||
|
||||
if ([lastExt length] > 0) {
|
||||
[newFileName appendFormat:@".%@", lastExt];
|
||||
}
|
||||
|
||||
[self renameFile:newFileName];
|
||||
}
|
||||
|
||||
- (void)removeExtensionAttributeWithName:(NSString *)attrName {
|
||||
// This method is only used on the iPhone simulator, where normal extended attributes are broken.
|
||||
// See full explanation in the header file.
|
||||
- (void)_removeExtensionAttributeWithName:(NSString *)attrName {
|
||||
// This method is only used on the iPhone simulator for backward compatibility reason.
|
||||
|
||||
if ([attrName length] == 0) {
|
||||
return;
|
||||
|
@ -1629,7 +1571,7 @@ static int exception_count = 0;
|
|||
// "mylog.archived.txt" -> "mylog.txt"
|
||||
// "mylog.archived" -> "mylog"
|
||||
|
||||
NSArray *components = [[self fileName] componentsSeparatedByString:@"."];
|
||||
NSArray *components = [[self fileName] componentsSeparatedByString:kDDExtensionSeparator];
|
||||
|
||||
NSUInteger count = [components count];
|
||||
|
||||
|
@ -1650,7 +1592,8 @@ static int exception_count = 0;
|
|||
if ([attrName isEqualToString:attr]) {
|
||||
found = YES;
|
||||
} else {
|
||||
[newFileName appendFormat:@".%@", attr];
|
||||
[newFileName appendString:kDDExtensionSeparator];
|
||||
[newFileName appendString:attr];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1659,22 +1602,42 @@ static int exception_count = 0;
|
|||
}
|
||||
}
|
||||
|
||||
#else /* if TARGET_IPHONE_SIMULATOR */
|
||||
#endif /* if TARGET_IPHONE_SIMULATOR */
|
||||
|
||||
- (BOOL)hasExtendedAttributeWithName:(NSString *)attrName {
|
||||
const char *path = [filePath UTF8String];
|
||||
const char *path = [filePath fileSystemRepresentation];
|
||||
const char *name = [attrName UTF8String];
|
||||
BOOL hasExtendedAttribute = NO;
|
||||
char buffer[1];
|
||||
|
||||
ssize_t result = getxattr(path, name, NULL, 0, 0, 0);
|
||||
ssize_t result = getxattr(path, name, buffer, 1, 0, 0);
|
||||
|
||||
return (result >= 0);
|
||||
// Fast path
|
||||
if (result > 0 && buffer[0] == '\1') {
|
||||
hasExtendedAttribute = YES;
|
||||
}
|
||||
// Maintain backward compatibility, but fix it for future checks
|
||||
else if (result >= 0) {
|
||||
hasExtendedAttribute = YES;
|
||||
|
||||
[self addExtendedAttributeWithName:attrName];
|
||||
}
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
else if ([self _hasExtensionAttributeWithName:_xattrToExtensionName(attrName)]) {
|
||||
hasExtendedAttribute = YES;
|
||||
|
||||
[self addExtendedAttributeWithName:attrName];
|
||||
}
|
||||
#endif
|
||||
|
||||
return hasExtendedAttribute;
|
||||
}
|
||||
|
||||
- (void)addExtendedAttributeWithName:(NSString *)attrName {
|
||||
const char *path = [filePath UTF8String];
|
||||
const char *path = [filePath fileSystemRepresentation];
|
||||
const char *name = [attrName UTF8String];
|
||||
|
||||
int result = setxattr(path, name, NULL, 0, 0, 0);
|
||||
int result = setxattr(path, name, "\1", 1, 0, 0);
|
||||
|
||||
if (result < 0) {
|
||||
NSLogError(@"DDLogFileInfo: setxattr(%@, %@): error = %s",
|
||||
|
@ -1682,10 +1645,15 @@ static int exception_count = 0;
|
|||
filePath,
|
||||
strerror(errno));
|
||||
}
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
else {
|
||||
[self _removeExtensionAttributeWithName:_xattrToExtensionName(attrName)];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)removeExtendedAttributeWithName:(NSString *)attrName {
|
||||
const char *path = [filePath UTF8String];
|
||||
const char *path = [filePath fileSystemRepresentation];
|
||||
const char *name = [attrName UTF8String];
|
||||
|
||||
int result = removexattr(path, name, 0);
|
||||
|
@ -1696,9 +1664,11 @@ static int exception_count = 0;
|
|||
self.fileName,
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* if TARGET_IPHONE_SIMULATOR */
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
[self _removeExtensionAttributeWithName:_xattrToExtensionName(attrName)];
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark Comparisons
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -22,6 +22,7 @@
|
|||
|
||||
#import <pthread.h>
|
||||
#import <objc/runtime.h>
|
||||
#import <sys/qos.h>
|
||||
|
||||
#if TARGET_OS_IOS
|
||||
#import <UIKit/UIDevice.h>
|
||||
|
@ -84,7 +85,7 @@ static void *const GlobalLoggingQueueIdentityKey = (void *)&GlobalLoggingQueueId
|
|||
@property (nonatomic, readonly) DDLogLevel level;
|
||||
@property (nonatomic, readonly) dispatch_queue_t loggerQueue;
|
||||
|
||||
+ (DDLoggerNode *)nodeWithLogger:(id <DDLogger>)logger
|
||||
+ (instancetype)nodeWithLogger:(id <DDLogger>)logger
|
||||
loggerQueue:(dispatch_queue_t)loggerQueue
|
||||
level:(DDLogLevel)level;
|
||||
|
||||
|
@ -173,7 +174,7 @@ static NSUInteger _numProcessors;
|
|||
*
|
||||
* @return An initialized `DDLog` instance.
|
||||
*/
|
||||
- (id)init {
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
|
@ -508,13 +509,11 @@ static NSUInteger _numProcessors;
|
|||
[self queueLogMessage:logMessage asynchronously:asynchronous];
|
||||
}
|
||||
|
||||
+ (void)log:(BOOL)asynchronous
|
||||
message:(DDLogMessage *)logMessage {
|
||||
+ (void)log:(BOOL)asynchronous message:(DDLogMessage *)logMessage {
|
||||
[self.sharedInstance log:asynchronous message:logMessage];
|
||||
}
|
||||
|
||||
- (void)log:(BOOL)asynchronous
|
||||
message:(DDLogMessage *)logMessage {
|
||||
- (void)log:(BOOL)asynchronous message:(DDLogMessage *)logMessage {
|
||||
[self queueLogMessage:logMessage asynchronously:asynchronous];
|
||||
}
|
||||
|
||||
|
@ -693,7 +692,7 @@ static NSUInteger _numProcessors;
|
|||
// Add to loggers array.
|
||||
// Need to create loggerQueue if loggerNode doesn't provide one.
|
||||
|
||||
for (DDLoggerNode* node in self._loggers) {
|
||||
for (DDLoggerNode *node in self._loggers) {
|
||||
if (node->_logger == logger
|
||||
&& node->_level == level) {
|
||||
// Exactly same logger already added, exit
|
||||
|
@ -705,21 +704,18 @@ static NSUInteger _numProcessors;
|
|||
@"This method should only be run on the logging thread/queue");
|
||||
|
||||
dispatch_queue_t loggerQueue = NULL;
|
||||
|
||||
if ([logger respondsToSelector:@selector(loggerQueue)]) {
|
||||
// Logger may be providing its own queue
|
||||
|
||||
loggerQueue = [logger loggerQueue];
|
||||
loggerQueue = logger.loggerQueue;
|
||||
}
|
||||
|
||||
if (loggerQueue == nil) {
|
||||
// Automatically create queue for the logger.
|
||||
// Use the logger name as the queue name if possible.
|
||||
|
||||
const char *loggerQueueName = NULL;
|
||||
|
||||
if ([logger respondsToSelector:@selector(loggerName)]) {
|
||||
loggerQueueName = [[logger loggerName] UTF8String];
|
||||
loggerQueueName = logger.loggerName.UTF8String;
|
||||
}
|
||||
|
||||
loggerQueue = dispatch_queue_create(loggerQueueName, NULL);
|
||||
|
@ -1000,8 +996,8 @@ NSString * __nullable DDExtractFileNameWithoutExtension(const char *filePath, BO
|
|||
return self;
|
||||
}
|
||||
|
||||
+ (DDLoggerNode *)nodeWithLogger:(id <DDLogger>)logger loggerQueue:(dispatch_queue_t)loggerQueue level:(DDLogLevel)level {
|
||||
return [[DDLoggerNode alloc] initWithLogger:logger loggerQueue:loggerQueue level:level];
|
||||
+ (instancetype)nodeWithLogger:(id <DDLogger>)logger loggerQueue:(dispatch_queue_t)loggerQueue level:(DDLogLevel)level {
|
||||
return [[self alloc] initWithLogger:logger loggerQueue:loggerQueue level:level];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
|
@ -1071,6 +1067,9 @@ NSString * __nullable DDExtractFileNameWithoutExtension(const char *filePath, BO
|
|||
|
||||
// Try to get the current queue's label
|
||||
_queueLabel = [[NSString alloc] initWithFormat:@"%s", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)];
|
||||
|
||||
if (@available(macOS 10.10, iOS 8.0, *))
|
||||
_qos = (NSUInteger) qos_class_self();
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -1092,6 +1091,7 @@ NSString * __nullable DDExtractFileNameWithoutExtension(const char *filePath, BO
|
|||
newMessage->_threadID = _threadID;
|
||||
newMessage->_threadName = _threadName;
|
||||
newMessage->_queueLabel = _queueLabel;
|
||||
newMessage->_qos = _qos;
|
||||
|
||||
return newMessage;
|
||||
}
|
||||
|
@ -1110,7 +1110,7 @@ NSString * __nullable DDExtractFileNameWithoutExtension(const char *filePath, BO
|
|||
const char *loggerQueueName = NULL;
|
||||
|
||||
if ([self respondsToSelector:@selector(loggerName)]) {
|
||||
loggerQueueName = [[self loggerName] UTF8String];
|
||||
loggerQueueName = self.loggerName.UTF8String;
|
||||
}
|
||||
|
||||
_loggerQueue = dispatch_queue_create(loggerQueueName, NULL);
|
||||
|
@ -1242,9 +1242,7 @@ NSString * __nullable DDExtractFileNameWithoutExtension(const char *filePath, BO
|
|||
}
|
||||
};
|
||||
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
|
||||
dispatch_async(globalLoggingQueue, ^{
|
||||
dispatch_async(DDLog.loggingQueue, ^{
|
||||
dispatch_async(self->_loggerQueue, block);
|
||||
});
|
||||
}
|
||||
|
@ -1293,8 +1291,8 @@ NSString * __nullable DDExtractFileNameWithoutExtension(const char *filePath, BO
|
|||
return self;
|
||||
}
|
||||
|
||||
+ (DDLoggerInformation *)informationWithLogger:(id <DDLogger>)logger andLevel:(DDLogLevel)level {
|
||||
return [[DDLoggerInformation alloc] initWithLogger:logger andLevel:level];
|
||||
+ (instancetype)informationWithLogger:(id <DDLogger>)logger andLevel:(DDLogLevel)level {
|
||||
return [[self alloc] initWithLogger:logger andLevel:level];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -21,9 +21,11 @@
|
|||
NSString *_subsystem;
|
||||
NSString *_category;
|
||||
}
|
||||
@property (copy, nonatomic, readonly) NSString *subsystem;
|
||||
@property (copy, nonatomic, readonly) NSString *category;
|
||||
@property (strong, nonatomic, readwrite) os_log_t logger;
|
||||
|
||||
@property (copy, nonatomic, readonly, nullable) NSString *subsystem;
|
||||
@property (copy, nonatomic, readonly, nullable) NSString *category;
|
||||
@property (strong, nonatomic, readwrite, nonnull) os_log_t logger;
|
||||
|
||||
@end
|
||||
|
||||
@implementation DDOSLogger
|
||||
|
@ -38,7 +40,7 @@
|
|||
* Swift: (String, String)?
|
||||
*/
|
||||
- (instancetype)initWithSubsystem:(NSString *)subsystem category:(NSString *)category {
|
||||
NSAssert((subsystem == nil) == (category == nil), @"Either both subsystem and category or neither can be nil.");
|
||||
NSAssert((subsystem == nil) == (category == nil), @"Either both subsystem and category or neither should be nil.");
|
||||
if (self = [super init]) {
|
||||
_subsystem = [subsystem copy];
|
||||
_category = [category copy];
|
||||
|
@ -68,9 +70,7 @@ static DDOSLogger *sharedInstance;
|
|||
if (self.subsystem == nil || self.category == nil) {
|
||||
return OS_LOG_DEFAULT;
|
||||
}
|
||||
__auto_type subdomain = self.subsystem.UTF8String;
|
||||
__auto_type category = self.category.UTF8String;
|
||||
return os_log_create(subdomain, category);
|
||||
return os_log_create(self.subsystem.UTF8String, self.category.UTF8String);
|
||||
}
|
||||
|
||||
- (os_log_t)logger {
|
||||
|
@ -82,14 +82,17 @@ static DDOSLogger *sharedInstance;
|
|||
|
||||
#pragma mark - DDLogger
|
||||
|
||||
- (DDLoggerName)loggerName {
|
||||
return DDLoggerNameOS;
|
||||
}
|
||||
|
||||
- (void)logMessage:(DDLogMessage *)logMessage {
|
||||
// Skip captured log messages
|
||||
if ([logMessage->_fileName isEqualToString:@"DDASLLogCapture"]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(@available(iOS 10.0, macOS 10.12, tvOS 10.0, watchOS 3.0, *)) {
|
||||
|
||||
if (@available(iOS 10.0, macOS 10.12, tvOS 10.0, watchOS 3.0, *)) {
|
||||
NSString * message = _logFormatter ? [_logFormatter formatLogMessage:logMessage] : logMessage->_message;
|
||||
if (message != nil) {
|
||||
const char *msg = [message UTF8String];
|
||||
|
@ -98,23 +101,18 @@ static DDOSLogger *sharedInstance;
|
|||
case DDLogFlagError :
|
||||
os_log_error(logger, "%{public}s", msg);
|
||||
break;
|
||||
case DDLogFlagWarning :
|
||||
case DDLogFlagWarning:
|
||||
case DDLogFlagInfo :
|
||||
os_log_info(logger, "%{public}s", msg);
|
||||
break;
|
||||
case DDLogFlagDebug :
|
||||
case DDLogFlagVerbose :
|
||||
case DDLogFlagVerbose:
|
||||
default :
|
||||
os_log_debug(logger, "%{public}s", msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (DDLoggerName)loggerName {
|
||||
return DDLoggerNameOS;
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -113,7 +113,7 @@ typedef struct {
|
|||
size_t resetCodeLen;
|
||||
}
|
||||
|
||||
- (instancetype)initWithForegroundColor:(DDColor *)fgColor backgroundColor:(DDColor *)bgColor flag:(DDLogFlag)mask context:(NSInteger)ctxt;
|
||||
- (nullable instancetype)initWithForegroundColor:(nullable DDColor *)fgColor backgroundColor:(nullable DDColor *)bgColor flag:(DDLogFlag)mask context:(NSInteger)ctxt;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -821,7 +821,7 @@ static DDTTYLogger *sharedInstance;
|
|||
NSLogInfo(@"DDTTYLogger: isaColor256TTY: %@", (isaColor256TTY ? @"YES" : @"NO"));
|
||||
NSLogInfo(@"DDTTYLogger: isaXcodeColorTTY: %@", (isaXcodeColorTTY ? @"YES" : @"NO"));
|
||||
|
||||
sharedInstance = [[[self class] alloc] init];
|
||||
sharedInstance = [[self alloc] init];
|
||||
});
|
||||
|
||||
return sharedInstance;
|
||||
|
@ -832,6 +832,10 @@ static DDTTYLogger *sharedInstance;
|
|||
return nil;
|
||||
}
|
||||
|
||||
if (@available(iOS 10.0, macOS 10.12, tvOS 10.0, watchOS 3.0, *)) {
|
||||
NSLogWarn(@"CocoaLumberjack: Warning: Usage of DDTTYLogger detected when DDOSLogger is available and can be used! Please consider migrating to DDOSLogger.");
|
||||
}
|
||||
|
||||
if ((self = [super init])) {
|
||||
// Initialize 'app' variable (char *)
|
||||
|
||||
|
@ -889,6 +893,10 @@ static DDTTYLogger *sharedInstance;
|
|||
return self;
|
||||
}
|
||||
|
||||
- (DDLoggerName)loggerName {
|
||||
return DDLoggerNameTTY;
|
||||
}
|
||||
|
||||
- (void)loadDefaultColorProfiles {
|
||||
[self setForegroundColor:DDMakeColor(214, 57, 30) backgroundColor:nil forFlag:DDLogFlagError];
|
||||
[self setForegroundColor:DDMakeColor(204, 121, 32) backgroundColor:nil forFlag:DDLogFlagWarning];
|
||||
|
@ -1366,10 +1374,6 @@ static DDTTYLogger *sharedInstance;
|
|||
}
|
||||
}
|
||||
|
||||
- (DDLoggerName)loggerName {
|
||||
return DDLoggerNameTTY;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -22,11 +22,11 @@
|
|||
|
||||
@interface DDLoggingContextSet : NSObject
|
||||
|
||||
@property (readonly, copy, nonnull) NSArray *currentSet;
|
||||
|
||||
- (void)addToSet:(NSInteger)loggingContext;
|
||||
- (void)removeFromSet:(NSInteger)loggingContext;
|
||||
|
||||
@property (readonly, copy) NSArray *currentSet;
|
||||
|
||||
- (BOOL)isInSet:(NSInteger)loggingContext;
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -15,19 +15,35 @@
|
|||
|
||||
#import <CocoaLumberjack/DDDispatchQueueLogFormatter.h>
|
||||
#import <pthread/pthread.h>
|
||||
#import <objc/runtime.h>
|
||||
#import <stdatomic.h>
|
||||
#import <sys/qos.h>
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
#error This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
|
||||
#endif
|
||||
|
||||
DDQualityOfServiceName const DDQualityOfServiceUserInteractive = @"UI";
|
||||
DDQualityOfServiceName const DDQualityOfServiceUserInitiated = @"IN";
|
||||
DDQualityOfServiceName const DDQualityOfServiceDefault = @"DF";
|
||||
DDQualityOfServiceName const DDQualityOfServiceUtility = @"UT";
|
||||
DDQualityOfServiceName const DDQualityOfServiceBackground = @"BG";
|
||||
DDQualityOfServiceName const DDQualityOfServiceUnspecified = @"UN";
|
||||
|
||||
static DDQualityOfServiceName _qos_name(NSUInteger qos) {
|
||||
switch ((qos_class_t) qos) {
|
||||
case QOS_CLASS_USER_INTERACTIVE: return DDQualityOfServiceUserInteractive;
|
||||
case QOS_CLASS_USER_INITIATED: return DDQualityOfServiceUserInitiated;
|
||||
case QOS_CLASS_DEFAULT: return DDQualityOfServiceDefault;
|
||||
case QOS_CLASS_UTILITY: return DDQualityOfServiceUtility;
|
||||
case QOS_CLASS_BACKGROUND: return DDQualityOfServiceBackground;
|
||||
default: return DDQualityOfServiceUnspecified;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - DDDispatchQueueLogFormatter
|
||||
|
||||
@interface DDDispatchQueueLogFormatter () {
|
||||
DDDispatchQueueLogFormatterMode _mode;
|
||||
NSString *_dateFormatterKey;
|
||||
DDAtomicCounter *_atomicLoggerCounter;
|
||||
NSDateFormatter *_threadUnsafeDateFormatter; // Use [self stringFromDate]
|
||||
NSDateFormatter *_dateFormatter; // Use [self stringFromDate]
|
||||
|
||||
pthread_mutex_t _mutex;
|
||||
|
||||
|
@ -43,31 +59,12 @@
|
|||
|
||||
- (instancetype)init {
|
||||
if ((self = [super init])) {
|
||||
_mode = DDDispatchQueueLogFormatterModeShareble;
|
||||
_dateFormatter = [self createDateFormatter];
|
||||
|
||||
// We need to carefully pick the name for storing in thread dictionary to not
|
||||
// use a formatter configured by subclass and avoid surprises.
|
||||
Class cls = [self class];
|
||||
Class superClass = class_getSuperclass(cls);
|
||||
SEL configMethodName = @selector(configureDateFormatter:);
|
||||
Method configMethod = class_getInstanceMethod(cls, configMethodName);
|
||||
while (class_getInstanceMethod(superClass, configMethodName) == configMethod) {
|
||||
cls = superClass;
|
||||
superClass = class_getSuperclass(cls);
|
||||
}
|
||||
// now `cls` is the class that provides implementation for `configureDateFormatter:`
|
||||
_dateFormatterKey = [NSString stringWithFormat:@"%s_NSDateFormatter", class_getName(cls)];
|
||||
|
||||
_atomicLoggerCounter = [[DDAtomicCounter alloc] initWithDefaultValue:0];
|
||||
_threadUnsafeDateFormatter = nil;
|
||||
|
||||
_minQueueLength = 0;
|
||||
_maxQueueLength = 0;
|
||||
pthread_mutex_init(&_mutex, NULL);
|
||||
_replacements = [[NSMutableDictionary alloc] init];
|
||||
|
||||
// Set default replacements:
|
||||
|
||||
_replacements[@"com.apple.main-thread"] = @"main";
|
||||
}
|
||||
|
||||
|
@ -75,10 +72,7 @@
|
|||
}
|
||||
|
||||
- (instancetype)initWithMode:(DDDispatchQueueLogFormatterMode)mode {
|
||||
if ((self = [self init])) {
|
||||
_mode = mode;
|
||||
}
|
||||
return self;
|
||||
return [self init];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
|
@ -130,39 +124,11 @@
|
|||
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
|
||||
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss:SSS"];
|
||||
[dateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]];
|
||||
|
||||
NSString *calendarIdentifier = NSCalendarIdentifierGregorian;
|
||||
|
||||
[dateFormatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:calendarIdentifier]];
|
||||
[dateFormatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]];
|
||||
}
|
||||
|
||||
- (NSString *)stringFromDate:(NSDate *)date {
|
||||
|
||||
NSDateFormatter *dateFormatter = nil;
|
||||
if (_mode == DDDispatchQueueLogFormatterModeNonShareble) {
|
||||
// Single-threaded mode.
|
||||
|
||||
dateFormatter = _threadUnsafeDateFormatter;
|
||||
if (dateFormatter == nil) {
|
||||
dateFormatter = [self createDateFormatter];
|
||||
_threadUnsafeDateFormatter = dateFormatter;
|
||||
}
|
||||
} else {
|
||||
// Multi-threaded mode.
|
||||
// NSDateFormatter is NOT thread-safe.
|
||||
|
||||
NSString *key = _dateFormatterKey;
|
||||
|
||||
NSMutableDictionary *threadDictionary = [[NSThread currentThread] threadDictionary];
|
||||
dateFormatter = threadDictionary[key];
|
||||
|
||||
if (dateFormatter == nil) {
|
||||
dateFormatter = [self createDateFormatter];
|
||||
threadDictionary[key] = dateFormatter;
|
||||
}
|
||||
}
|
||||
|
||||
return [dateFormatter stringFromDate:date];
|
||||
return [_dateFormatter stringFromDate:date];
|
||||
}
|
||||
|
||||
- (NSString *)queueThreadLabelForLogMessage:(DDLogMessage *)logMessage {
|
||||
|
@ -262,69 +228,44 @@
|
|||
NSString *timestamp = [self stringFromDate:(logMessage->_timestamp)];
|
||||
NSString *queueThreadLabel = [self queueThreadLabelForLogMessage:logMessage];
|
||||
|
||||
if (@available(macOS 10.10, iOS 8.0, *))
|
||||
return [NSString stringWithFormat:@"%@ [%@ (QOS:%@)] %@", timestamp, queueThreadLabel, _qos_name(logMessage->_qos), logMessage->_message];
|
||||
return [NSString stringWithFormat:@"%@ [%@] %@", timestamp, queueThreadLabel, logMessage->_message];
|
||||
}
|
||||
|
||||
- (void)didAddToLogger:(id <DDLogger> __attribute__((unused)))logger {
|
||||
NSAssert([_atomicLoggerCounter increment] <= 1 || _mode == DDDispatchQueueLogFormatterModeShareble, @"Can't reuse formatter with multiple loggers in non-shareable mode.");
|
||||
}
|
||||
|
||||
- (void)willRemoveFromLogger:(id <DDLogger> __attribute__((unused)))logger {
|
||||
[_atomicLoggerCounter decrement];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - DDAtomicCounter
|
||||
|
||||
#define DD_OSATOMIC_API_DEPRECATED (TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) || (TARGET_OS_IOS && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || (TARGET_OS_WATCH && __WATCH_OS_VERSION_MIN_REQUIRED >= 30000) || (TARGET_OS_TV && __TV_OS_VERSION_MIN_REQUIRED >= 100000)
|
||||
|
||||
#if DD_OSATOMIC_API_DEPRECATED
|
||||
#import <stdatomic.h>
|
||||
#else
|
||||
#import <libkern/OSAtomic.h>
|
||||
#endif
|
||||
|
||||
@interface DDAtomicCounter() {
|
||||
#if DD_OSATOMIC_API_DEPRECATED
|
||||
_Atomic(int32_t) _value;
|
||||
#else
|
||||
int32_t _value;
|
||||
#endif
|
||||
atomic_int_fast32_t _value;
|
||||
}
|
||||
@end
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
|
||||
@implementation DDAtomicCounter
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
- (instancetype)initWithDefaultValue:(int32_t)defaultValue {
|
||||
if ((self = [super init])) {
|
||||
_value = defaultValue;
|
||||
atomic_init(&_value, defaultValue);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (int32_t)value {
|
||||
return _value;
|
||||
return atomic_load_explicit(&_value, memory_order_relaxed);
|
||||
}
|
||||
|
||||
#if DD_OSATOMIC_API_DEPRECATED
|
||||
- (int32_t)increment {
|
||||
atomic_fetch_add_explicit(&_value, 1, memory_order_relaxed);
|
||||
return _value;
|
||||
int32_t old = atomic_fetch_add_explicit(&_value, 1, memory_order_relaxed);
|
||||
return (old + 1);
|
||||
}
|
||||
|
||||
- (int32_t)decrement {
|
||||
atomic_fetch_sub_explicit(&_value, 1, memory_order_relaxed);
|
||||
return _value;
|
||||
int32_t old = atomic_fetch_sub_explicit(&_value, 1, memory_order_relaxed);
|
||||
return (old - 1);
|
||||
}
|
||||
#else
|
||||
- (int32_t)increment {
|
||||
return OSAtomicIncrement32(&_value);
|
||||
}
|
||||
|
||||
- (int32_t)decrement {
|
||||
return OSAtomicDecrement32(&_value);
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -110,23 +110,27 @@ static NSUInteger DDGetDefaultBufferSizeBytes() {
|
|||
#pragma mark - Logging
|
||||
|
||||
- (void)logMessage:(DDLogMessage *)logMessage {
|
||||
// Don't need to check for isOnInternalLoggerQueue, -lt_dataForMessage: will do it for us.
|
||||
NSData *data = [_fileLogger lt_dataForMessage:logMessage];
|
||||
NSUInteger length = data.length;
|
||||
if (length == 0) {
|
||||
|
||||
if (data.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef DEBUG
|
||||
[data enumerateByteRangesUsingBlock:^(const void * __nonnull bytes, NSRange byteRange, BOOL * __nonnull __unused stop) {
|
||||
NSUInteger bytesLength = byteRange.length;
|
||||
#ifdef NS_BLOCK_ASSERTIONS
|
||||
__unused
|
||||
#endif
|
||||
NSInteger written = [_buffer write:[data bytes] maxLength:length];
|
||||
NSAssert(written == (NSInteger)length, @"Failed to write to memory buffer.");
|
||||
NSInteger written = [_buffer write:bytes maxLength:bytesLength];
|
||||
NSAssert(written > 0 && (NSUInteger)written == bytesLength, @"Failed to write to memory buffer.");
|
||||
|
||||
_currentBufferSizeBytes += length;
|
||||
_currentBufferSizeBytes += bytesLength;
|
||||
|
||||
if (_currentBufferSizeBytes >= _maxBufferSizeBytes) {
|
||||
[self lt_sendBufferedDataToFileLogger];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)flush {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -18,6 +18,8 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* This class represents an NSColor replacement for CLI projects that don't link with AppKit
|
||||
**/
|
||||
|
@ -31,7 +33,7 @@
|
|||
* @param blue blue channel, between 0 and 1
|
||||
* @param alpha alpha channel, between 0 and 1
|
||||
*/
|
||||
+ (CLIColor *)colorWithCalibratedRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
|
||||
+ (instancetype)colorWithCalibratedRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
|
||||
|
||||
/**
|
||||
* Get the RGBA components from a `CLIColor`
|
||||
|
@ -41,8 +43,10 @@
|
|||
* @param blue blue channel, between 0 and 1
|
||||
* @param alpha alpha channel, between 0 and 1
|
||||
*/
|
||||
- (void)getRed:(CGFloat *)red green:(CGFloat *)green blue:(CGFloat *)blue alpha:(CGFloat *)alpha NS_SWIFT_NAME(get(red:green:blue:alpha:));
|
||||
- (void)getRed:(nullable CGFloat *)red green:(nullable CGFloat *)green blue:(nullable CGFloat *)blue alpha:(nullable CGFloat *)alpha NS_SWIFT_NAME(get(red:green:blue:alpha:));
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -17,6 +17,8 @@
|
|||
|
||||
@protocol DDLogger;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* This class provides the ability to capture the ASL (Apple System Logs)
|
||||
*/
|
||||
|
@ -40,3 +42,5 @@ API_DEPRECATED("Use DDOSLogger instead", macosx(10.4,10.12), ios(2.0,10.0), watc
|
|||
@property (class) DDLogLevel captureLevel;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -22,6 +22,8 @@
|
|||
|
||||
#import <CocoaLumberjack/DDLog.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Custom key set on messages sent to ASL
|
||||
extern const char* const kDDASLKeyDDLog;
|
||||
|
||||
|
@ -49,7 +51,7 @@ API_DEPRECATED("Use DDOSLogger instead", macosx(10.4,10.12), ios(2.0,10.0), watc
|
|||
*
|
||||
* @return the shared instance
|
||||
*/
|
||||
@property (class, readonly, strong) DDASLLogger *sharedInstance;
|
||||
@property (nonatomic, class, readonly, strong) DDASLLogger *sharedInstance;
|
||||
|
||||
// Inherited from DDAbstractLogger
|
||||
|
||||
|
@ -57,3 +59,5 @@ API_DEPRECATED("Use DDOSLogger instead", macosx(10.4,10.12), ios(2.0,10.0), watc
|
|||
// - (void)setLogFormatter:(id <DDLogFormatter>)formatter;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -20,6 +20,8 @@
|
|||
|
||||
#import <CocoaLumberjack/DDLog.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* This class provides an abstract implementation of a database logger.
|
||||
*
|
||||
|
@ -121,3 +123,5 @@
|
|||
- (void)deleteOldLogEntries;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -23,4 +23,3 @@
|
|||
NSAssert(NO, @"%@", description); \
|
||||
}
|
||||
#define DDAssertCondition(condition) DDAssert(condition, @"Condition not satisfied: %s", #condition)
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -22,6 +22,8 @@
|
|||
|
||||
#import <CocoaLumberjack/DDLog.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* This class provides a log formatter that filters log statements from a logging context not on the whitelist.
|
||||
*
|
||||
|
@ -65,7 +67,7 @@
|
|||
/**
|
||||
* Return the whitelist
|
||||
*/
|
||||
@property (readonly, copy) NSArray<NSNumber *> *whitelist;
|
||||
@property (nonatomic, readonly, copy) NSArray<NSNumber *> *whitelist;
|
||||
|
||||
/**
|
||||
* Check if a context is on the whitelist
|
||||
|
@ -115,3 +117,5 @@
|
|||
- (BOOL)isOnBlacklist:(NSInteger)loggingContext;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -22,9 +22,12 @@
|
|||
|
||||
#import <CocoaLumberjack/DDLog.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* Log formatter mode
|
||||
*/
|
||||
__attribute__((deprecated("DDDispatchQueueLogFormatter is always shareable")))
|
||||
typedef NS_ENUM(NSUInteger, DDDispatchQueueLogFormatterMode){
|
||||
/**
|
||||
* This is the default option, means the formatter can be reused between multiple loggers and therefore is thread-safe.
|
||||
|
@ -38,6 +41,36 @@ typedef NS_ENUM(NSUInteger, DDDispatchQueueLogFormatterMode){
|
|||
DDDispatchQueueLogFormatterModeNonShareble,
|
||||
};
|
||||
|
||||
/**
|
||||
* Quality of Service names.
|
||||
*
|
||||
* Since macOS 10.10 and iOS 8.0, pthreads, dispatch queues and NSOperations express their
|
||||
* scheduling priority by using an abstract classification called Quality of Service (QOS).
|
||||
*
|
||||
* This formatter will add a representation of this QOS in the log message by using those
|
||||
* string constants.
|
||||
* For example:
|
||||
*
|
||||
* `2011-10-17 20:21:45.435 AppName[19928:5207 (QOS:DF)] Your log message here`
|
||||
*
|
||||
* Where QOS is one of:
|
||||
* `- UI = User Interactive`
|
||||
* `- IN = User Initiated`
|
||||
* `- DF = Default`
|
||||
* `- UT = Utility`
|
||||
* `- BG = Background`
|
||||
* `- UN = Unspecified`
|
||||
*
|
||||
* Note: QOS will be absent in the log messages if running on OS versions that don't support it.
|
||||
**/
|
||||
typedef NSString * DDQualityOfServiceName NS_EXTENSIBLE_STRING_ENUM;
|
||||
|
||||
FOUNDATION_EXPORT DDQualityOfServiceName const DDQualityOfServiceUserInteractive API_AVAILABLE(macos(10.10), ios(8.0));
|
||||
FOUNDATION_EXPORT DDQualityOfServiceName const DDQualityOfServiceUserInitiated API_AVAILABLE(macos(10.10), ios(8.0));
|
||||
FOUNDATION_EXPORT DDQualityOfServiceName const DDQualityOfServiceDefault API_AVAILABLE(macos(10.10), ios(8.0));
|
||||
FOUNDATION_EXPORT DDQualityOfServiceName const DDQualityOfServiceUtility API_AVAILABLE(macos(10.10), ios(8.0));
|
||||
FOUNDATION_EXPORT DDQualityOfServiceName const DDQualityOfServiceBackground API_AVAILABLE(macos(10.10), ios(8.0));
|
||||
FOUNDATION_EXPORT DDQualityOfServiceName const DDQualityOfServiceUnspecified API_AVAILABLE(macos(10.10), ios(8.0));
|
||||
|
||||
/**
|
||||
* This class provides a log formatter that prints the dispatch_queue label instead of the mach_thread_id.
|
||||
|
@ -89,7 +122,7 @@ typedef NS_ENUM(NSUInteger, DDDispatchQueueLogFormatterMode){
|
|||
*
|
||||
* @param mode choose between DDDispatchQueueLogFormatterModeShareble and DDDispatchQueueLogFormatterModeNonShareble, depending if the formatter is shared between several loggers or not
|
||||
*/
|
||||
- (instancetype)initWithMode:(DDDispatchQueueLogFormatterMode)mode;
|
||||
- (instancetype)initWithMode:(DDDispatchQueueLogFormatterMode)mode __attribute__((deprecated("DDDispatchQueueLogFormatter is always shareable")));
|
||||
|
||||
/**
|
||||
* The minQueueLength restricts the minimum size of the [detail box].
|
||||
|
@ -140,12 +173,12 @@ typedef NS_ENUM(NSUInteger, DDDispatchQueueLogFormatterMode){
|
|||
*
|
||||
* To remove/undo a previous replacement, invoke this method with nil for the 'shortLabel' parameter.
|
||||
**/
|
||||
- (NSString *)replacementStringForQueueLabel:(NSString *)longLabel;
|
||||
- (nullable NSString *)replacementStringForQueueLabel:(NSString *)longLabel;
|
||||
|
||||
/**
|
||||
* See the `replacementStringForQueueLabel:` description
|
||||
*/
|
||||
- (void)setReplacementString:(NSString *)shortLabel forQueueLabel:(NSString *)longLabel;
|
||||
- (void)setReplacementString:(nullable NSString *)shortLabel forQueueLabel:(NSString *)longLabel;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -176,8 +209,9 @@ typedef NS_ENUM(NSUInteger, DDDispatchQueueLogFormatterMode){
|
|||
|
||||
@end
|
||||
|
||||
#pragma mark - DDAtomicCounter
|
||||
#pragma mark - DDAtomicCountable
|
||||
|
||||
__attribute__((deprecated("DDAtomicCountable is useless since DDDispatchQueueLogFormatter is always shareable now")))
|
||||
@protocol DDAtomicCountable <NSObject>
|
||||
|
||||
- (instancetype)initWithDefaultValue:(int32_t)defaultValue;
|
||||
|
@ -187,5 +221,8 @@ typedef NS_ENUM(NSUInteger, DDDispatchQueueLogFormatterMode){
|
|||
|
||||
@end
|
||||
|
||||
__attribute__((deprecated("DDAtomicCountable is deprecated")))
|
||||
@interface DDAtomicCounter: NSObject<DDAtomicCountable>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -20,10 +20,10 @@
|
|||
|
||||
#import <CocoaLumberjack/DDLog.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class DDLogFileInfo;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* This class provides a logger to write log statements to a file.
|
||||
**/
|
||||
|
@ -148,10 +148,17 @@ extern unsigned long long const kDDDefaultLogFilesDiskQuota;
|
|||
* This method is executed directly on the file logger's internal queue.
|
||||
* The file has to exist by the time the method returns.
|
||||
**/
|
||||
- (NSString *)createNewLogFile;
|
||||
- (nullable NSString *)createNewLogFileWithError:(NSError **)error;
|
||||
|
||||
@optional
|
||||
|
||||
// Private methods (only to be used by DDFileLogger)
|
||||
/**
|
||||
* Creates a new log file ignoring any errors. Deprecated in favor of `-createNewLogFileWithError:`.
|
||||
* Will only be called if `-createNewLogFileWithError:` is not implemented.
|
||||
**/
|
||||
- (nullable NSString *)createNewLogFile __attribute__((deprecated("Use -createNewLogFileWithError:"))) NS_SWIFT_UNAVAILABLE("Use -createNewLogFileWithError:");
|
||||
|
||||
// Notifications from DDFileLogger
|
||||
|
||||
/**
|
||||
|
@ -195,7 +202,7 @@ extern unsigned long long const kDDDefaultLogFilesDiskQuota;
|
|||
* If logDirectory is not specified, then a folder called "Logs" is created in the app's cache directory.
|
||||
* While running on the simulator, the "Logs" folder is located in the library temporary directory.
|
||||
*/
|
||||
- (instancetype)initWithLogsDirectory:(NSString * __nullable)logsDirectory NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithLogsDirectory:(nullable NSString *)logsDirectory NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
/*
|
||||
|
@ -209,7 +216,7 @@ extern unsigned long long const kDDDefaultLogFilesDiskQuota;
|
|||
* null
|
||||
* cy#
|
||||
**/
|
||||
- (instancetype)initWithLogsDirectory:(NSString * __nullable)logsDirectory
|
||||
- (instancetype)initWithLogsDirectory:(nullable NSString *)logsDirectory
|
||||
defaultFileProtectionLevel:(NSFileProtectionType)fileProtectionLevel;
|
||||
#endif
|
||||
|
||||
|
@ -306,7 +313,7 @@ extern unsigned long long const kDDDefaultLogFilesDiskQuota;
|
|||
/**
|
||||
* Designated initializer, requires a date formatter
|
||||
*/
|
||||
- (instancetype)initWithDateFormatter:(NSDateFormatter * __nullable)dateFormatter NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithDateFormatter:(nullable NSDateFormatter *)dateFormatter NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -329,15 +336,15 @@ extern unsigned long long const kDDDefaultLogFilesDiskQuota;
|
|||
* A global queue w/ default priority is used to run callbacks.
|
||||
* If needed, specify queue using `initWithLogFileManager:completionQueue:`.
|
||||
*/
|
||||
- (instancetype)initWithLogFileManager:(id <DDLogFileManager> __nullable)logFileManager;
|
||||
- (instancetype)initWithLogFileManager:(id <DDLogFileManager>)logFileManager;
|
||||
|
||||
/**
|
||||
* Designated initializer, requires a `DDLogFileManager` instance.
|
||||
* The completionQueue is used to execute `didArchiveLogFile`, `didRollAndArchiveLogFile`,
|
||||
* and the callback in `rollLog`. If nil, a global queue w/ default priority is used.
|
||||
*/
|
||||
- (instancetype)initWithLogFileManager:(id <DDLogFileManager> __nullable)logFileManager
|
||||
completionQueue:(dispatch_queue_t __nullable)dispatchQueue NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithLogFileManager:(id <DDLogFileManager>)logFileManager
|
||||
completionQueue:(nullable dispatch_queue_t)dispatchQueue NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Deprecated. Use `willLogMessage:`
|
||||
|
@ -437,14 +444,14 @@ extern unsigned long long const kDDDefaultLogFilesDiskQuota;
|
|||
* You can optionally force the current log file to be rolled with this method.
|
||||
* CompletionBlock will be called on main queue.
|
||||
*/
|
||||
- (void)rollLogFileWithCompletionBlock:(void (^ __nullable)(void))completionBlock
|
||||
- (void)rollLogFileWithCompletionBlock:(nullable void (^)(void))completionBlock
|
||||
NS_SWIFT_NAME(rollLogFile(withCompletion:));
|
||||
|
||||
/**
|
||||
* Method is deprecated.
|
||||
* @deprecated Use `rollLogFileWithCompletionBlock:` method instead.
|
||||
*/
|
||||
- (void)rollLogFile __attribute((deprecated));
|
||||
- (void)rollLogFile __attribute__((deprecated("Use -rollLogFileWithCompletionBlock:")));
|
||||
|
||||
// Inherited from DDAbstractLogger
|
||||
|
||||
|
@ -456,9 +463,9 @@ extern unsigned long long const kDDDefaultLogFilesDiskQuota;
|
|||
* If there is an existing log file that is suitable,
|
||||
* within the constraints of `maximumFileSize` and `rollingFrequency`, then it is returned.
|
||||
*
|
||||
* Otherwise a new file is created and returned.
|
||||
* Otherwise a new file is created and returned. If this failes, `NULL` is returned.
|
||||
**/
|
||||
@property (nonatomic, readonly, strong) DDLogFileInfo *currentLogFileInfo;
|
||||
@property (nonatomic, nullable, readonly, strong) DDLogFileInfo *currentLogFileInfo;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -485,14 +492,10 @@ extern unsigned long long const kDDDefaultLogFilesDiskQuota;
|
|||
@property (strong, nonatomic, readonly) NSString *filePath;
|
||||
@property (strong, nonatomic, readonly) NSString *fileName;
|
||||
|
||||
#if FOUNDATION_SWIFT_SDK_EPOCH_AT_LEAST(8)
|
||||
@property (strong, nonatomic, readonly) NSDictionary<NSFileAttributeKey, id> *fileAttributes;
|
||||
#else
|
||||
@property (strong, nonatomic, readonly) NSDictionary<NSString *, id> *fileAttributes;
|
||||
#endif
|
||||
|
||||
@property (strong, nonatomic, readonly) NSDate *creationDate;
|
||||
@property (strong, nonatomic, readonly) NSDate *modificationDate;
|
||||
@property (strong, nonatomic, nullable, readonly) NSDate *creationDate;
|
||||
@property (strong, nonatomic, nullable, readonly) NSDate *modificationDate;
|
||||
|
||||
@property (nonatomic, readonly) unsigned long long fileSize;
|
||||
|
||||
|
@ -500,7 +503,7 @@ extern unsigned long long const kDDDefaultLogFilesDiskQuota;
|
|||
|
||||
@property (nonatomic, readwrite) BOOL isArchived;
|
||||
|
||||
+ (instancetype)logFileWithPath:(NSString *)filePath NS_SWIFT_UNAVAILABLE("Use init(filePath:)");
|
||||
+ (nullable instancetype)logFileWithPath:(nullable NSString *)filePath NS_SWIFT_UNAVAILABLE("Use init(filePath:)");
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (instancetype)initWithFilePath:(NSString *)filePath NS_DESIGNATED_INITIALIZER;
|
||||
|
@ -508,45 +511,11 @@ extern unsigned long long const kDDDefaultLogFilesDiskQuota;
|
|||
- (void)reset;
|
||||
- (void)renameFile:(NSString *)newFileName NS_SWIFT_NAME(renameFile(to:));
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
|
||||
// So here's the situation.
|
||||
// Extended attributes are perfect for what we're trying to do here (marking files as archived).
|
||||
// This is exactly what extended attributes were designed for.
|
||||
//
|
||||
// But Apple screws us over on the simulator.
|
||||
// Everytime you build-and-go, they copy the application into a new folder on the hard drive,
|
||||
// and as part of the process they strip extended attributes from our log files.
|
||||
// Normally, a copy of a file preserves extended attributes.
|
||||
// So obviously Apple has gone to great lengths to piss us off.
|
||||
//
|
||||
// Thus we use a slightly different tactic for marking log files as archived in the simulator.
|
||||
// That way it "just works" and there's no confusion when testing.
|
||||
//
|
||||
// The difference in method names is indicative of the difference in functionality.
|
||||
// On the simulator we add an attribute by appending a filename extension.
|
||||
//
|
||||
// For example:
|
||||
// "mylog.txt" -> "mylog.archived.txt"
|
||||
// "mylog" -> "mylog.archived"
|
||||
|
||||
- (BOOL)hasExtensionAttributeWithName:(NSString *)attrName;
|
||||
|
||||
- (void)addExtensionAttributeWithName:(NSString *)attrName;
|
||||
- (void)removeExtensionAttributeWithName:(NSString *)attrName;
|
||||
|
||||
#else /* if TARGET_IPHONE_SIMULATOR */
|
||||
|
||||
// Normal use of extended attributes used everywhere else,
|
||||
// such as on Macs and on iPhone devices.
|
||||
|
||||
- (BOOL)hasExtendedAttributeWithName:(NSString *)attrName;
|
||||
|
||||
- (void)addExtendedAttributeWithName:(NSString *)attrName;
|
||||
- (void)removeExtendedAttributeWithName:(NSString *)attrName;
|
||||
|
||||
#endif /* if TARGET_IPHONE_SIMULATOR */
|
||||
|
||||
- (NSComparisonResult)reverseCompareByCreationDate:(DDLogFileInfo *)another;
|
||||
- (NSComparisonResult)reverseCompareByModificationDate:(DDLogFileInfo *)another;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -80,4 +80,3 @@
|
|||
#define DDLogVInfo(frmt, avalist) LOGV_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagInfo, 0, nil, __PRETTY_FUNCTION__, frmt, avalist)
|
||||
#define DDLogVDebug(frmt, avalist) LOGV_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagDebug, 0, nil, __PRETTY_FUNCTION__, frmt, avalist)
|
||||
#define DDLogVVerbose(frmt, avalist) LOGV_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagVerbose, 0, nil, __PRETTY_FUNCTION__, frmt, avalist)
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -39,6 +39,8 @@
|
|||
@protocol DDLogger;
|
||||
@protocol DDLogFormatter;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* Define the standard options.
|
||||
*
|
||||
|
@ -173,8 +175,6 @@ typedef NS_ENUM(NSUInteger, DDLogLevel){
|
|||
DDLogLevelAll = NSUIntegerMax
|
||||
};
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* Extracts just the file name, no path or extension
|
||||
*
|
||||
|
@ -247,9 +247,9 @@ FOUNDATION_EXTERN NSString * __nullable DDExtractFileNameWithoutExtension(const
|
|||
flag:(DDLogFlag)flag
|
||||
context:(NSInteger)context
|
||||
file:(const char *)file
|
||||
function:(const char *)function
|
||||
function:(nullable const char *)function
|
||||
line:(NSUInteger)line
|
||||
tag:(id __nullable)tag
|
||||
tag:(nullable id)tag
|
||||
format:(NSString *)format, ... NS_FORMAT_FUNCTION(9,10);
|
||||
|
||||
/**
|
||||
|
@ -273,9 +273,9 @@ FOUNDATION_EXTERN NSString * __nullable DDExtractFileNameWithoutExtension(const
|
|||
flag:(DDLogFlag)flag
|
||||
context:(NSInteger)context
|
||||
file:(const char *)file
|
||||
function:(const char *)function
|
||||
function:(nullable const char *)function
|
||||
line:(NSUInteger)line
|
||||
tag:(id __nullable)tag
|
||||
tag:(nullable id)tag
|
||||
format:(NSString *)format, ... NS_FORMAT_FUNCTION(9,10);
|
||||
|
||||
/**
|
||||
|
@ -300,9 +300,9 @@ FOUNDATION_EXTERN NSString * __nullable DDExtractFileNameWithoutExtension(const
|
|||
flag:(DDLogFlag)flag
|
||||
context:(NSInteger)context
|
||||
file:(const char *)file
|
||||
function:(const char *)function
|
||||
function:(nullable const char *)function
|
||||
line:(NSUInteger)line
|
||||
tag:(id __nullable)tag
|
||||
tag:(nullable id)tag
|
||||
format:(NSString *)format
|
||||
args:(va_list)argList NS_SWIFT_NAME(log(asynchronous:level:flag:context:file:function:line:tag:format:arguments:));
|
||||
|
||||
|
@ -328,9 +328,9 @@ FOUNDATION_EXTERN NSString * __nullable DDExtractFileNameWithoutExtension(const
|
|||
flag:(DDLogFlag)flag
|
||||
context:(NSInteger)context
|
||||
file:(const char *)file
|
||||
function:(const char *)function
|
||||
function:(nullable const char *)function
|
||||
line:(NSUInteger)line
|
||||
tag:(id __nullable)tag
|
||||
tag:(nullable id)tag
|
||||
format:(NSString *)format
|
||||
args:(va_list)argList NS_SWIFT_NAME(log(asynchronous:level:flag:context:file:function:line:tag:format:arguments:));
|
||||
|
||||
|
@ -581,7 +581,7 @@ FOUNDATION_EXTERN NSString * __nullable DDExtractFileNameWithoutExtension(const
|
|||
* If no formatter is set, the logger simply logs the message as it is given in logMessage,
|
||||
* or it may use its own built in formatting style.
|
||||
**/
|
||||
@property (nonatomic, strong) id <DDLogFormatter> logFormatter;
|
||||
@property (nonatomic, strong, nullable) id <DDLogFormatter> logFormatter;
|
||||
|
||||
@optional
|
||||
|
||||
|
@ -666,7 +666,7 @@ FOUNDATION_EXTERN NSString * __nullable DDExtractFileNameWithoutExtension(const
|
|||
* The formatter may also optionally filter the log message by returning nil,
|
||||
* in which case the logger will not log the message.
|
||||
**/
|
||||
- (NSString * __nullable)formatLogMessage:(DDLogMessage *)logMessage NS_SWIFT_NAME(format(message:));
|
||||
- (nullable NSString *)formatLogMessage:(DDLogMessage *)logMessage NS_SWIFT_NAME(format(message:));
|
||||
|
||||
@optional
|
||||
|
||||
|
@ -676,7 +676,7 @@ FOUNDATION_EXTERN NSString * __nullable DDExtractFileNameWithoutExtension(const
|
|||
*
|
||||
* This is primarily for thread-safety.
|
||||
* If a formatter is explicitly not thread-safe, it may wish to throw an exception if added to multiple loggers.
|
||||
* Or if a formatter has potentially thread-unsafe code (e.g. NSDateFormatter),
|
||||
* Or if a formatter has potentially thread-unsafe code (e.g. NSDateFormatter with 10.0 behavior),
|
||||
* it could possibly use these hooks to switch to thread-safe versions of the code.
|
||||
**/
|
||||
- (void)didAddToLogger:(id <DDLogger>)logger;
|
||||
|
@ -687,7 +687,7 @@ FOUNDATION_EXTERN NSString * __nullable DDExtractFileNameWithoutExtension(const
|
|||
*
|
||||
* This is primarily for thread-safety.
|
||||
* If a formatter is explicitly not thread-safe, it may wish to throw an exception if added to multiple loggers.
|
||||
* Or if a formatter has potentially thread-unsafe code (e.g. NSDateFormatter),
|
||||
* Or if a formatter has potentially thread-unsafe code (e.g. NSDateFormatter with 10.0 behavior),
|
||||
* it could possibly use these hooks to switch to thread-safe versions of the code or use dispatch_set_specific()
|
||||
.* to add its own specific values.
|
||||
**/
|
||||
|
@ -780,10 +780,11 @@ typedef NS_OPTIONS(NSInteger, DDLogMessageOptions){
|
|||
NSUInteger _line;
|
||||
id _tag;
|
||||
DDLogMessageOptions _options;
|
||||
NSDate *_timestamp;
|
||||
NSDate * _timestamp;
|
||||
NSString *_threadID;
|
||||
NSString *_threadName;
|
||||
NSString *_queueLabel;
|
||||
NSUInteger _qos;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -823,11 +824,11 @@ typedef NS_OPTIONS(NSInteger, DDLogMessageOptions){
|
|||
flag:(DDLogFlag)flag
|
||||
context:(NSInteger)context
|
||||
file:(NSString *)file
|
||||
function:(NSString * __nullable)function
|
||||
function:(nullable NSString *)function
|
||||
line:(NSUInteger)line
|
||||
tag:(id __nullable)tag
|
||||
tag:(nullable id)tag
|
||||
options:(DDLogMessageOptions)options
|
||||
timestamp:(NSDate * __nullable)timestamp NS_DESIGNATED_INITIALIZER;
|
||||
timestamp:(nullable NSDate *)timestamp NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Read-only properties
|
||||
|
@ -842,14 +843,15 @@ typedef NS_OPTIONS(NSInteger, DDLogMessageOptions){
|
|||
@property (readonly, nonatomic) NSInteger context;
|
||||
@property (readonly, nonatomic) NSString *file;
|
||||
@property (readonly, nonatomic) NSString *fileName;
|
||||
@property (readonly, nonatomic) NSString * __nullable function;
|
||||
@property (readonly, nonatomic, nullable) NSString * function;
|
||||
@property (readonly, nonatomic) NSUInteger line;
|
||||
@property (readonly, nonatomic) id __nullable tag;
|
||||
@property (readonly, nonatomic, nullable) id tag;
|
||||
@property (readonly, nonatomic) DDLogMessageOptions options;
|
||||
@property (readonly, nonatomic) NSDate *timestamp;
|
||||
@property (readonly, nonatomic) NSString *threadID; // ID as it appears in NSLog calculated from the machThreadID
|
||||
@property (readonly, nonatomic) NSString *threadName;
|
||||
@property (readonly, nonatomic, nullable) NSString *threadName;
|
||||
@property (readonly, nonatomic) NSString *queueLabel;
|
||||
@property (readonly, nonatomic) NSUInteger qos API_AVAILABLE(macos(10.10), ios(8.0));
|
||||
|
||||
@end
|
||||
|
||||
|
@ -907,7 +909,7 @@ typedef NS_OPTIONS(NSInteger, DDLogMessageOptions){
|
|||
@property (nonatomic, readonly) id <DDLogger> logger;
|
||||
@property (nonatomic, readonly) DDLogLevel level;
|
||||
|
||||
+ (DDLoggerInformation *)informationWithLogger:(id <DDLogger>)logger
|
||||
+ (instancetype)informationWithLogger:(id <DDLogger>)logger
|
||||
andLevel:(DDLogLevel)level;
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -18,9 +18,13 @@
|
|||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NSString *DDLoggerName NS_TYPED_EXTENSIBLE_ENUM;
|
||||
FOUNDATION_EXPORT DDLoggerName const DDLoggerNameASL NS_SWIFT_NAME(DDLoggerName.asl); // DDASLLogger
|
||||
FOUNDATION_EXPORT DDLoggerName const DDLoggerNameTTY NS_SWIFT_NAME(DDLoggerName.tty); // DDTTYLogger
|
||||
|
||||
FOUNDATION_EXPORT DDLoggerName const DDLoggerNameOS NS_SWIFT_NAME(DDLoggerName.os); // DDOSLogger
|
||||
FOUNDATION_EXPORT DDLoggerName const DDLoggerNameFile NS_SWIFT_NAME(DDLoggerName.file); // DDFileLogger
|
||||
|
||||
FOUNDATION_EXPORT DDLoggerName const DDLoggerNameTTY NS_SWIFT_NAME(DDLoggerName.tty); // DDTTYLogger
|
||||
|
||||
API_DEPRECATED("Use DDOSLogger instead", macosx(10.4, 10.12), ios(2.0, 10.0), watchos(2.0, 3.0), tvos(9.0, 10.0))
|
||||
FOUNDATION_EXPORT DDLoggerName const DDLoggerNameASL NS_SWIFT_NAME(DDLoggerName.asl); // DDASLLogger
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -22,6 +22,8 @@
|
|||
|
||||
#import <CocoaLumberjack/DDLog.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* This formatter can be used to chain different formatters together.
|
||||
* The log message will processed in the order of the formatters added.
|
||||
|
@ -31,7 +33,7 @@
|
|||
/**
|
||||
* Array of chained formatters
|
||||
*/
|
||||
@property (readonly) NSArray<id<DDLogFormatter>> *formatters;
|
||||
@property (nonatomic, readonly) NSArray<id<DDLogFormatter>> *formatters;
|
||||
|
||||
/**
|
||||
* Add a new formatter
|
||||
|
@ -54,3 +56,5 @@
|
|||
- (BOOL)isFormattingWithFormatter:(id<DDLogFormatter>)formatter;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -22,6 +22,8 @@
|
|||
|
||||
#import <CocoaLumberjack/DDLog.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* This class provides a logger for the Apple os_log facility.
|
||||
**/
|
||||
|
@ -33,18 +35,21 @@ API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0))
|
|||
*
|
||||
* @return the shared instance with OS_LOG_DEFAULT.
|
||||
*/
|
||||
@property (class, readonly, strong) DDOSLogger *sharedInstance;
|
||||
@property (nonatomic, class, readonly, strong) DDOSLogger *sharedInstance;
|
||||
|
||||
/**
|
||||
Designed initializer
|
||||
Designated initializer
|
||||
|
||||
@param subsystem Desired subsystem in log. Consider "org.example"
|
||||
@param category Desired category in log. Consider "Point of interests."
|
||||
@param subsystem Desired subsystem in log. E.g. "org.example"
|
||||
@param category Desired category in log. E.g. "Point of interests."
|
||||
@return New instance of DDOSLogger.
|
||||
|
||||
@discussion This method accepts parameters of type (String, String)?
|
||||
If both parameters are nil, this method will return logger wrapper for `OS_LOG_DEFAULT`.
|
||||
If both parameters are not nil, it will return logger wrapper for `os_log_create(subsystem, category)`
|
||||
@discussion This method requires either both or no parameter to be set. Much like `(String, String)?` in Swift.
|
||||
If both parameters are nil, this method will return a logger configured with `OS_LOG_DEFAULT`.
|
||||
If both parameters are non-nil, it will return a logger configured with `os_log_create(subsystem, category)`
|
||||
*/
|
||||
- (instancetype)initWithSubsystem:(NSString *)subsystem category:(NSString *)category NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithSubsystem:(nullable NSString *)subsystem category:(nullable NSString *)category NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -28,20 +28,21 @@
|
|||
// iOS or tvOS or watchOS
|
||||
#import <UIKit/UIColor.h>
|
||||
typedef UIColor DDColor;
|
||||
static inline DDColor* DDMakeColor(CGFloat r, CGFloat g, CGFloat b) {return [DDColor colorWithRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f];}
|
||||
static inline DDColor* _Nonnull DDMakeColor(CGFloat r, CGFloat g, CGFloat b) {return [DDColor colorWithRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f];}
|
||||
#elif defined(DD_CLI) || !__has_include(<AppKit/NSColor.h>)
|
||||
// OS X CLI
|
||||
#import <CocoaLumberjack/CLIColor.h>
|
||||
typedef CLIColor DDColor;
|
||||
static inline DDColor* DDMakeColor(CGFloat r, CGFloat g, CGFloat b) {return [DDColor colorWithCalibratedRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f];}
|
||||
static inline DDColor* _Nonnull DDMakeColor(CGFloat r, CGFloat g, CGFloat b) {return [DDColor colorWithCalibratedRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f];}
|
||||
#else
|
||||
// OS X with AppKit
|
||||
#import <AppKit/NSColor.h>
|
||||
typedef NSColor DDColor;
|
||||
static inline DDColor* DDMakeColor(CGFloat r, CGFloat g, CGFloat b) {return [DDColor colorWithCalibratedRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f];}
|
||||
static inline DDColor * _Nonnull DDMakeColor(CGFloat r, CGFloat g, CGFloat b) {return [DDColor colorWithCalibratedRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f];}
|
||||
#endif
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* This class provides a logger for Terminal output or Xcode console output,
|
||||
|
@ -60,9 +61,9 @@
|
|||
@interface DDTTYLogger : DDAbstractLogger <DDLogger>
|
||||
|
||||
/**
|
||||
* Singleton method
|
||||
* Singleton instance. Returns `nil` if the initialization of the DDTTYLogger fails.
|
||||
*/
|
||||
@property (class, readonly, strong) DDTTYLogger *sharedInstance;
|
||||
@property (nonatomic, class, readonly, strong, nullable) DDTTYLogger *sharedInstance;
|
||||
|
||||
/* Inherited from the DDLogger protocol:
|
||||
*
|
||||
|
@ -103,6 +104,11 @@
|
|||
**/
|
||||
@property (nonatomic, readwrite, assign) BOOL automaticallyAppendNewlineForCustomFormatters;
|
||||
|
||||
/**
|
||||
Using this initializer is not supported. Please use `DDTTYLogger.sharedInstance`.
|
||||
**/
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* The default color set (foregroundColor, backgroundColor) is:
|
||||
*
|
||||
|
@ -125,7 +131,7 @@
|
|||
*
|
||||
* This method invokes setForegroundColor:backgroundColor:forFlag:context: and applies it to `LOG_CONTEXT_ALL`.
|
||||
**/
|
||||
- (void)setForegroundColor:(DDColor *)txtColor backgroundColor:(DDColor *)bgColor forFlag:(DDLogFlag)mask;
|
||||
- (void)setForegroundColor:(nullable DDColor *)txtColor backgroundColor:(nullable DDColor *)bgColor forFlag:(DDLogFlag)mask;
|
||||
|
||||
/**
|
||||
* Just like setForegroundColor:backgroundColor:flag, but allows you to specify a particular logging context.
|
||||
|
@ -138,7 +144,7 @@
|
|||
* Logging context's are explained in further detail here:
|
||||
* Documentation/CustomContext.md
|
||||
**/
|
||||
- (void)setForegroundColor:(DDColor *)txtColor backgroundColor:(DDColor *)bgColor forFlag:(DDLogFlag)mask context:(NSInteger)ctxt;
|
||||
- (void)setForegroundColor:(nullable DDColor *)txtColor backgroundColor:(nullable DDColor *)bgColor forFlag:(DDLogFlag)mask context:(NSInteger)ctxt;
|
||||
|
||||
/**
|
||||
* Similar to the methods above, but allows you to map DDLogMessage->tag to a particular color profile.
|
||||
|
@ -163,7 +169,7 @@
|
|||
*
|
||||
* DDLogPurple(@"I'm a purple log message!");
|
||||
**/
|
||||
- (void)setForegroundColor:(DDColor *)txtColor backgroundColor:(DDColor *)bgColor forTag:(id <NSCopying>)tag;
|
||||
- (void)setForegroundColor:(nullable DDColor *)txtColor backgroundColor:(nullable DDColor *)bgColor forTag:(id <NSCopying>)tag;
|
||||
|
||||
/**
|
||||
* Clearing color profiles.
|
||||
|
@ -176,3 +182,5 @@
|
|||
- (void)clearAllColors;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
@ -14,7 +14,7 @@
|
|||
// prior written permission of Deusty, LLC.
|
||||
|
||||
#if SWIFT_PACKAGE
|
||||
import CocoaLumberjack
|
||||
@_exported import CocoaLumberjack
|
||||
import CocoaLumberjackSwiftSupport
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Software License Agreement (BSD License)
|
||||
//
|
||||
// Copyright (c) 2010-2019, Deusty, LLC
|
||||
// Copyright (c) 2010-2020, Deusty, LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use of this software in source and binary forms,
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
PODS:
|
||||
- Alamofire (5.0.0-rc.3)
|
||||
- CocoaLumberjack/Core (3.6.0)
|
||||
- CocoaLumberjack/Swift (3.6.0):
|
||||
- Alamofire (5.0.2)
|
||||
- CocoaLumberjack/Core (3.6.1)
|
||||
- CocoaLumberjack/Swift (3.6.1):
|
||||
- CocoaLumberjack/Core
|
||||
- Crashlytics (3.14.0):
|
||||
- Fabric (~> 1.10.2)
|
||||
- Fabric (1.10.2)
|
||||
- LetsMove (1.24)
|
||||
- RxCocoa (5.0.1):
|
||||
- RxCocoa (5.1.0):
|
||||
- RxRelay (~> 5)
|
||||
- RxSwift (~> 5)
|
||||
- RxRelay (5.0.1):
|
||||
- RxRelay (5.1.0):
|
||||
- RxSwift (~> 5)
|
||||
- RxSwift (5.0.1)
|
||||
- Sparkle (1.22.0)
|
||||
- RxSwift (5.1.0)
|
||||
- Sparkle (1.23.0)
|
||||
- Starscream (3.1.1)
|
||||
- SwiftyJSON (5.0.0)
|
||||
- WebViewJavascriptBridge (6.0.3)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Alamofire (~> 5.0.0-rc.3)
|
||||
- Alamofire (~> 5.0)
|
||||
- CocoaLumberjack/Swift
|
||||
- Crashlytics
|
||||
- Fabric
|
||||
|
@ -36,31 +36,30 @@ SPEC REPOS:
|
|||
- Alamofire
|
||||
- CocoaLumberjack
|
||||
- Crashlytics
|
||||
- Fabric
|
||||
- LetsMove
|
||||
- RxCocoa
|
||||
- RxRelay
|
||||
- RxSwift
|
||||
- Sparkle
|
||||
- Starscream
|
||||
- SwiftyJSON
|
||||
- WebViewJavascriptBridge
|
||||
https://github.com/cocoapods/specs.git:
|
||||
- Fabric
|
||||
- RxSwift
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Alamofire: ca8c0de6906873be89d6deec5c8de279e00bf872
|
||||
CocoaLumberjack: 78b0c238666f4f58db069738ec176f4519557516
|
||||
Alamofire: 3ba7a4db18b4f62c4a1c0e1cb39d7f3d52e10ada
|
||||
CocoaLumberjack: b17ae15142558d08bbacf69775fa10c4abbebcc9
|
||||
Crashlytics: 540b7e5f5da5a042647227a5e3ac51d85eed06df
|
||||
Fabric: 706c8b8098fff96c33c0db69cbf81f9c551d0d74
|
||||
LetsMove: fefe56bc7bc7fb7d37049e28a14f297961229fc5
|
||||
RxCocoa: e741b9749968e8a143e2b787f1dfbff2b63d0a5c
|
||||
RxRelay: 89d54507f4fd4d969e6ec1d4bd7f3673640b4640
|
||||
RxSwift: e2dc62b366a3adf6a0be44ba9f405efd4c94e0c4
|
||||
Sparkle: 593ac2e677c07bcb6c3b22d621240e7cbedaab57
|
||||
RxCocoa: 13d2a4d7546a34b8ececae8c281e4ea1dbb94f2b
|
||||
RxRelay: a168bd6caf712d00c676ac344e9295afc93b418e
|
||||
RxSwift: ad5874f24bb0dbffd1e9bb8443604e3578796c7a
|
||||
Sparkle: 55b1a87ba69d56913375a281546b7c82dec95bb0
|
||||
Starscream: 4bb2f9942274833f7b4d296a55504dcfc7edb7b0
|
||||
SwiftyJSON: 36413e04c44ee145039d332b4f4e2d3e8d6c4db7
|
||||
WebViewJavascriptBridge: 7f5bc4d3581e672e8f32bd0f812d54bc69bb8e29
|
||||
|
||||
PODFILE CHECKSUM: 8dd9c30013fa97b5c735e427620c41790488a2a1
|
||||
PODFILE CHECKSUM: b104b5e59f0be7cdf17282b19ab5917132171e6f
|
||||
|
||||
COCOAPODS: 1.7.5
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -35,7 +35,7 @@ struct Bag<T> : CustomDebugStringConvertible {
|
|||
|
||||
typealias Entry = (key: BagKey, value: T)
|
||||
|
||||
fileprivate var _nextKey: BagKey = BagKey(rawValue: 0)
|
||||
private var _nextKey: BagKey = BagKey(rawValue: 0)
|
||||
|
||||
// data
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ struct PriorityQueue<Element> {
|
|||
private let _hasHigherPriority: (Element, Element) -> Bool
|
||||
private let _isEqual: (Element, Element) -> Bool
|
||||
|
||||
fileprivate var _elements = [Element]()
|
||||
private var _elements = [Element]()
|
||||
|
||||
init(hasHigherPriority: @escaping (Element, Element) -> Bool, isEqual: @escaping (Element, Element) -> Bool) {
|
||||
_hasHigherPriority = hasHigherPriority
|
||||
|
|
|
@ -186,7 +186,7 @@ If you wish to build RxSwift as a Static Library using Carthage you may use the
|
|||
```bash
|
||||
carthage update RxSwift --platform iOS --no-build
|
||||
sed -i -e 's/MACH_O_TYPE = mh_dylib/MACH_O_TYPE = staticlib/g' Carthage/Checkouts/RxSwift/Rx.xcodeproj/project.pbxproj
|
||||
carthage build RxAlamofire --platform iOS
|
||||
carthage build RxSwift --platform iOS
|
||||
```
|
||||
|
||||
### [Swift Package Manager](https://github.com/apple/swift-package-manager)
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
/// Parent object associated with delegate proxy.
|
||||
private weak var _parentObject: ParentObject?
|
||||
|
||||
fileprivate let _currentDelegateFor: (ParentObject) -> AnyObject?
|
||||
fileprivate let _setCurrentDelegateTo: (AnyObject?, ParentObject) -> Void
|
||||
private let _currentDelegateFor: (ParentObject) -> AnyObject?
|
||||
private let _setCurrentDelegateTo: (AnyObject?, ParentObject) -> Void
|
||||
|
||||
/// Initializes new instance.
|
||||
///
|
||||
|
@ -258,7 +258,7 @@
|
|||
|
||||
private let mainScheduler = MainScheduler()
|
||||
|
||||
fileprivate final class MessageDispatcher {
|
||||
private final class MessageDispatcher {
|
||||
private let dispatcher: PublishSubject<[Any]>
|
||||
private let result: Observable<[Any]>
|
||||
|
||||
|
|
|
@ -240,18 +240,18 @@ extension DelegateProxyType {
|
|||
}
|
||||
|
||||
|
||||
// fileprivate extensions
|
||||
// private extensions
|
||||
extension DelegateProxyType {
|
||||
fileprivate static var factory: DelegateProxyFactory {
|
||||
private static var factory: DelegateProxyFactory {
|
||||
return DelegateProxyFactory.sharedFactory(for: self)
|
||||
}
|
||||
|
||||
fileprivate static func assignedProxy(for object: ParentObject) -> AnyObject? {
|
||||
private static func assignedProxy(for object: ParentObject) -> AnyObject? {
|
||||
let maybeDelegate = objc_getAssociatedObject(object, self.identifier)
|
||||
return castOptionalOrFatalError(maybeDelegate)
|
||||
}
|
||||
|
||||
fileprivate static func assignProxy(_ proxy: AnyObject, toObject object: ParentObject) {
|
||||
private static func assignProxy(_ proxy: AnyObject, toObject object: ParentObject) {
|
||||
objc_setAssociatedObject(object, self.identifier, proxy, .OBJC_ASSOCIATION_RETAIN)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -220,12 +220,6 @@ extension ObservableType {
|
|||
fatalError()
|
||||
}
|
||||
}
|
||||
extension UIWebView {
|
||||
@available(*, unavailable, message: "createRxDelegateProxy is now unavailable, check DelegateProxyFactory")
|
||||
public func createRxDelegateProxy() -> RxWebViewDelegateProxy {
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if os(macOS)
|
||||
|
@ -407,8 +401,6 @@ extension Reactive where Base: UISegmentedControl {
|
|||
}
|
||||
#endif
|
||||
|
||||
import RxSwift
|
||||
|
||||
@available(*, deprecated, message: "Variable is deprecated. Please use `BehaviorRelay` as a replacement.")
|
||||
extension Variable {
|
||||
/// Converts `Variable` to `Driver` trait.
|
||||
|
|
|
@ -6,7 +6,11 @@
|
|||
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
#if canImport(FoundationNetworking)
|
||||
import struct FoundationNetworking.URLRequest
|
||||
#else
|
||||
import struct Foundation.URLRequest
|
||||
#endif
|
||||
|
||||
/// Simple logging settings for RxCocoa library.
|
||||
public struct Logging {
|
||||
|
|
|
@ -202,7 +202,7 @@ extension Reactive where Base: AnyObject {
|
|||
}
|
||||
}
|
||||
|
||||
fileprivate func registerMessageInterceptor<T: MessageInterceptorSubject>(_ selector: Selector) throws -> T {
|
||||
private func registerMessageInterceptor<T: MessageInterceptorSubject>(_ selector: Selector) throws -> T {
|
||||
let rxSelector = RX_selector(selector)
|
||||
let selectorReference = RX_reference_from_selector(rxSelector)
|
||||
|
||||
|
@ -251,7 +251,7 @@ extension Reactive where Base: AnyObject {
|
|||
var targetImplementation: IMP { get set }
|
||||
}
|
||||
|
||||
fileprivate final class DeallocatingProxy
|
||||
private final class DeallocatingProxy
|
||||
: MessageInterceptorSubject
|
||||
, RXDeallocatingObserver {
|
||||
typealias Element = ()
|
||||
|
@ -276,7 +276,7 @@ extension Reactive where Base: AnyObject {
|
|||
}
|
||||
}
|
||||
|
||||
fileprivate final class MessageSentProxy
|
||||
private final class MessageSentProxy
|
||||
: MessageInterceptorSubject
|
||||
, RXMessageSentObserver {
|
||||
typealias Element = [AnyObject]
|
||||
|
@ -310,7 +310,7 @@ extension Reactive where Base: AnyObject {
|
|||
#endif
|
||||
|
||||
|
||||
fileprivate final class DeallocObservable {
|
||||
private final class DeallocObservable {
|
||||
let _subject = ReplaySubject<Void>.create(bufferSize:1)
|
||||
|
||||
init() {
|
||||
|
@ -333,7 +333,7 @@ private protocol KVOObservableProtocol {
|
|||
var options: KeyValueObservingOptions { get }
|
||||
}
|
||||
|
||||
fileprivate final class KVOObserver
|
||||
private final class KVOObserver
|
||||
: _RXKVOObserver
|
||||
, Disposable {
|
||||
typealias Callback = (Any?) -> Void
|
||||
|
@ -361,7 +361,7 @@ fileprivate final class KVOObserver
|
|||
}
|
||||
}
|
||||
|
||||
fileprivate final class KVOObservable<Element>
|
||||
private final class KVOObservable<Element>
|
||||
: ObservableType
|
||||
, KVOObservableProtocol {
|
||||
typealias Element = Element?
|
||||
|
@ -397,7 +397,7 @@ fileprivate final class KVOObservable<Element>
|
|||
|
||||
}
|
||||
|
||||
fileprivate extension KeyValueObservingOptions {
|
||||
private extension KeyValueObservingOptions {
|
||||
var nsOptions: NSKeyValueObservingOptions {
|
||||
var result: UInt = 0
|
||||
if self.contains(.new) {
|
||||
|
@ -438,7 +438,7 @@ fileprivate extension KeyValueObservingOptions {
|
|||
return properyRuntimeInfo.range(of: ",W,") != nil
|
||||
}
|
||||
|
||||
fileprivate extension ObservableType where Element == AnyObject? {
|
||||
private extension ObservableType where Element == AnyObject? {
|
||||
func finishWithNilWhenDealloc(_ target: NSObject)
|
||||
-> Observable<AnyObject?> {
|
||||
let deallocating = target.rx.deallocating
|
||||
|
|
|
@ -7,18 +7,26 @@
|
|||
//
|
||||
|
||||
import struct Foundation.URL
|
||||
import struct Foundation.URLRequest
|
||||
import struct Foundation.Data
|
||||
import struct Foundation.Date
|
||||
import struct Foundation.TimeInterval
|
||||
import class Foundation.HTTPURLResponse
|
||||
import class Foundation.URLSession
|
||||
import class Foundation.URLResponse
|
||||
import class Foundation.JSONSerialization
|
||||
import class Foundation.NSError
|
||||
import var Foundation.NSURLErrorCancelled
|
||||
import var Foundation.NSURLErrorDomain
|
||||
|
||||
#if canImport(FoundationNetworking)
|
||||
import struct FoundationNetworking.URLRequest
|
||||
import class FoundationNetworking.HTTPURLResponse
|
||||
import class FoundationNetworking.URLSession
|
||||
import class FoundationNetworking.URLResponse
|
||||
#else
|
||||
import struct Foundation.URLRequest
|
||||
import class Foundation.HTTPURLResponse
|
||||
import class Foundation.URLSession
|
||||
import class Foundation.URLResponse
|
||||
#endif
|
||||
|
||||
#if os(Linux)
|
||||
// don't know why
|
||||
import Foundation
|
||||
|
@ -60,11 +68,11 @@ private func escapeTerminalString(_ value: String) -> String {
|
|||
return value.replacingOccurrences(of: "\"", with: "\\\"", options:[], range: nil)
|
||||
}
|
||||
|
||||
fileprivate func convertURLRequestToCurlCommand(_ request: URLRequest) -> String {
|
||||
private func convertURLRequestToCurlCommand(_ request: URLRequest) -> String {
|
||||
let method = request.httpMethod ?? "GET"
|
||||
var returnValue = "curl -X \(method) "
|
||||
|
||||
if let httpBody = request.httpBody, request.httpMethod == "POST" {
|
||||
if let httpBody = request.httpBody, request.httpMethod == "POST" || request.httpMethod == "PUT" {
|
||||
let maybeBody = String(data: httpBody, encoding: String.Encoding.utf8)
|
||||
if let body = maybeBody {
|
||||
returnValue += "-d \"\(escapeTerminalString(body))\" "
|
||||
|
|
|
@ -20,10 +20,9 @@ public protocol ControlEventType : ObservableType {
|
|||
|
||||
Properties:
|
||||
|
||||
- it never fails,
|
||||
- it doesn’t send any initial value on subscription,
|
||||
- it `Complete`s the sequence when the control deallocates,
|
||||
- it never errors out, and
|
||||
- it never errors out
|
||||
- it delivers events on `MainScheduler.instance`.
|
||||
|
||||
**The implementation of `ControlEvent` will ensure that sequence of events is being subscribed on main scheduler
|
||||
|
@ -33,7 +32,7 @@ public protocol ControlEventType : ObservableType {
|
|||
|
||||
**If they aren’t, using this trait will communicate wrong properties, and could potentially break someone’s code.**
|
||||
|
||||
**If the `events` observable sequence passed into thr initializer doesn’t satisfy all enumerated
|
||||
**If the `events` observable sequence passed into the initializer doesn’t satisfy all enumerated
|
||||
properties, don’t use this trait.**
|
||||
*/
|
||||
public struct ControlEvent<PropertyType> : ControlEventType {
|
||||
|
|
|
@ -23,7 +23,6 @@ public protocol ControlPropertyType : ObservableType, ObserverType {
|
|||
|
||||
It's properties are:
|
||||
|
||||
- it never fails
|
||||
- `shareReplay(1)` behavior
|
||||
- it's stateful, upon subscription (calling subscribe) last element is immediately replayed if it was produced
|
||||
- it will `Complete` sequence on control being deallocated
|
||||
|
|
|
@ -25,6 +25,30 @@ extension SharedSequenceConvertibleType {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: compactMap
|
||||
extension SharedSequenceConvertibleType {
|
||||
|
||||
/**
|
||||
Projects each element of an observable sequence into an optional form and filters all optional results.
|
||||
|
||||
Equivalent to:
|
||||
|
||||
func compactMap<Result>(_ transform: @escaping (Self.E) -> Result?) -> SharedSequence<SharingStrategy, Result> {
|
||||
return self.map(transform).filter { $0 != nil }.map { $0! }
|
||||
}
|
||||
|
||||
- parameter transform: A transform function to apply to each source element and which returns an element or nil.
|
||||
- returns: An observable sequence whose elements are the result of filtering the transform function for each element of the source.
|
||||
|
||||
*/
|
||||
public func compactMap<Result>(_ selector: @escaping (Element) -> Result?) -> SharedSequence<SharingStrategy, Result> {
|
||||
let source = self
|
||||
.asObservable()
|
||||
.compactMap(selector)
|
||||
return SharedSequence<SharingStrategy, Result>(source)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: filter
|
||||
extension SharedSequenceConvertibleType {
|
||||
/**
|
||||
|
|
|
@ -37,8 +37,8 @@ public struct SharedSequence<SharingStrategy: SharingStrategyProtocol, Element>
|
|||
By defining `EXPANDABLE_SHARED_SEQUENCE` one agrees that it's up to him to ensure shared sequence
|
||||
properties are preserved after extension.
|
||||
*/
|
||||
public static func createUnsafe<Source: ObservableType>(source: Source) -> SharedSequence<Sequence, Source.Element> {
|
||||
return SharedSequence<Sequence, Source.Element>(raw: source.asObservable())
|
||||
public static func createUnsafe<Source: ObservableType>(source: Source) -> SharedSequence<SharingStrategy, Source.Element> {
|
||||
return SharedSequence<SharingStrategy, Source.Element>(raw: source.asObservable())
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -17,10 +17,10 @@ extension UICollectionView: HasPrefetchDataSource {
|
|||
}
|
||||
|
||||
@available(iOS 10.0, tvOS 10.0, *)
|
||||
fileprivate let collectionViewPrefetchDataSourceNotSet = CollectionViewPrefetchDataSourceNotSet()
|
||||
private let collectionViewPrefetchDataSourceNotSet = CollectionViewPrefetchDataSourceNotSet()
|
||||
|
||||
@available(iOS 10.0, tvOS 10.0, *)
|
||||
fileprivate final class CollectionViewPrefetchDataSourceNotSet
|
||||
private final class CollectionViewPrefetchDataSourceNotSet
|
||||
: NSObject
|
||||
, UICollectionViewDataSourcePrefetching {
|
||||
|
||||
|
@ -48,7 +48,7 @@ open class RxCollectionViewDataSourcePrefetchingProxy
|
|||
self.register { RxCollectionViewDataSourcePrefetchingProxy(collectionView: $0) }
|
||||
}
|
||||
|
||||
fileprivate var _prefetchItemsPublishSubject: PublishSubject<[IndexPath]>?
|
||||
private var _prefetchItemsPublishSubject: PublishSubject<[IndexPath]>?
|
||||
|
||||
/// Optimized version used for observing prefetch items callbacks.
|
||||
internal var prefetchItemsPublishSubject: PublishSubject<[IndexPath]> {
|
||||
|
|
|
@ -15,9 +15,9 @@ extension UICollectionView: HasDataSource {
|
|||
public typealias DataSource = UICollectionViewDataSource
|
||||
}
|
||||
|
||||
fileprivate let collectionViewDataSourceNotSet = CollectionViewDataSourceNotSet()
|
||||
private let collectionViewDataSourceNotSet = CollectionViewDataSourceNotSet()
|
||||
|
||||
fileprivate final class CollectionViewDataSourceNotSet
|
||||
private final class CollectionViewDataSourceNotSet
|
||||
: NSObject
|
||||
, UICollectionViewDataSource {
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@ open class RxScrollViewDelegateProxy
|
|||
self.register { RxTextViewDelegateProxy(textView: $0) }
|
||||
}
|
||||
|
||||
fileprivate var _contentOffsetBehaviorSubject: BehaviorSubject<CGPoint>?
|
||||
fileprivate var _contentOffsetPublishSubject: PublishSubject<()>?
|
||||
private var _contentOffsetBehaviorSubject: BehaviorSubject<CGPoint>?
|
||||
private var _contentOffsetPublishSubject: PublishSubject<()>?
|
||||
|
||||
/// Optimized version used for observing content offset changes.
|
||||
internal var contentOffsetBehaviorSubject: BehaviorSubject<CGPoint> {
|
||||
|
|
|
@ -17,10 +17,10 @@ extension UITableView: HasPrefetchDataSource {
|
|||
}
|
||||
|
||||
@available(iOS 10.0, tvOS 10.0, *)
|
||||
fileprivate let tableViewPrefetchDataSourceNotSet = TableViewPrefetchDataSourceNotSet()
|
||||
private let tableViewPrefetchDataSourceNotSet = TableViewPrefetchDataSourceNotSet()
|
||||
|
||||
@available(iOS 10.0, tvOS 10.0, *)
|
||||
fileprivate final class TableViewPrefetchDataSourceNotSet
|
||||
private final class TableViewPrefetchDataSourceNotSet
|
||||
: NSObject
|
||||
, UITableViewDataSourcePrefetching {
|
||||
|
||||
|
@ -48,7 +48,7 @@ open class RxTableViewDataSourcePrefetchingProxy
|
|||
self.register { RxTableViewDataSourcePrefetchingProxy(tableView: $0) }
|
||||
}
|
||||
|
||||
fileprivate var _prefetchRowsPublishSubject: PublishSubject<[IndexPath]>?
|
||||
private var _prefetchRowsPublishSubject: PublishSubject<[IndexPath]>?
|
||||
|
||||
/// Optimized version used for observing prefetch rows callbacks.
|
||||
internal var prefetchRowsPublishSubject: PublishSubject<[IndexPath]> {
|
||||
|
|
|
@ -15,9 +15,9 @@ extension UITableView: HasDataSource {
|
|||
public typealias DataSource = UITableViewDataSource
|
||||
}
|
||||
|
||||
fileprivate let tableViewDataSourceNotSet = TableViewDataSourceNotSet()
|
||||
private let tableViewDataSourceNotSet = TableViewDataSourceNotSet()
|
||||
|
||||
fileprivate final class TableViewDataSourceNotSet
|
||||
private final class TableViewDataSourceNotSet
|
||||
: NSObject
|
||||
, UITableViewDataSource {
|
||||
|
||||
|
@ -50,7 +50,7 @@ open class RxTableViewDataSourceProxy
|
|||
self.register { RxTableViewDataSourceProxy(tableView: $0) }
|
||||
}
|
||||
|
||||
fileprivate weak var _requiredMethodsDataSource: UITableViewDataSource? = tableViewDataSourceNotSet
|
||||
private weak var _requiredMethodsDataSource: UITableViewDataSource? = tableViewDataSourceNotSet
|
||||
|
||||
// MARK: delegate
|
||||
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
//
|
||||
// RxWebViewDelegateProxy.swift
|
||||
// RxCocoa
|
||||
//
|
||||
// Created by Andrew Breckenridge on 9/26/16.
|
||||
// Copyright © 2016 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS)
|
||||
|
||||
import UIKit
|
||||
import RxSwift
|
||||
|
||||
extension UIWebView: HasDelegate {
|
||||
public typealias Delegate = UIWebViewDelegate
|
||||
}
|
||||
|
||||
open class RxWebViewDelegateProxy
|
||||
: DelegateProxy<UIWebView, UIWebViewDelegate>
|
||||
, DelegateProxyType
|
||||
, UIWebViewDelegate {
|
||||
|
||||
/// Typed parent object.
|
||||
public weak private(set) var webView: UIWebView?
|
||||
|
||||
/// - parameter webView: Parent object for delegate proxy.
|
||||
public init(webView: ParentObject) {
|
||||
self.webView = webView
|
||||
super.init(parentObject: webView, delegateProxy: RxWebViewDelegateProxy.self)
|
||||
}
|
||||
|
||||
// Register known implementations
|
||||
public static func registerKnownImplementations() {
|
||||
self.register { RxWebViewDelegateProxy(webView: $0) }
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -11,7 +11,7 @@
|
|||
import UIKit
|
||||
import RxSwift
|
||||
|
||||
fileprivate var rx_tap_key: UInt8 = 0
|
||||
private var rx_tap_key: UInt8 = 0
|
||||
|
||||
extension Reactive where Base: UIBarButtonItem {
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ extension Reactive where Base: UICollectionView {
|
|||
- parameter cellIdentifier: Identifier used to dequeue cells.
|
||||
- parameter source: Observable sequence of items.
|
||||
- parameter configureCell: Transform between sequence elements and view cells.
|
||||
- parameter cellType: Type of table view cell.
|
||||
- parameter cellType: Type of collection view cell.
|
||||
- returns: Disposable object that can be used to unbind.
|
||||
|
||||
Example
|
||||
|
|
|
@ -51,6 +51,13 @@ extension Reactive where Base: UITextField {
|
|||
)
|
||||
}
|
||||
|
||||
/// Bindable sink for `isSecureTextEntry` property.
|
||||
public var isSecureTextEntry: Binder<Bool> {
|
||||
return Binder(self.base) { textField, isSecureTextEntry in
|
||||
textField.isSecureTextEntry = isSecureTextEntry
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
//
|
||||
// UIWebView+Rx.swift
|
||||
// RxCocoa
|
||||
//
|
||||
// Created by Andrew Breckenridge on 8/30/16.
|
||||
// Copyright © 2016 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS)
|
||||
|
||||
import UIKit
|
||||
import RxSwift
|
||||
|
||||
extension Reactive where Base: UIWebView {
|
||||
|
||||
/// Reactive wrapper for `delegate`.
|
||||
/// For more information take a look at `DelegateProxyType` protocol documentation.
|
||||
public var delegate: DelegateProxy<UIWebView, UIWebViewDelegate> {
|
||||
return RxWebViewDelegateProxy.proxy(for: base)
|
||||
}
|
||||
|
||||
/// Reactive wrapper for `delegate` message.
|
||||
public var didStartLoad: Observable<Void> {
|
||||
return delegate
|
||||
.methodInvoked(#selector(UIWebViewDelegate.webViewDidStartLoad(_:)))
|
||||
.map { _ in }
|
||||
}
|
||||
|
||||
/// Reactive wrapper for `delegate` message.
|
||||
public var didFinishLoad: Observable<Void> {
|
||||
return delegate
|
||||
.methodInvoked(#selector(UIWebViewDelegate.webViewDidFinishLoad(_:)))
|
||||
.map { _ in }
|
||||
}
|
||||
|
||||
/// Reactive wrapper for `delegate` message.
|
||||
public var didFailLoad: Observable<Error> {
|
||||
return delegate
|
||||
.methodInvoked(#selector(UIWebViewDelegate.webView(_:didFailLoadWithError:)))
|
||||
.map { a in
|
||||
return try castOrThrow(Error.self, a[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -16,7 +16,7 @@ extension Reactive where Base: NSSlider {
|
|||
/// Reactive wrapper for `value` property.
|
||||
public var value: ControlProperty<Double> {
|
||||
return self.base.rx.controlProperty(
|
||||
getter: { control in
|
||||
getter: { control -> Double in
|
||||
return control.doubleValue
|
||||
},
|
||||
setter: { control, value in
|
||||
|
|
|
@ -186,7 +186,7 @@ If you wish to build RxSwift as a Static Library using Carthage you may use the
|
|||
```bash
|
||||
carthage update RxSwift --platform iOS --no-build
|
||||
sed -i -e 's/MACH_O_TYPE = mh_dylib/MACH_O_TYPE = staticlib/g' Carthage/Checkouts/RxSwift/Rx.xcodeproj/project.pbxproj
|
||||
carthage build RxAlamofire --platform iOS
|
||||
carthage build RxSwift --platform iOS
|
||||
```
|
||||
|
||||
### [Swift Package Manager](https://github.com/apple/swift-package-manager)
|
||||
|
|
|
@ -35,7 +35,7 @@ struct Bag<T> : CustomDebugStringConvertible {
|
|||
|
||||
typealias Entry = (key: BagKey, value: T)
|
||||
|
||||
fileprivate var _nextKey: BagKey = BagKey(rawValue: 0)
|
||||
private var _nextKey: BagKey = BagKey(rawValue: 0)
|
||||
|
||||
// data
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ struct PriorityQueue<Element> {
|
|||
private let _hasHigherPriority: (Element, Element) -> Bool
|
||||
private let _isEqual: (Element, Element) -> Bool
|
||||
|
||||
fileprivate var _elements = [Element]()
|
||||
private var _elements = [Element]()
|
||||
|
||||
init(hasHigherPriority: @escaping (Element, Element) -> Bool, isEqual: @escaping (Element, Element) -> Bool) {
|
||||
_hasHigherPriority = hasHigherPriority
|
||||
|
|
|
@ -186,7 +186,7 @@ If you wish to build RxSwift as a Static Library using Carthage you may use the
|
|||
```bash
|
||||
carthage update RxSwift --platform iOS --no-build
|
||||
sed -i -e 's/MACH_O_TYPE = mh_dylib/MACH_O_TYPE = staticlib/g' Carthage/Checkouts/RxSwift/Rx.xcodeproj/project.pbxproj
|
||||
carthage build RxAlamofire --platform iOS
|
||||
carthage build RxSwift --platform iOS
|
||||
```
|
||||
|
||||
### [Swift Package Manager](https://github.com/apple/swift-package-manager)
|
||||
|
|
|
@ -179,7 +179,7 @@ public final class Variable<Element> {
|
|||
private var _value: Element
|
||||
|
||||
#if DEBUG
|
||||
fileprivate let _synchronizationTracker = SynchronizationTracker()
|
||||
private let _synchronizationTracker = SynchronizationTracker()
|
||||
#endif
|
||||
|
||||
/// Gets or sets current value of variable.
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
/// Represents an Action-based disposable.
|
||||
///
|
||||
/// When dispose method is called, disposal action will be dereferenced.
|
||||
fileprivate final class AnonymousDisposable : DisposeBase, Cancelable {
|
||||
private final class AnonymousDisposable : DisposeBase, Cancelable {
|
||||
public typealias DisposeAction = () -> Void
|
||||
|
||||
private let _isDisposed = AtomicInt(0)
|
||||
|
@ -23,7 +23,7 @@ fileprivate final class AnonymousDisposable : DisposeBase, Cancelable {
|
|||
/// Constructs a new disposable with the given action used for disposal.
|
||||
///
|
||||
/// - parameter disposeAction: Disposal action which will be run upon calling `dispose`.
|
||||
fileprivate init(_ disposeAction: @escaping DisposeAction) {
|
||||
private init(_ disposeAction: @escaping DisposeAction) {
|
||||
self._disposeAction = disposeAction
|
||||
super.init()
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ public final class DisposeBag: DisposeBase {
|
|||
private var _lock = SpinLock()
|
||||
|
||||
// state
|
||||
fileprivate var _disposables = [Disposable]()
|
||||
fileprivate var _isDisposed = false
|
||||
private var _disposables = [Disposable]()
|
||||
private var _isDisposed = false
|
||||
|
||||
/// Constructs new empty dispose bag.
|
||||
public override init() {
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
/// Represents a disposable that does nothing on disposal.
|
||||
///
|
||||
/// Nop = No Operation
|
||||
fileprivate struct NopDisposable : Disposable {
|
||||
private struct NopDisposable : Disposable {
|
||||
|
||||
fileprivate static let noOp: Disposable = NopDisposable()
|
||||
|
||||
fileprivate init() {
|
||||
private init() {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ If an underlying disposable resource has already been set, future attempts to se
|
|||
*/
|
||||
public final class SingleAssignmentDisposable : DisposeBase, Cancelable {
|
||||
|
||||
fileprivate enum DisposeState: Int32 {
|
||||
private enum DisposeState: Int32 {
|
||||
case disposed = 1
|
||||
case disposableSet = 2
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ public enum RxError
|
|||
case unknown
|
||||
/// Performing an action on disposed object.
|
||||
case disposed(object: AnyObject)
|
||||
/// Aritmetic overflow error.
|
||||
/// Arithmetic overflow error.
|
||||
case overflow
|
||||
/// Argument out of range error.
|
||||
case argumentOutOfRange
|
||||
|
|
|
@ -94,7 +94,7 @@ public protocol EventConvertible {
|
|||
/// Type of element in event
|
||||
associatedtype Element
|
||||
|
||||
@available(*, deprecated, message: "Use `Element` instead.")
|
||||
@available(*, deprecated, renamed: "Element")
|
||||
typealias ElementType = Element
|
||||
|
||||
/// Event representation of this instance
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
//
|
||||
// String+Rx.swift
|
||||
// RxSwift
|
||||
//
|
||||
// Created by Krunoslav Zaher on 12/25/15.
|
||||
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
extension String {
|
||||
/// This is needed because on Linux Swift doesn't have `rangeOfString(..., options: .BackwardsSearch)`
|
||||
func lastIndexOf(_ character: Character) -> Index? {
|
||||
var index = self.endIndex
|
||||
while index > self.startIndex {
|
||||
index = self.index(before: index)
|
||||
if self[index] == character {
|
||||
return index
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -29,13 +29,5 @@ public class Observable<Element> : ObservableType {
|
|||
_ = Resources.decrementTotal()
|
||||
#endif
|
||||
}
|
||||
|
||||
// this is kind of ugly I know :(
|
||||
// Swift compiler reports "Not supported yet" when trying to override protocol extensions, so ¯\_(ツ)_/¯
|
||||
|
||||
/// Optimizations for map operator
|
||||
internal func composeMap<Result>(_ transform: @escaping (Element) throws -> Result) -> Observable<Result> {
|
||||
return _map(source: self, transform: transform)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ public protocol ObservableConvertibleType {
|
|||
/// Type of elements in sequence.
|
||||
associatedtype Element
|
||||
|
||||
@available(*, deprecated, message: "Use `Element` instead.")
|
||||
@available(*, deprecated, renamed: "Element")
|
||||
typealias E = Element
|
||||
|
||||
/// Converts `self` to `Observable` sequence.
|
||||
|
|
|
@ -89,14 +89,17 @@ extension Hooks {
|
|||
public typealias DefaultErrorHandler = (_ subscriptionCallStack: [String], _ error: Error) -> Void
|
||||
public typealias CustomCaptureSubscriptionCallstack = () -> [String]
|
||||
|
||||
fileprivate static let _lock = RecursiveLock()
|
||||
fileprivate static var _defaultErrorHandler: DefaultErrorHandler = { subscriptionCallStack, error in
|
||||
private static let _lock = RecursiveLock()
|
||||
private static var _defaultErrorHandler: DefaultErrorHandler = { subscriptionCallStack, error in
|
||||
#if DEBUG
|
||||
let serializedCallStack = subscriptionCallStack.joined(separator: "\n")
|
||||
print("Unhandled error happened: \(error)\n subscription called from:\n\(serializedCallStack)")
|
||||
print("Unhandled error happened: \(error)")
|
||||
if !serializedCallStack.isEmpty {
|
||||
print("subscription called from:\n\(serializedCallStack)")
|
||||
}
|
||||
#endif
|
||||
}
|
||||
fileprivate static var _customCaptureSubscriptionCallstack: CustomCaptureSubscriptionCallstack = {
|
||||
private static var _customCaptureSubscriptionCallstack: CustomCaptureSubscriptionCallstack = {
|
||||
#if DEBUG
|
||||
return Thread.callStackSymbols
|
||||
#else
|
||||
|
|
|
@ -39,7 +39,7 @@ extension ObservableType {
|
|||
}
|
||||
}
|
||||
|
||||
fileprivate enum AmbState {
|
||||
private enum AmbState {
|
||||
case neither
|
||||
case left
|
||||
case right
|
||||
|
@ -51,7 +51,7 @@ final private class AmbObserver<Observer: ObserverType>: ObserverType {
|
|||
typealias This = AmbObserver<Observer>
|
||||
typealias Sink = (This, Event<Element>) -> Void
|
||||
|
||||
fileprivate let _parent: Parent
|
||||
private let _parent: Parent
|
||||
fileprivate var _sink: Sink
|
||||
fileprivate var _cancel: Disposable
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// Copyright © 2017 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
fileprivate final class AsMaybeSink<Observer: ObserverType> : Sink<Observer>, ObserverType {
|
||||
private final class AsMaybeSink<Observer: ObserverType> : Sink<Observer>, ObserverType {
|
||||
typealias Element = Observer.Element
|
||||
|
||||
private var _element: Event<Element>?
|
||||
|
@ -34,7 +34,7 @@ fileprivate final class AsMaybeSink<Observer: ObserverType> : Sink<Observer>, Ob
|
|||
}
|
||||
|
||||
final class AsMaybe<Element>: Producer<Element> {
|
||||
fileprivate let _source: Observable<Element>
|
||||
private let _source: Observable<Element>
|
||||
|
||||
init(source: Observable<Element>) {
|
||||
self._source = source
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// Copyright © 2017 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
fileprivate final class AsSingleSink<Observer: ObserverType> : Sink<Observer>, ObserverType {
|
||||
private final class AsSingleSink<Observer: ObserverType> : Sink<Observer>, ObserverType {
|
||||
typealias Element = Observer.Element
|
||||
|
||||
private var _element: Event<Element>?
|
||||
|
@ -37,7 +37,7 @@ fileprivate final class AsSingleSink<Observer: ObserverType> : Sink<Observer>, O
|
|||
}
|
||||
|
||||
final class AsSingle<Element>: Producer<Element> {
|
||||
fileprivate let _source: Observable<Element>
|
||||
private let _source: Observable<Element>
|
||||
|
||||
init(source: Observable<Element>) {
|
||||
self._source = source
|
||||
|
|
|
@ -30,7 +30,7 @@ final private class AnonymousObservableSink<Observer: ObserverType>: Sink<Observ
|
|||
private let _isStopped = AtomicInt(0)
|
||||
|
||||
#if DEBUG
|
||||
fileprivate let _synchronizationTracker = SynchronizationTracker()
|
||||
private let _synchronizationTracker = SynchronizationTracker()
|
||||
#endif
|
||||
|
||||
override init(observer: Observer, cancel: Cancelable) {
|
||||
|
|
|
@ -26,9 +26,9 @@ extension ObservableType {
|
|||
}
|
||||
}
|
||||
|
||||
fileprivate let dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
|
||||
private let dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
|
||||
|
||||
fileprivate func logEvent(_ identifier: String, dateFormat: DateFormatter, content: String) {
|
||||
private func logEvent(_ identifier: String, dateFormat: DateFormatter, content: String) {
|
||||
print("\(dateFormat.string(from: Date())): \(identifier) -> \(content)")
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ final private class DebugSink<Source: ObservableType, Observer: ObserverType>: S
|
|||
final private class Debug<Source: ObservableType>: Producer<Source.Element> {
|
||||
fileprivate let _identifier: String
|
||||
fileprivate let _trimOutput: Bool
|
||||
fileprivate let _source: Source
|
||||
private let _source: Source
|
||||
|
||||
init(source: Source, identifier: String?, trimOutput: Bool, file: String, line: UInt, function: String) {
|
||||
self._trimOutput = trimOutput
|
||||
|
@ -84,7 +84,7 @@ final private class Debug<Source: ObservableType>: Producer<Source.Element> {
|
|||
}
|
||||
else {
|
||||
let trimmedFile: String
|
||||
if let lastIndex = file.lastIndexOf("/") {
|
||||
if let lastIndex = file.lastIndex(of: "/") {
|
||||
trimmedFile = String(file[file.index(after: lastIndex) ..< file.endIndex])
|
||||
}
|
||||
else {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue