Di iOS 7, sizeWithFont:
sekarang sudah usang. Bagaimana saya sekarang meneruskan objek UIFont ke metode penggantian sizeWithAttributes:
?
Di iOS 7, sizeWithFont:
sekarang sudah usang. Bagaimana saya sekarang meneruskan objek UIFont ke metode penggantian sizeWithAttributes:
?
Jawaban:
Gunakan sizeWithAttributes:
sebagai gantinya, yang sekarang membutuhkan NSDictionary
. Masukkan pasangan dengan kunci UITextAttributeFont
dan objek font Anda seperti ini:
CGSize size = [string sizeWithAttributes:
@{NSFontAttributeName: [UIFont systemFontOfSize:17.0f]}];
// Values are fractional -- you should take the ceilf to get equivalent values
CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height));
boundingRectWithSize:options:attributes:context:
sebagai gantinya, dengan menyerahkan CGSizeMake(250.0f, CGFLOAT_MAX)
sebagian besar kasus.
Saya percaya fungsi tersebut sudah usang karena serangkaian NSString+UIKit
fungsi ( sizewithFont:...
, dll) didasarkan pada UIStringDrawing
perpustakaan, yang bukan thread aman. Jika Anda mencoba menjalankannya bukan di utas utama (seperti UIKit
fungsi lainnya ), Anda akan mendapatkan perilaku yang tidak terduga. Khususnya, jika Anda menjalankan fungsi pada banyak utas secara bersamaan, mungkin aplikasi Anda akan macet. Inilah sebabnya mengapa di iOS 6, mereka memperkenalkan boundingRectWithSize:...
metode untuk NSAttributedString
. Ini dibangun di atas NSStringDrawing
perpustakaan dan aman utasnya.
Jika Anda melihat NSString
boundingRectWithSize:...
fungsi baru , ia meminta array atribut dengan cara yang sama dengan a NSAttributeString
. Jika saya harus menebak, NSString
fungsi baru ini di iOS 7 hanyalah pembungkus untuk NSAttributeString
fungsi dari iOS 6.
Pada catatan itu, jika Anda hanya mendukung iOS 6 dan iOS 7, maka saya pasti akan mengubah semua Anda NSString
sizeWithFont:...
menjadi NSAttributeString
boundingRectWithSize
. Ini akan menghemat banyak sakit kepala jika Anda memiliki kasing sudut multi-threading yang aneh! Inilah cara saya mengonversi NSString
sizeWithFont:constrainedToSize:
:
Apa yang dulu:
NSString *text = ...;
CGFloat width = ...;
UIFont *font = ...;
CGSize size = [text sizeWithFont:font
constrainedToSize:(CGSize){width, CGFLOAT_MAX}];
Dapat diganti dengan:
NSString *text = ...;
CGFloat width = ...;
UIFont *font = ...;
NSAttributedString *attributedText =
[[NSAttributedString alloc] initWithString:text
attributes:@{NSFontAttributeName: font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGSize size = rect.size;
Harap perhatikan dokumentasi yang menyebutkan:
Di iOS 7 dan yang lebih baru, metode ini mengembalikan ukuran fraksional (dalam komponen ukuran yang dikembalikan
CGRect
); untuk menggunakan ukuran yang dikembalikan ke ukuran tampilan, Anda harus menggunakan menaikkan nilainya ke bilangan bulat terdekat terdekat menggunakan fungsi ceil.
Jadi untuk mengeluarkan tinggi atau lebar yang dihitung yang akan digunakan untuk mengukur ukuran, saya akan menggunakan:
CGFloat height = ceilf(size.height);
CGFloat width = ceilf(size.width);
Seperti yang Anda lihat sizeWithFont
di situs Pengembang Apple itu sudah usang jadi kami perlu menggunakannya sizeWithAttributes
.
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
NSString *text = @"Hello iOS 7.0";
if (SYSTEM_VERSION_LESS_THAN(@"7.0")) {
// code here for iOS 5.0,6.0 and so on
CGSize fontSize = [text sizeWithFont:[UIFont fontWithName:@"Helvetica"
size:12]];
} else {
// code here for iOS 7.0
CGSize fontSize = [text sizeWithAttributes:
@{NSFontAttributeName:
[UIFont fontWithName:@"Helvetica" size:12]}];
}
[NSObject respondsToSelector:]
metode seperti di sini: stackoverflow.com/a/3863039/1226304
Saya membuat kategori untuk menangani masalah ini, ini dia:
#import "NSString+StringSizeWithFont.h"
@implementation NSString (StringSizeWithFont)
- (CGSize) sizeWithMyFont:(UIFont *)fontToUse
{
if ([self respondsToSelector:@selector(sizeWithAttributes:)])
{
NSDictionary* attribs = @{NSFontAttributeName:fontToUse};
return ([self sizeWithAttributes:attribs]);
}
return ([self sizeWithFont:fontToUse]);
}
Dengan cara ini Anda hanya perlu mencari / mengganti sizeWithFont:
dengan sizeWithMyFont:
dan Anda siap melakukannya.
Di iOS7 saya membutuhkan logika untuk mengembalikan ketinggian yang benar untuk tampilan tabel: metode heightForRowAtIndexPath, tetapi sizeWithAttributes selalu mengembalikan ketinggian yang sama terlepas dari panjang string karena tidak tahu bahwa itu akan dimasukkan ke dalam sel tabel lebar tetap . Saya menemukan ini bekerja bagus untuk saya dan menghitung ketinggian yang benar dengan mempertimbangkan lebar untuk sel tabel! Ini berdasarkan jawaban Mr. T di atas.
NSString *text = @"The text that I want to wrap in a table cell."
CGFloat width = tableView.frame.size.width - 15 - 30 - 15; //tableView width - left border width - accessory indicator - right border width
UIFont *font = [UIFont systemFontOfSize:17];
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:@{NSFontAttributeName: font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGSize size = rect.size;
size.height = ceilf(size.height);
size.width = ceilf(size.width);
return size.height + 15; //Add a little more padding for big thumbs and the detailText label
Label multi-garis menggunakan ketinggian dinamis mungkin memerlukan informasi tambahan untuk mengatur ukuran dengan benar. Anda dapat menggunakan sizeWithAttributes dengan UIFont dan NSParagraphStyle untuk menentukan font dan mode line-break.
Anda akan menentukan Gaya Paragraf dan menggunakan NSDictionary seperti ini:
// set paragraph style
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setLineBreakMode:NSLineBreakByWordWrapping];
// make dictionary of attributes with paragraph style
NSDictionary *sizeAttributes = @{NSFontAttributeName:myLabel.font, NSParagraphStyleAttributeName: style};
// get the CGSize
CGSize adjustedSize = CGSizeMake(label.frame.size.width, CGFLOAT_MAX);
// alternatively you can also get a CGRect to determine height
CGRect rect = [myLabel.text boundingRectWithSize:adjustedSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:sizeAttributes
context:nil];
Anda dapat menggunakan properti CGSize 'customizedSize' atau CGRect sebagai rect.size.height jika Anda mencari ketinggian.
Info lebih lanjut tentang NSParagraphStyle di sini: https://developer.apple.com/library/mac/documentation/cocoa/reference/applicationkit/classes/NSParagraphStyle_Class/Reference/Reference.html
// max size constraint
CGSize maximumLabelSize = CGSizeMake(184, FLT_MAX)
// font
UIFont *font = [UIFont fontWithName:TRADE_GOTHIC_REGULAR size:20.0f];
// set paragraph style
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
// dictionary of attributes
NSDictionary *attributes = @{NSFontAttributeName:font,
NSParagraphStyleAttributeName: paragraphStyle.copy};
CGRect textRect = [string boundingRectWithSize: maximumLabelSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
CGSize expectedLabelSize = CGSizeMake(ceil(textRect.size.width), ceil(textRect.size.height));
Buat fungsi yang mengambil instance UILabel. dan mengembalikan CGSize
CGSize constraint = CGSizeMake(label.frame.size.width , 2000.0);
// Adjust according to requirement
CGSize size;
if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0){
NSRange range = NSMakeRange(0, [label.attributedText length]);
NSDictionary *attributes = [label.attributedText attributesAtIndex:0 effectiveRange:&range];
CGSize boundingBox = [label.text boundingRectWithSize:constraint options: NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size;
size = CGSizeMake(ceil(boundingBox.width), ceil(boundingBox.height));
}
else{
size = [label.text sizeWithFont:label.font constrainedToSize:constraint lineBreakMode:label.lineBreakMode];
}
return size;
tableView.estimatedRowHeight = 68.0 tableView.rowHeight = UITableViewAutomaticDimension
Solusi alternatif-
CGSize expectedLabelSize;
if ([subTitle respondsToSelector:@selector(sizeWithAttributes:)])
{
expectedLabelSize = [subTitle sizeWithAttributes:@{NSFontAttributeName:subTitleLabel.font}];
}else{
expectedLabelSize = [subTitle sizeWithFont:subTitleLabel.font constrainedToSize:subTitleLabel.frame.size lineBreakMode:NSLineBreakByWordWrapping];
}
Membangun di @bitsand, ini adalah metode baru yang saya tambahkan ke kategori NSString + Extras saya:
- (CGRect) boundingRectWithFont:(UIFont *) font constrainedToSize:(CGSize) constraintSize lineBreakMode:(NSLineBreakMode) lineBreakMode;
{
// set paragraph style
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setLineBreakMode:lineBreakMode];
// make dictionary of attributes with paragraph style
NSDictionary *sizeAttributes = @{NSFontAttributeName:font, NSParagraphStyleAttributeName: style};
CGRect frame = [self boundingRectWithSize:constraintSize options:NSStringDrawingUsesLineFragmentOrigin attributes:sizeAttributes context:nil];
/*
// OLD
CGSize stringSize = [self sizeWithFont:font
constrainedToSize:constraintSize
lineBreakMode:lineBreakMode];
// OLD
*/
return frame;
}
Saya hanya menggunakan ukuran frame yang dihasilkan.
Anda masih bisa menggunakan sizeWithFont
. tetapi, di iOS> = 7.0 metode menyebabkan crash jika string berisi spasi awal dan akhir atau garis akhir \n
.
Memotong teks sebelum menggunakannya
label.text = [label.text stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
Itu juga mungkin berlaku untuk sizeWithAttributes
dan [label sizeToFit]
.
juga, setiap kali Anda memiliki nsstringdrawingtextstorage message sent to deallocated instance
perangkat iOS 7.0 itu berurusan dengan ini.
Lebih baik gunakan dimensi otomatis (Swift):
tableView.estimatedRowHeight = 68.0
tableView.rowHeight = UITableViewAutomaticDimension
NB: 1. Prototipe UITableViewCell harus dirancang dengan baik (untuk contoh jangan lupa setel UILabel.numberOfLines = 0 dll) 2. Hapus metode HeightForRowAtIndexPath
VIDEO: https://youtu.be/Sz3XfCsSb6k
Jawaban yang diterima di Xamarin adalah (gunakan sizeWithAttributes dan UITextAttributeFont):
UIStringAttributes attributes = new UIStringAttributes
{
Font = UIFont.SystemFontOfSize(17)
};
var size = text.GetSizeUsingAttributes(attributes);
Sebagai jawaban @Ayush:
Seperti yang Anda lihat
sizeWithFont
di situs Pengembang Apple itu sudah usang jadi kami perlu menggunakannyasizeWithAttributes
.
Nah, seandainya pada 2019+ Anda mungkin menggunakan Swift dan String
bukannya Objective-c dan NSString
, inilah cara yang benar untuk mendapatkan ukuran huruf String
dengan font yang telah ditentukan:
let stringSize = NSString(string: label.text!).size(withAttributes: [.font : UIFont(name: "OpenSans-Regular", size: 15)!])
- (CGSize) sizeWithMyFont:(UIFont *)fontToUse
{
if ([self respondsToSelector:@selector(sizeWithAttributes:)])
{
NSDictionary* attribs = @{NSFontAttributeName:fontToUse};
return ([self sizeWithAttributes:attribs]);
}
return ([self sizeWithFont:fontToUse]);
}
Berikut ini adalah setara monotouch jika ada yang membutuhkannya:
/// <summary>
/// Measures the height of the string for the given width.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="font">The font.</param>
/// <param name="width">The width.</param>
/// <param name="padding">The padding.</param>
/// <returns></returns>
public static float MeasureStringHeightForWidth(this string text, UIFont font, float width, float padding = 20)
{
NSAttributedString attributedString = new NSAttributedString(text, new UIStringAttributes() { Font = font });
RectangleF rect = attributedString.GetBoundingRect(new SizeF(width, float.MaxValue), NSStringDrawingOptions.UsesLineFragmentOrigin, null);
return rect.Height + padding;
}
yang bisa digunakan seperti ini:
public override float GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
//Elements is a string array
return Elements[indexPath.Row].MeasureStringHeightForWidth(UIFont.SystemFontOfSize(UIFont.LabelFontSize), tableView.Frame.Size.Width - 15 - 30 - 15);
}
CGSize maximumLabelSize = CGSizeMake(label.frame.size.width, FLT_MAX);
CGSize expectedLabelSize = [label sizeThatFits:maximumLabelSize];
float heightUse = expectedLabelSize.height;
Coba sintaks ini:
NSAttributedString *attributedText =
[[NSAttributedString alloc] initWithString:text
attributes:@{NSFontAttributeName: font}];
Tak satu pun dari ini bekerja untuk saya di ios 7. Inilah yang akhirnya saya lakukan. Saya menempatkan ini di kelas sel khusus saya dan memanggil metode dalam metode heightForCellAtIndexPath saya.
Sel saya terlihat mirip dengan sel deskripsi saat melihat aplikasi di app store.
Pertama di storyboard, atur label Anda ke 'attributedText', atur jumlah baris menjadi 0 (yang akan mengubah ukuran label secara otomatis (hanya 6 + lebih)) dan atur ke bungkus kata.
Lalu saya hanya menambahkan semua ketinggian isi sel di Kelas Sel kustom saya. Dalam kasus saya, saya memiliki Label di bagian atas yang selalu bertuliskan "Keterangan" (_descriptionHeadingLabel), label yang lebih kecil yang ukuran variabel yang berisi deskripsi aktual (_descriptionLabel) kendala dari bagian atas sel ke pos (_descriptionHeadingLabelTopConstraint) . Saya juga menambahkan 3 ke spasi sedikit di bagian bawah (tentang jumlah yang sama tempat apel pada sel jenis subtitle.)
- (CGFloat)calculateHeight
{
CGFloat width = _descriptionLabel.frame.size.width;
NSAttributedString *attributedText = _descriptionLabel.attributedText;
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX} options: NSStringDrawingUsesLineFragmentOrigin context:nil];
return rect.size.height + _descriptionHeadingLabel.frame.size.height + _descriptionHeadingLabelTopConstraint.constant + 3;
}
Dan dalam delegasi Table View saya:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
if (indexPath.row == 0) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"descriptionCell"];
DescriptionCell *descriptionCell = (DescriptionCell *)cell;
NSString *text = [_event objectForKey:@"description"];
descriptionCell.descriptionLabel.text = text;
return [descriptionCell calculateHeight];
}
return 44.0f;
}
Anda bisa mengubah pernyataan if menjadi sedikit 'lebih pintar' dan benar-benar mendapatkan pengenal sel dari semacam sumber data. Dalam kasus saya sel-sel akan dikodekan dengan keras karena akan ada jumlah yang tetap dari mereka dalam urutan tertentu.
boundingRectWithSize
di ios 9.2 masalah sekarang, hasilnya berbeda dengan ios <9.2. Anda menemukan atau mengetahui cara terbaik lain untuk membuat ini.
NSString
danUILabel
(tidak SELALU kasusnya, tetapi sering kali demikian), untuk mencegah duplikasi kode / dll, Anda juga dapat mengganti[UIFont systemFontOfSize:17.0f]
denganlabel.font
- membantu pemeliharaan kode dengan merujuk data yang ada vs. Anda mengetiknya beberapa kali atau merujuk konstanta di seluruh tempat, dll