Skip to content

Commit 6ee8302

Browse files
committed
Refactor image loading code to separate method
Now we use RCTConvert in debug mode & RCTImageLoader in release.
1 parent f9c84a6 commit 6ee8302

File tree

2 files changed

+76
-30
lines changed

2 files changed

+76
-30
lines changed

ios/RNSBarButtonItem.mm

Lines changed: 67 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#import <React/RCTConvert.h>
33
#import <React/RCTFont.h>
44
#import <React/RCTImageSource.h>
5-
#import <objc/runtime.h>
5+
#import "RCTImageSource+AccessHiddenMembers.h"
66
#import "RNSDefines.h"
77

88
@implementation RNSBarButtonItem {
@@ -22,39 +22,25 @@ - (instancetype)initWithConfig:(NSDictionary<NSString *, id> *)dict
2222

2323
NSString *title = dict[@"title"];
2424
NSDictionary *imageSourceObj = dict[@"imageSource"];
25-
if (imageSourceObj) {
26-
if (imageSourceObj[@"__packager_asset"]) {
27-
self.title = title;
28-
self.image = [RCTConvert UIImage:imageSourceObj];
29-
} else {
30-
RCTImageSource *imageSource = [RCTConvert RCTImageSource:imageSourceObj];
31-
[imageLoader loadImageWithURLRequest:imageSource.request
32-
size:imageSource.size
33-
scale:imageSource.scale
34-
clipped:true
35-
resizeMode:RCTResizeModeContain
36-
progressBlock:^(int64_t progress, int64_t total) {
37-
}
38-
partialLoadBlock:^(UIImage *_Nonnull image) {
39-
}
40-
completionBlock:^(NSError *_Nullable error, UIImage *_Nullable image) {
41-
dispatch_async(dispatch_get_main_queue(), ^{
42-
self.image = image;
43-
self.title = title;
44-
});
45-
}];
46-
}
47-
} else if (title) {
48-
self.title = title;
49-
}
5025
NSString *sfSymbolName = dict[@"sfSymbolName"];
51-
if (sfSymbolName) {
26+
27+
if (imageSourceObj != nil) {
28+
void (^completionAction)(NSError *_Nullable, UIImage *_Nullable) =
29+
^(NSError *_Nullable error, UIImage *_Nullable image) {
30+
self.image = image;
31+
};
32+
[self loadImageSyncFromImageSourceJson:imageSourceObj withImageLoader:imageLoader completionBlock:completionAction];
33+
} else if (sfSymbolName != nil) {
5234
self.image = [UIImage systemImageNamed:sfSymbolName];
5335
}
5436

55-
NSDictionary *titleStyle = dict[@"titleStyle"];
56-
if (titleStyle) {
57-
[self setTitleStyleFromConfig:titleStyle];
37+
if (title != nil) {
38+
self.title = title;
39+
40+
NSDictionary *titleStyle = dict[@"titleStyle"];
41+
if (titleStyle != nil) {
42+
[self setTitleStyleFromConfig:titleStyle];
43+
}
5844
}
5945

6046
id tintColorObj = dict[@"tintColor"];
@@ -332,4 +318,55 @@ - (void)setBadgeFromConfig:(NSDictionary *)badgeObj
332318
}
333319
#endif
334320

321+
/**
322+
* Should be called from UI thread only. If done so, the method **tries** to load the image synchronously.
323+
* There is no guarantee, because in release mode we rely on `RCTImageLoader` implementation details.
324+
* No matter how the image is loaded, `completionBlock` is executed on main queue.
325+
*/
326+
- (void)loadImageSyncFromImageSourceJson:(nonnull NSDictionary *)imageSourceJson
327+
withImageLoader:(nullable RCTImageLoader *)imageLoader
328+
completionBlock:
329+
(void (^_Nonnull)(NSError *_Nullable error, UIImage *_Nullable image))completion
330+
{
331+
RCTAssert(RCTIsMainQueue(), @"[RNScreens] Expected to run on main queue");
332+
333+
RCTImageSource *imageSource = [RCTConvert RCTImageSource:imageSourceJson];
334+
RCTAssert(imageSource != nil, @"[RNScreens] Expected nonnill image source");
335+
336+
// We use `+ [RCTConvert UIImage:]` only in debug mode, because it is deprecated, however
337+
// I haven't found different way to load image synchronously in debug other than
338+
// writing the code manually.
339+
340+
#if !defined(NDEBUG) // We're in debug mode here
341+
if (!imageSource.packagerAsset) {
342+
// This is rather unexpected. In debug mode local asset should be sourced from packager.
343+
RCTLogWarn(@"[RNScreens] Unexpected case during image load: loading not a packager asset");
344+
}
345+
346+
// Try to load anyway.
347+
UIImage *loadedImage = [RCTConvert UIImage:imageSourceJson];
348+
completion(nil, loadedImage);
349+
return;
350+
#else // We're in release mode here
351+
[imageLoader loadImageWithURLRequest:imageSource.request
352+
size:imageSource.size
353+
scale:imageSource.scale
354+
clipped:true
355+
resizeMode:RCTResizeModeContain
356+
progressBlock:^(int64_t progress, int64_t total) {
357+
}
358+
partialLoadBlock:^(UIImage *_Nonnull image) {
359+
}
360+
completionBlock:^(NSError *_Nullable error, UIImage *_Nullable image) {
361+
if (RCTIsMainQueue()) {
362+
completion(error, image);
363+
} else {
364+
dispatch_async(dispatch_get_main_queue(), ^{
365+
completion(error, image);
366+
});
367+
}
368+
}];
369+
#endif
370+
}
371+
335372
@end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
3+
// This field should exist in extension in `RCTImageSource.m`
4+
5+
@interface RCTImageSource (AccessHiddenMembers)
6+
7+
@property (nonatomic, assign) BOOL packagerAsset;
8+
9+
@end

0 commit comments

Comments
 (0)