This repository was archived by the owner on May 28, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 804
Protecting UIButton's CGSize calculations against nil receivers; more… #2094
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -371,21 +371,32 @@ - (CGRect)contentRectForBounds:(CGRect)bounds { | |
| @Status Interoperable | ||
| */ | ||
| - (CGRect)imageRectForContentRect:(CGRect)contentRect { | ||
| CGSize titleSize = [self.currentTitle sizeWithFont:self.font]; | ||
| // TODO #1365 :: Currently cannot assume getting size from nil will return CGSizeZero | ||
| CGSize imageSize = CGSizeZero; | ||
| CGRect insetsRect = UIEdgeInsetsInsetRect(contentRect, self.imageEdgeInsets); | ||
|
|
||
| if (!self.currentImage) { | ||
| ///////////////////////////////////////////////////////////////////// | ||
| // Note: #1365 All size calculations here must check for nil, | ||
| // as we cannot assume getting a size from nil will return CGSizeZero | ||
| ///////////////////////////////////////////////////////////////////// | ||
| UIImage* currentImage = self.currentImage; | ||
| if (!currentImage) { | ||
| // No image, so we return zero for the entire content rect | ||
| return CGRectZero; | ||
| } | ||
|
|
||
| imageSize = self.currentImage.size; | ||
| // Grab the size of the current title | ||
| // TODO: Should we be asking our label for this? | ||
| NSString* currentTitle = self.currentTitle; | ||
| CGSize titleSize = CGSizeZero; | ||
| if (currentTitle) { | ||
| // We need to round the font size to the nearest pixel value to avoid rounding errors when used in conjunction with the | ||
| // frame values that are rounded by UIView. | ||
| titleSize = doPixelRound([currentTitle sizeWithFont:self.font]); | ||
| } | ||
|
|
||
| CGSize totalSize = imageSize; | ||
| // Now calculate the total size based on the image and title sizes | ||
| CGSize totalSize = currentImage.size; | ||
| totalSize.width += titleSize.width; | ||
|
|
||
| // Get the frame based on the control alignment. | ||
| CGRect insetsRect = UIEdgeInsetsInsetRect(contentRect, self.imageEdgeInsets); | ||
| CGRect ret = calculateContentRect(self, totalSize, insetsRect); | ||
|
|
||
| ret.size.width -= titleSize.width; | ||
|
|
@@ -404,19 +415,34 @@ - (CGRect)imageRectForContentRect:(CGRect)contentRect { | |
| @Status Interoperable | ||
| */ | ||
| - (CGRect)titleRectForContentRect:(CGRect)contentRect { | ||
| // TODO: Should we be asking our label for its intrinsicContentSize? | ||
| // We need to round the font size to the nearest pixel value to avoid rounding errors when used in conjunction with the | ||
| // frame values that are rounded by UIView. | ||
| CGSize titleSize = doPixelRound([self.currentTitle sizeWithFont:self.font]); | ||
| CGSize totalSize = titleSize; | ||
| // TODO #1365 :: Currently cannot assume getting size from nil will return CGSizeZero | ||
| CGSize imageSize = self.currentImage ? [self.currentImage size] : CGSizeZero; | ||
| CGRect insetsRect = UIEdgeInsetsInsetRect(contentRect, self.titleEdgeInsets); | ||
| ///////////////////////////////////////////////////////////////////// | ||
| // Note: #1365 All size calculations here must check for nil, | ||
| // as we cannot assume getting a size from nil will return CGSizeZero | ||
| ///////////////////////////////////////////////////////////////////// | ||
|
|
||
| if ([self currentTitle].length == 0) { | ||
| // Grab the size of the current title | ||
| // TODO: Should we be asking our label for this? | ||
| NSString* currentTitle = self.currentTitle; | ||
| CGSize titleSize = CGSizeZero; | ||
| if (currentTitle && currentTitle.length > 0) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. per oliver's comment;
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i know, but if we don't leave the explicit nil check, someone may forget next time they come through here? In reply to: 103035907 [](ancestors = 103035907) |
||
| // We need to round the font size to the nearest pixel value to avoid rounding errors when used in conjunction with the | ||
| // frame values that are rounded by UIView. | ||
| titleSize = doPixelRound([currentTitle sizeWithFont:self.font]); | ||
| } else { | ||
| // No title, so we return zero for the entire content rect | ||
| return CGRectZero; | ||
| } | ||
|
|
||
| // Grab the size of the current image | ||
| UIImage* currentImage = self.currentImage; | ||
| CGSize imageSize = CGSizeZero; | ||
| if (currentImage) { | ||
| imageSize = [currentImage size]; | ||
| } | ||
|
|
||
| CGRect insetsRect = UIEdgeInsetsInsetRect(contentRect, self.titleEdgeInsets); | ||
|
|
||
| CGSize totalSize = titleSize; | ||
| totalSize.width += imageSize.width; | ||
|
|
||
| // Get the frame based on the control alignment. | ||
|
|
@@ -951,32 +977,35 @@ - (UIImageView*)imageView { | |
| - (CGSize)intrinsicContentSize { | ||
| CGSize ret = CGSizeZero; | ||
|
|
||
| UIImage* img = self.currentImage; | ||
| UIEdgeInsets contentInsets = self.contentEdgeInsets; | ||
|
|
||
| // TODO: Should we be asking our label for its intrinsicContentSize? | ||
| // We need to round the font size to the nearest pixel value to avoid rounding errors when used in conjunction with the | ||
| // frame values that are rounded by UIView. | ||
| CGSize textSize = doPixelRound([[self currentTitle] sizeWithFont:self.font]); | ||
| //////////////////////////////////////////////////////////////////// | ||
| // Note: #1365 All size calculations here must check for nil, | ||
| // as we cannot assume getting a size from nil will return CGSizeZero | ||
| //////////////////////////////////////////////////////////////////// | ||
|
|
||
| // Size should at least fit the image in a normal state. | ||
| if (img != nil) { | ||
| ret = [img size]; | ||
| UIImage* currentImage = self.currentImage; | ||
| if (currentImage) { | ||
| ret = [currentImage size]; | ||
| } | ||
|
|
||
| if ([self currentTitle].length) { | ||
| // TODO: Should we be asking our label for its intrinsicContentSize? | ||
| CGSize textSize = CGSizeZero; | ||
| NSString* currentTitle = self.currentTitle; | ||
| if (currentTitle && (currentTitle.length > 0)) { | ||
| // We need to round the font size to the nearest pixel value to avoid rounding errors when used in conjunction with the | ||
| // frame values that are rounded by UIView. | ||
| textSize = doPixelRound([currentTitle sizeWithFont:self.font]); | ||
| ret.width = std::max(textSize.width, ret.width); | ||
| ret.height = std::max(textSize.height, ret.height); | ||
| } | ||
|
|
||
| // If we have a background, its image size dictates the smallest size. | ||
| if (self.currentBackgroundImage) { | ||
| UIImage* background = self.currentBackgroundImage; | ||
| // TODO #1365 :: Currently cannot assume getting size from nil will return CGSizeZero | ||
| CGSize size = background ? [background size] : CGSizeZero; | ||
|
|
||
| ret.width = std::max(size.width, ret.width); | ||
| ret.height = std::max(size.height, ret.height); | ||
| UIEdgeInsets contentInsets = self.contentEdgeInsets; | ||
| UIImage* currentBackgroundImage = self.currentBackgroundImage; | ||
| if (currentBackgroundImage) { | ||
| CGSize imageSize = [currentBackgroundImage size]; | ||
| ret.width = std::max(imageSize.width, ret.width); | ||
| ret.height = std::max(imageSize.height, ret.height); | ||
| } else if (UIEdgeInsetsEqualToEdgeInsets(contentInsets, UIEdgeInsetsZero)) { | ||
| // Min values found emperically; set if no contentInsets are set. | ||
| ret.width = std::max(ret.width, 30.0f); | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[currentTitle length] > 0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure, and i think the safest approach is to stick to functional equivalence just to be safe
In reply to: 103035505 [](ancestors = 103035505)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you saying we should not do the same check like below: currentTitle && currentTitle.length > 0?
In reply to: 103035505 [](ancestors = 103035505)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm saying, 'i don't know'; do we have tests to validate this behavior? I just went through and kept the existing functionality. The other functions check the length, and this one doesn't, because that's how it worked previously.
In reply to: 103035705 [](ancestors = 103035705,103035505)