1

Summary:

In subclass of UITextField:

  • [UIColor colorWithRed:green:blue:alpha] causes total app crash
  • [UIColor greenColor] works fine without any problems

How is that possible?

Answer:

As it turns out, the problem is that it was from layoutSubviews that I was calling the method that was using colorWithRed. Apparently colorWithRed allocates extra memory and that causes a problem at that point. (Thanks to Johannes Fahrenkrug for pointing out in a comment that it may well be something else -- see below.)

Detail:

In a ECTextField class that is a subclass of UITextField I get a terrible crash when I make the following call:

[self setTextColor:[UIColor colorWithRed:42/255.0 green:170/255.0 blue:42/255.0 alpha:0.8]];

The app freezes, hangs, and then after a little while I get the following error:

SampleApp(58375,0x34f71a8) malloc: *** mach_vm_map(size=1048576) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
2013-11-14 22:25:11.929 SampleApp[58375:907] *** Terminating app due to uncaught exception 'NSMallocException', reason: '*** NSAllocateObject(): attempt to allocate object of class 'NSPathStore2' failed'
*** First throw call stack:
(0x2362012 0x2166e7e 0x2361deb 0x1b5bcf2 0x1b60148 0x1bdb7a6 0x120f8a3 0x10ccaf2 0x96b14e4 0x10cc84e 0x96b1542 0x130c42 0x120491 0x120308 0x10fb2dd 0x217a6b0 0x3dbfc0 0x3d033c 0x3d0150 0x34e0bc 0x34f227 0x34f8e2 0x232aafe 0x232aa3d 0x23087c2 0x2307f44 0x2307e1b 0x35647e3 0x3564668 0x10aaffc 0x798d 0x25a5)
libc++abi.dylib: terminate called throwing an exception

Strangely enough everything works fine if I replace that line of code with the following:

[self setTextColor:[UIColor greenColor]];

Does anyone know why that might be, and what I could try to fix this problem?

Thanks for any help,

Erik

Erik van der Neut
  • 2,245
  • 2
  • 22
  • 21
  • 2
    Could you provide some more context? This line alone might not be the whole problem. Usinge `[UIColor greenColor]` always returns the same object, whereas `[UIColor colorWithRed:...]` creates a new object (and allocates more memory) every time. – Johannes Fahrenkrug Nov 14 '13 at 13:32
  • Could you post more code? – Johannes Fahrenkrug Nov 14 '13 at 13:35
  • Thanks Johannes. You were right! This crash only happens when I call that from layoutSubViews. It's not a problem when I call it later. So, the extra memory allocation that you are talking about must be an easy that early in the lifecycle of that view... – Erik van der Neut Nov 14 '13 at 13:41

3 Answers3

7

The problem is that you have an infinite loop. If you call [self setTextColor: in layoutSubviews of your UITextField subclass, you create an infinite loop because setTextColor causes layoutSubviews to be called again: UITextView setTextColor changes layout in UITableViewCell

That's why it takes a while for the error to appear: The app runs out of memory. You can probably verify this by running it with Instruments.

Never call anything from layoutSubviews that triggers layoutSubviews.

Community
  • 1
  • 1
Johannes Fahrenkrug
  • 42,912
  • 19
  • 126
  • 165
6

Change it to

[self setTextColor:[UIColor colorWithRed:42.0f/255.0f green:170.0f/255.0f blue:42.0f/255.0f alpha:0.8f]];

component of the color object, specified as a value from 0.0 to 1.0.

Jay Gajjar
  • 2,661
  • 2
  • 21
  • 35
  • Thanks for that. That seems to make sense. Unfortunately, that still causes the exact same crash, so unfortunately that is not the answer :-( I'll edit my original question to have those /255.0 in there... – Erik van der Neut Nov 14 '13 at 13:23
  • http://stackoverflow.com/questions/7272484/what-is-a-nspathstore2-lets-figure-it-out – Jay Gajjar Nov 14 '13 at 13:30
  • are you positive you corrected it like Jay suggested? if even one of those values is an int and not a float, it will crash. EVERY number in there should end with "point zero" – ryan cumley Nov 14 '13 at 13:32
  • 1
    int/float = float... CS Basics 101. Don't know why this answer got upvoted that much, because the original answer works perfect. There has to be another issue. – Marc Nov 14 '13 at 13:41
  • 1
    Yes, positive about that. As it turns out, I should not call the colorWithRed method from layoutSubviews. If I comment it out my call to the method there then the error goes away, while I can still keep calling the method that uses it from other places without problems. See the comment from Johannes Fahrenkrug above. I must say that this is pretty tricky, but a good lesson... – Erik van der Neut Nov 14 '13 at 13:43
1

creating category for color is best. You can reuse your code at as many places you want.

How to create a category?

If you press command+n it will show you a file option Category. Choose from there or create a .h file named UIColor+custom.h and .m named UIColor+custom.m

In .m file define a method:

+ (UIColor *)myColor
{
    return [UIColor colorWithRed:42.0/255.0 green:170.0/255.0 blue:42.0/255.0  alpha:0.8];
}

and declare this method in .h file:

+ (UIColor *) myColor;

now import this category in your viewController like this:

#import "UIColor+custom.h"

and now give your UITextField text color like this:

[self setTextColor:[UIColor myColor]];

Hope this helps.

Community
  • 1
  • 1
Vaibhav Saran
  • 12,848
  • 3
  • 65
  • 75
  • Originally I did something similar (but not exactly the same). I used a constant that pointed to a macro that gives a color through the colorWithRed:green:blue:alpha. That caused the crash, so I stepped back and I put the colorWithRed method in directly:still a crash. When I switched to greenColor as a test, only then the crash went away. How would you explain that..? Anyway, I'll give your suggestion a go... – Erik van der Neut Nov 14 '13 at 13:30
  • may not a solution for me but i like the answer, it is helpful as a short introduction how to create a category. i will share it, thank you. – brush51 Jan 07 '15 at 08:38