12

When an image view's source is pre-set from the attributes inspector, when/how is the actual path to the file resolved? There don't seem to be any calls to NSBundle, but I may be wrong.

EDIT: I'm trying to swizzle whatever method is called (if possible) to dynamically replace the assets later.

enter image description here

kasrak
  • 470
  • 4
  • 12

2 Answers2

10

None of UIImage initializers or factories are getting called.
I made some research with debugger (on iOS Simulator 7.0.3) and found following:
1) UIImageView which is set up in IB is initialised via -initWithCoder:.
2) In initWithCoder: method decodeObjectForKey: is called. And (!) key named UIImage contains image from IB. This image is set to UIImageView through ivar, not through setImage: setter.
So, seems like IB packs raw image data into XIB / Storyboard while compiling. Nonsense, but true.
That's why we cannot swizzle +imageNamed: or some another factory and should use conditional code to setup images for retina4 and iOS6

EDIT:

Comments show up that hexdumping of compiled IB file has png name inside.

In fact, looking at the output of "hexdump -C BYZ-38-t0r-view-8bC-Xf-vdC.nib " indicates that the filename of the PNG appears in the compiled file. So, it must be loading the file data via the file name from the same bundle.

However, they're still loaded via some internal mechanism, not via imageNamed:

Petro Korienev
  • 4,007
  • 6
  • 34
  • 43
  • Yes...so there is no way to swizzle some method like imageNamed? – jerrygdm Jan 12 '15 at 12:45
  • You can swizzle it, but for this particular task, you'll get no profit – Petro Korienev Jan 12 '15 at 13:56
  • 1
    The comment about "IB packs raw image data into XIB" does not make sense. I just looked at a compiled storyboard and found that the image data is not inlined into the output file BYZ-38-t0r-view-8bC-Xf-vdC.nib. In fact, looking at the output of "hexdump -C BYZ-38-t0r-view-8bC-Xf-vdC.nib " indicates that the filename of the PNG appears in the compiled file. So, it must be loading the file data via the file name from the same bundle. – MoDJ Oct 17 '16 at 21:55
  • @MoDJ thanks for your comment, I've updated answer appropriately. However, I'd ask you to treat your wording more carefully. "This does not make sense" is rather abusive than constructive. – Petro Korienev Oct 18 '16 at 08:30
  • Abusive? Petro, you made an assertion in your writeup that inlining PNG data was "Nonsense, but true." My correcting your mistaken conclusion is not abuse, it is the Socratic method. – MoDJ Oct 18 '16 at 17:05
  • @MoDJ compare my depersonalized statement with yours pointing at exact mistake of mine. My almost-3-years-ago research has given these results and feeling sense of good attitude in SO community I would say something like "My research has shown different results" or "Are you sure in your statement because I've compiled and blah-blah". If you don't think that mutual respect is vital here or don't agree with my arguments I appreciate that, because it's something called THE POINT. However, having THE POINT is not enough, one should be able to deliver it in clear and polite way IMO – Petro Korienev Oct 19 '16 at 08:10
  • @MoDJ also please mind, that my answer has solved OP's problem despite one of assertions inside was false-positive. And the summary is still actual despite on of assertions inside was false-positive. Keeping this in mind, I would correct mistakes on these parts very carefully, probably proposing an edit to an answer, but not commenting something wrong out in the way you did this – Petro Korienev Oct 19 '16 at 08:15
3

iOS will automatically look for your file overflow.png in the same bundle as your xib file. If your xib file is just in your application's target, then by default it looks inside the main bundle.

If you want to programatically load a new image into an image view and your image is inside the main bundle:

UIImage *image = [UIImage imageNamed:@"MyAwesomeImage"];
self.imageView.image = image;

If your image is inside another bundle:

NSBundle *imageBundle = ... // [NSBundle mainBundle] if your image is inside main bundle
NSString *imagePath = [imageBundle pathForResource:@"MyAwesomeImage" ofType:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
self.imageView.image = image;
Sonny Saluja
  • 7,193
  • 2
  • 25
  • 39
  • Yes, but is there any method called to get the path? (See me edit for motivation). – kasrak Jun 04 '13 at 02:46
  • @kasrak, You want the path of the image overflow.png? Is it in the main bundle? – Sonny Saluja Jun 04 '13 at 02:48
  • I don't think I was very clear. I'm wondering how the runtime actually initializes the UIImageView when it loads it from the storyboard/xib. This would allow for automatically replacing images in the app without any code changes. – kasrak Jun 04 '13 at 19:57
  • @andi There is a typo. Try self.imageView.image – Sonny Saluja Sep 23 '15 at 00:43