Skip to content

Commit fe61c0e

Browse files
committed
update to v2.9.3
- autorelease pools for lower memory footprint - optimizations for internal structures to avoid objc_msgSend - no_escape attribute throughout (will avoid warnings on XC 10) - misc cleanup - enable parallelized unit tests (XC 10 only) - unit tests go from 85s to 62s - splitting up TwitterImagePipelineTests will make things even faster, todo for the future
1 parent a312d62 commit fe61c0e

28 files changed

+322
-242
lines changed

CHANGELOG.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1-
# Twitter Logging Service Change Log
1+
# Twitter Image Pipeline Change Log
22

33
## Info
44

5-
**Document version:** 2.9.2
5+
**Document version:** 2.9.3
66

7-
**Last updated:** 04/27/2018
7+
**Last updated:** 05/16/2018
88

99
**Author:** Nolan O'Brien
1010

1111
## History
1212

13+
### 2.9.3
14+
15+
- Add `notifyAllFetchHelpersToRetryFailedLoads` class method to `TIPImageViewFetchHelper`
16+
- This will offer an easy way for consuming apps to trigger a reload of failed image fetches when the network conditions change
17+
1318
### 2.9.2
1419

1520
- Add `TIPRenderImage` util function

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,3 +360,12 @@ Inspecting pipelines is asynchronously done on background threads before the ins
360360
called on the main thread. This can provide very useful debugging info. As an example, Twitter has
361361
built in UI and tools that use the inspection support of *TIP* for internal builds.
362362
363+
# License
364+
365+
Copyright 2015-2018 Twitter, Inc.
366+
367+
Licensed under the Apache License, Version 2.0: https://www.apache.org/licenses/LICENSE-2.0
368+
369+
# Security Issues?
370+
371+
Please report sensitive security issues via Twitter's bug-bounty program (https://hackerone.com/twitter) rather than GitHub.

TwitterImagePipeline.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'TwitterImagePipeline'
3-
s.version = '2.9.2'
3+
s.version = '2.9.3'
44
s.summary = 'Twitter Image Pipeline is a robust and performant image loading and caching framework for iOS'
55
s.description = 'Twitter created a framework for image loading/caching in order to fulfill the numerous needs of Twitter for iOS including being fast, safe, modular and versatile.'
66
s.homepage = 'https://github.com/twitter/ios-twitter-logging-service'

TwitterImagePipeline.xcodeproj/xcshareddata/xcschemes/TwitterImagePipeline.xcscheme renamed to TwitterImagePipeline.xcodeproj/xcshareddata/xcschemes/GraphicsRendererSpeed.xcscheme

Lines changed: 20 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
LastUpgradeVersion = "0930"
44
version = "1.3">
55
<BuildAction
6-
parallelizeBuildables = "NO"
7-
buildImplicitDependencies = "NO">
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES">
88
<BuildActionEntries>
99
<BuildActionEntry
1010
buildForTesting = "YES"
@@ -14,23 +14,9 @@
1414
buildForAnalyzing = "YES">
1515
<BuildableReference
1616
BuildableIdentifier = "primary"
17-
BlueprintIdentifier = "8BFBD3461AA77DB2007A08DD"
18-
BuildableName = "libTwitterImagePipeline.a"
19-
BlueprintName = "TwitterImagePipeline"
20-
ReferencedContainer = "container:TwitterImagePipeline.xcodeproj">
21-
</BuildableReference>
22-
</BuildActionEntry>
23-
<BuildActionEntry
24-
buildForTesting = "YES"
25-
buildForRunning = "NO"
26-
buildForProfiling = "NO"
27-
buildForArchiving = "NO"
28-
buildForAnalyzing = "NO">
29-
<BuildableReference
30-
BuildableIdentifier = "primary"
31-
BlueprintIdentifier = "8BA975521D77E2C900601D70"
32-
BuildableName = "TIPTests.framework"
33-
BlueprintName = "TIPTests"
17+
BlueprintIdentifier = "8B93D8D220864CAC00CFB01A"
18+
BuildableName = "GraphicsRendererSpeed.app"
19+
BlueprintName = "GraphicsRendererSpeed"
3420
ReferencedContainer = "container:TwitterImagePipeline.xcodeproj">
3521
</BuildableReference>
3622
</BuildActionEntry>
@@ -42,23 +28,13 @@
4228
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
4329
shouldUseLaunchSchemeArgsEnv = "YES">
4430
<Testables>
45-
<TestableReference
46-
skipped = "NO">
47-
<BuildableReference
48-
BuildableIdentifier = "primary"
49-
BlueprintIdentifier = "8BFBD3511AA77DB2007A08DD"
50-
BuildableName = "TwitterImagePipelineTests.xctest"
51-
BlueprintName = "TwitterImagePipelineTests"
52-
ReferencedContainer = "container:TwitterImagePipeline.xcodeproj">
53-
</BuildableReference>
54-
</TestableReference>
5531
</Testables>
5632
<MacroExpansion>
5733
<BuildableReference
5834
BuildableIdentifier = "primary"
59-
BlueprintIdentifier = "8BFBD3461AA77DB2007A08DD"
60-
BuildableName = "libTwitterImagePipeline.a"
61-
BlueprintName = "TwitterImagePipeline"
35+
BlueprintIdentifier = "8B93D8D220864CAC00CFB01A"
36+
BuildableName = "GraphicsRendererSpeed.app"
37+
BlueprintName = "GraphicsRendererSpeed"
6238
ReferencedContainer = "container:TwitterImagePipeline.xcodeproj">
6339
</BuildableReference>
6440
</MacroExpansion>
@@ -75,15 +51,16 @@
7551
debugDocumentVersioning = "YES"
7652
debugServiceExtension = "internal"
7753
allowLocationSimulation = "YES">
78-
<MacroExpansion>
54+
<BuildableProductRunnable
55+
runnableDebuggingMode = "0">
7956
<BuildableReference
8057
BuildableIdentifier = "primary"
81-
BlueprintIdentifier = "8BFBD3461AA77DB2007A08DD"
82-
BuildableName = "libTwitterImagePipeline.a"
83-
BlueprintName = "TwitterImagePipeline"
58+
BlueprintIdentifier = "8B93D8D220864CAC00CFB01A"
59+
BuildableName = "GraphicsRendererSpeed.app"
60+
BlueprintName = "GraphicsRendererSpeed"
8461
ReferencedContainer = "container:TwitterImagePipeline.xcodeproj">
8562
</BuildableReference>
86-
</MacroExpansion>
63+
</BuildableProductRunnable>
8764
<AdditionalOptions>
8865
</AdditionalOptions>
8966
</LaunchAction>
@@ -93,15 +70,16 @@
9370
savedToolIdentifier = ""
9471
useCustomWorkingDirectory = "NO"
9572
debugDocumentVersioning = "YES">
96-
<MacroExpansion>
73+
<BuildableProductRunnable
74+
runnableDebuggingMode = "0">
9775
<BuildableReference
9876
BuildableIdentifier = "primary"
99-
BlueprintIdentifier = "8BFBD3461AA77DB2007A08DD"
100-
BuildableName = "libTwitterImagePipeline.a"
101-
BlueprintName = "TwitterImagePipeline"
77+
BlueprintIdentifier = "8B93D8D220864CAC00CFB01A"
78+
BuildableName = "GraphicsRendererSpeed.app"
79+
BlueprintName = "GraphicsRendererSpeed"
10280
ReferencedContainer = "container:TwitterImagePipeline.xcodeproj">
10381
</BuildableReference>
104-
</MacroExpansion>
82+
</BuildableProductRunnable>
10583
</ProfileAction>
10684
<AnalyzeAction
10785
buildConfiguration = "Debug">

TwitterImagePipeline.xcodeproj/xcshareddata/xcschemes/TwitterImagePipeline.framework.xcscheme

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@
5757
shouldUseLaunchSchemeArgsEnv = "YES">
5858
<Testables>
5959
<TestableReference
60-
skipped = "NO">
60+
skipped = "NO"
61+
parallelizable = "YES">
6162
<BuildableReference
6263
BuildableIdentifier = "primary"
6364
BlueprintIdentifier = "8BFBD3511AA77DB2007A08DD"

TwitterImagePipeline/Project/NSOperationQueue+TIPSafety.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ NS_ASSUME_NONNULL_BEGIN
2020
Same as `[NSOperationQueue addOperation:]` but with added safety.
2121
If _op_ returns `YES` for `isAsynchronous`, the operation will be retained for a period that
2222
extends beyond the lifetime of the operation executing to avoid a crash.
23+
If called on an OS version that doesn't have the bug, will just pass through to `addOperation:`
2324
*/
2425
- (void)tip_safeAddOperation:(NSOperation *)op;
2526

2627
@end
2728

2829
NS_ASSUME_NONNULL_END
29-

TwitterImagePipeline/Project/TIPImageDownloadInternalContext.h

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,38 @@
1414
NS_ASSUME_NONNULL_BEGIN
1515

1616
@interface TIPImageDownloadInternalContext : NSObject <TIPImageFetchOperationUnderlyingContext, TIPImageFetchDownloadContext>
17+
{
18+
@public
19+
20+
__unsafe_unretained id<TIPImageFetchDownload> __nullable _download;
21+
TIPImageDiskCacheTemporaryFile * __nullable _temporaryFile;
22+
TIPPartialImage * __nullable _partialImage;
23+
NSString * __nullable _lastModified;
24+
NSDictionary<NSString *, id> * __nullable _decoderConfigMap;
25+
NSError * __nullable _progressStateError;
26+
NSHTTPURLResponse * __nullable _response;
27+
NSUInteger _contentLength;
28+
29+
struct {
30+
BOOL didRequestHydration:1;
31+
BOOL didStart:1;
32+
BOOL didReceiveResponse:1;
33+
BOOL responseStatusCodeIsFailure:1;
34+
BOOL didReceiveData:1;
35+
BOOL didComplete:1;
36+
} _flags;
37+
38+
@private
39+
40+
NSMutableArray<id<TIPImageDownloadDelegate>> * __nonnull _delegates;
41+
}
1742

18-
@property (nonatomic, assign, nullable) id<TIPImageFetchDownload> download;
43+
@property (nonatomic, copy, nullable) NSURLRequest *originalRequest;
1944
@property (nonatomic, copy, nullable) NSURLRequest *hydratedRequest;
2045
@property (nonatomic, nullable) id<TIPImageFetchDownloadClient> client;
2146
@property (nonatomic, nullable) dispatch_queue_t downloadQueue;
2247

23-
@property (nonatomic, copy, nullable) NSURLRequest *originalRequest;
24-
@property (nonatomic, nullable) TIPImageDiskCacheTemporaryFile *temporaryFile;
25-
@property (nonatomic, nullable) TIPPartialImage *partialImage;
26-
@property (nonatomic, copy, nullable) NSString *lastModified;
27-
@property (nonatomic, copy, nullable) NSDictionary<NSString *, id> *decoderConfigMap;
28-
29-
@property (nonatomic, nullable) NSError *progressStateError;
30-
31-
@property (nonatomic) BOOL didRequestHydration;
32-
@property (nonatomic) BOOL didStart;
33-
@property (nonatomic) BOOL didReceiveResponse;
34-
@property (nonatomic) BOOL responseStatusCodeIsFailure;
35-
@property (nonatomic) BOOL didReceiveData;
36-
@property (nonatomic) BOOL didComplete;
37-
38-
@property (nonatomic, nullable) NSHTTPURLResponse *response;
39-
@property (nonatomic) NSUInteger contentLength;
40-
@property (nonatomic, readonly) NSUInteger delegateCount;
48+
@property (nonatomic, readonly) NSUInteger delegateCount; // computed property
4149

4250
- (NSOperationQueuePriority)downloadPriority;
4351
- (nullable id<TIPImageDownloadDelegate>)firstDelegate;

TwitterImagePipeline/Project/TIPImageDownloadInternalContext.m

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515
NS_ASSUME_NONNULL_BEGIN
1616

1717
@implementation TIPImageDownloadInternalContext
18-
{
19-
NSMutableArray<id<TIPImageDownloadDelegate>> *_delegates;
20-
}
2118

2219
- (instancetype)init
2320
{
@@ -73,15 +70,15 @@ - (void)removeDelegate:(id<TIPImageDownloadDelegate>)delegate
7370
NSUInteger count = _delegates.count;
7471
[_delegates removeObject:delegate];
7572
if (count > _delegates.count) {
76-
id<TIPImageFetchDownload> download = self.download;
73+
id<TIPImageFetchDownload> download = _download;
7774
[TIPImageDownloadInternalContext executeDelegate:delegate suspendingQueue:NULL block:^(id<TIPImageDownloadDelegate> blockDelegate) {
7875
[blockDelegate imageDownload:(id)download didCompleteWithPartialImage:nil lastModified:nil byteSize:0 imageType:nil image:nil imageRenderLatency:0.0 statusCode:0 error:[NSError errorWithDomain:TIPImageFetchErrorDomain code:TIPImageFetchErrorCodeCancelled userInfo:nil]];
7976
}];
8077
}
8178
}
8279

8380
- (void)executePerDelegateSuspendingQueue:(nullable dispatch_queue_t)queue
84-
block:(void(^)(id<TIPImageDownloadDelegate>))block;
81+
block:(void(^)(id<TIPImageDownloadDelegate>))block
8582
{
8683
for (id<TIPImageDownloadDelegate> delegate in _delegates) {
8784
[TIPImageDownloadInternalContext executeDelegate:delegate
@@ -91,14 +88,14 @@ - (void)executePerDelegateSuspendingQueue:(nullable dispatch_queue_t)queue
9188

9289
+ (void)executeDelegate:(id<TIPImageDownloadDelegate>)delegate
9390
suspendingQueue:(nullable dispatch_queue_t)queue
94-
block:(void (^)(id<TIPImageDownloadDelegate>))block;
91+
block:(void (^)(id<TIPImageDownloadDelegate>))block
9592
{
9693
dispatch_queue_t delegateQueue = [delegate respondsToSelector:@selector(imageDownloadDelegateQueue)] ? delegate.imageDownloadDelegateQueue : NULL;
9794
if (delegateQueue) {
9895
if (queue) {
9996
dispatch_suspend(queue);
10097
}
101-
dispatch_async(delegateQueue, ^{
98+
tip_dispatch_async_autoreleasing(delegateQueue, ^{
10299
block(delegate);
103100
if (queue) {
104101
dispatch_resume(queue);

0 commit comments

Comments
 (0)