extension UIFont { func sizeOfString(string: NSString, constrainedToWidth width: Double) -> CGSize { return string.boundingRectWithSize(CGSize(width: width, height: DBL_MAX), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: self], context: nil).size } } extension String { static private var kPBegin = "

" static private var kPEnd = "

" static private var kBBegin = "" static private var kBEnd = "" static private var kBr = "
" static private var kNewLine = "\n" static private var kSpaceSymbol = " " static private var kPreBegin = "
"
    static private var kPreEnd = "
" static private var kTableBegin = " String? { if nil == htmlText { return htmlText } let font = UIFont.systemFontOfSize(12) let compareWidth = 10000.0 var result: NSString = htmlText! var rangeStart = result.rangeOfString(kTableBegin, options: [.CaseInsensitiveSearch]) while rangeStart.location != NSNotFound { let rangeEnd = result.rangeOfString(kTableEnd, options: [.CaseInsensitiveSearch]) if rangeEnd.location != NSNotFound { let rangeTable = NSMakeRange(rangeStart.location, rangeEnd.location+rangeEnd.length - rangeStart.location) let stringTable = result.substringWithRange(rangeTable) let html = Ji(htmlString: stringTable) if let table = html?.rootNode?.firstChild?.firstChild, body = table.firstChild { // html->body->table->tbody->... var data = [[String]]() let trs = body.children if let maxTds = trs.first?.children.count { for i in 0...maxTds-1 { var columnData = [String]() for tr in trs { let tds = tr.children if i < tds.count { let td = tds[i] if let content = String.stringByStripHTML(td.content) { columnData.append(content) } continue } columnData.append("") } data.append(columnData) } } var fixedTable = kBr if data.count > 0 { for i in 0...data[0].count-1 { // columns var maxLength: CGFloat = 0 for j in 0...data.count-1 { // rows let string = data[i][j] let length = font.sizeOfString(string, constrainedToWidth: compareWidth).width if length > maxLength { maxLength = length } } for j in 0...data.count-1 { let string = data[i][j] let length = font.sizeOfString(string, constrainedToWidth: compareWidth).width var spaces = maxLength - length if spaces > 0 { spaces /= font.sizeOfString(kSpaceSymbol, constrainedToWidth: compareWidth).width let count = Int(spaces) if count > 0 { data[i][j] = string + String(count: count, repeatedValue: kSpaceSymbol.characters.first!) } } } } for i in 0...data.count-1 { // rows var row = [String]() for j in 0...data[0].count-1 { // columns row.append(data[j][i]) } fixedTable += kPreBegin + row.joinWithSeparator(kSpaceSymbol + kSpaceSymbol) + kPreEnd + kBr } } result = result.stringByReplacingOccurrencesOfString(stringTable, withString: fixedTable) } else { return result as String } rangeStart = result.rangeOfString(kTableBegin, options: [.CaseInsensitiveSearch]) } else { return result as String } } return result as String } }