For iOS7, I used the UIButton titleLabel.frame.size.width property to determine the width of my button title under different localisations so I could p
So we can try this code :
func withTitleAndImageAlign(title:String,image:UIImage,RL_Space:CGFloat) {
setNeedsLayout()
layoutIfNeeded()
let buttonWidth = frame.size.width
let textWidth = titleLabel?.frame.size.width
let imageWidth = imageView?.frame.size.width
let lim = buttonWidth - (textWidth! + imageWidth! + (2 * RL_Space) )
imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: lim)
titleEdgeInsets = UIEdgeInsets(top: 0, left: lim, bottom: 0, right: 0)
}
If you are then setting an image next to a button after getting the frame, you can use
[theButton setTitle: @"theTitle" forState:UIControlStateNormal];
[theButton setImage: theImage forState:UIControlStateNormal];
[theButton setNeedsLayout];
[theButton layoutIfNeeded];
[theButton setImageEdgeInsets: UIEdgeInsetsMake(6, transactionsButton.titleLabel.frame.size.width + 40.0, 0, 0)];
And in Swift 3, this will do.
self.view.layoutIfNeeded()
Maybe this will not work for you, but I had the same problem when running my code in XCode 6 GM / iOS8 and could not get it to work. It worked randomly and I ended up using a different approach instead of an NSString I used an NSAttributedString as the title.
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:@"Button text"];
NSTextAttachment* textAttachment = [NSTextAttachment new];
textAttachment.image = [UIImage imageNamed:@"Arrows"];
NSAttributedString *finalString = [NSAttributedString attributedStringWithAttachment:textAttachment];
[attributedText appendAttributedString:finalString];
Only caveat is that it’s iOS7 and up, but seems to work flawless.
Turns out I had greatly over engineered myself into this problem. I took out all of my content inset code and therefore didn't need to find the frame.size. I now just centre the button titles and all is well!
Still seems there is an issue with getting the frame.size but for my needs, I can work around it.
I resolved it. App run on iOS8, build by Xcode 6, not update frame right after UIButton setTitle, setTitleEdgeInsets. It will wait for next UI update. So, if you get frame of titleLabel, you will get CGRectZero.
Solution:
Call below methods after set UI property, to update layout immediately:
[self setNeedsLayout];
[self layoutIfNeeded];
Or:
titleFrame, use self.titleLabel.frame.Or:
Set the title text, then make a sizeToFit for the title label, and try to get the titleLabel.frame.size.width
[myButton setTitle:@"My Title" forState:UIControlStateNormal];
[myButton.titleLabel sizeToFit];