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
0 commit comments