Let’s start with a NavigationSplitView. It comes with a toggle sidebar button which is positioned and animated properly: (shown or hidden) ⨯ (fullscreen or windowed).
struct ContentView: View {
#NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some View {
NavigationSplitView {
} detail: {
}
}
}
I need a full-width toolbar, expanding from the trailing edge of the toggle button to the window's right edge. Just like this:
Let’s use a placeholder which is expanding in both direction:
struct Toolbar: View {
var body: some View {
Color.red
}
}
The .toolbar modifier does not work, I guess that ToolbarItem does not get the size of its parent view or does not pass that to its children. So it is only 10 pt by 10 pt.
.toolbar {
ToolbarItem(placement: .principal) {
Toolbar()
}
}
My best take was to pair NSHostingView with addTitlebarAccessoryViewController:
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ notification: Notification) {
let window = NSApplication.shared.windows[0]
window.titlebarAppearsTransparent = true
window.titleVisibility = .hidden
let toolbar = Toolbar()
let titlebarAccessoryViewController = NSTitlebarAccessoryViewController()
let titlebarAccessoryHostingView = NSHostingView(rootView: toolbar)
titlebarAccessoryViewController.view = titlebarAccessoryHostingView
titlebarAccessoryViewController.layoutAttribute = .trailing
window.addTitlebarAccessoryViewController(titlebarAccessoryViewController)
let toggle = window.toolbar!.items[0]
let toggleView = toggle.view!
titlebarAccessoryHostingView.translatesAutoresizingMaskIntoConstraints = false
titlebarAccessoryHostingView.leadingAnchor.constraint(equalTo: toggleView.trailingAnchor).isActive = true
}
}
It seems the auto layout constraint is buggy because the following runtime exception is thrown:
2023-01-13 14:09:41.128026+0700 FullWidthToolbar[40901:1231494] *** Assertion failure in -[NSTitlebarAccessoryViewController _auxiliaryViewFrameChanged:], NSTitlebarAccessoryViewController.m:341
2023-01-13 14:09:41.128277+0700 FullWidthToolbar[40901:1231494] [General] changing the view's origin is not allowed
2023-01-13 14:09:41.132215+0700 FullWidthToolbar[40901:1231494] [General] (
0 CoreFoundation 0x00000001862e33e8 __exceptionPreprocess + 176
1 libobjc.A.dylib 0x0000000185e2eea8 objc_exception_throw + 60
2 Foundation 0x0000000187226910 -[NSCalendarDate initWithCoder:] + 0
3 AppKit 0x000000018954f764 -[NSTitlebarAccessoryViewController _auxiliaryViewFrameChanged:] + 376
Is this approach promising? How to fix the auto layout constraint?
I’ve tried to set the size of the toolbar using a GeometryReader, unfortunately, it makes the (show/hide sidebar, fullscreen enter/exit, resizing, etc.) animation glitchy.
How to define separate constraints for iPhone 8 and 8+?
Since both have different width. Is it possible to differentiate it via storyboard.
Basically I want to set different x and y margins for both phones.
No you can't separate layout for iPhone 8 and 8+ in storyboard.because Autolayout is based on size class and there is no size class available that separate iphone 8 and 8+.
for more info : https://medium.com/#craiggrummitt/size-classes-in-interface-builder-in-xcode-8-74f20a541195.
Custom constraint class
IBDesignable & IBInspectable
import UIKit
#IBDesignable
class MyConstraint: NSLayoutConstraint {
#IBInspectable
var iPhone8: CGFloat = 0 {
didSet {
if UIScreen.main.bounds.maxY == 667 &&
UIScreen.main.bounds.maxX == 375 {
constant = iPhone8
}
}
}
#IBInspectable
var iPhone8Plus: CGFloat = 0 {
didSet {
if UIScreen.main.bounds.maxX == 414 &&
UIScreen.main.bounds.maxY == 736 {
constant = iPhone8Plus
}
}
}
}
Set constraint custom class
I am newbie to programming currently. Im trying to save a core data object but at the moment I have a error with saving the Coredata with displaying the error. Focussing on the save function.
)
libc++abi.dylib: terminating with uncaught exception of type NSException.
//
// ViewController.swift
// HitList
//
//
import UIKit
import CoreData
class ViewController: UIViewController, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
//Change “names” to “people” and [String] to [NSManagedObject]
var people = [NSManagedObject]()
#IBAction func addName(sender: AnyObject) {
let alert = UIAlertController(title: "New Name", message: "Add a new name", preferredStyle: .Alert)
let saveAction = UIAlertAction(title: "Save",
style: .Default,
handler: { (action:UIAlertAction) -> Void in
let textField = alert.textFields!.first
self.saveName(textField!.text!)
self.tableView.reloadData()
})
let cancelAction = UIAlertAction(title: "Cancel", style: .Default) {
(action: UIAlertAction) -> Void in
}
alert.addTextFieldWithConfigurationHandler {
(textField: UITextField) -> Void in
}
alert.addAction(saveAction)
alert.addAction(cancelAction)
presentViewController(alert, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
title = "\"The List\""
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell")
}
// MARK: UITableViewDataSource
func tableView(tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return people.count
}
func tableView(tableView: UITableView,
cellForRowAtIndexPath
indexPath: NSIndexPath) -> UITableViewCell {
let cell =
tableView.dequeueReusableCellWithIdentifier("Cell")
let person = people[indexPath.row]
cell!.textLabel!.text =
person.valueForKey("name") as? String
return cell!
}
func saveName(name: String) {
//1
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
//2
let entity = NSEntityDescription.entityForName("Person",
inManagedObjectContext:managedContext)
let person = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext: managedContext)
//3
person.setValue(name, forKey: "name")
//4
do {
try managedContext.save()
//5
people.append(person)
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIButton copyWithZone:]: unrecognized selector sent to instance 0x7f8089631d50'
*** First throw call stack:
(
0 CoreFoundation 0x000000010d6dde65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010f41ddeb objc_exception_throw + 48
2 CoreFoundation 0x000000010d6e648d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x000000010d63390a ___forwarding___ + 970
4 CoreFoundation 0x000000010d6334b8 _CF_forwarding_prep_0 + 120
5 CoreFoundation 0x000000010d5ad652 CFStringCreateCopy + 242
6 libswiftCore.dylib 0x000000010f9d52d8 _TTSf4g_d___TFSSCfMSSFT12_cocoaStringPSs9AnyObject__SS + 104
7 libswiftCore.dylib 0x000000010f99c9c3 _TFSSCfMSSFT12_cocoaStringPSs9AnyObject__SS + 19
8 libswiftFoundation.dylib 0x000000010fd6e260 _TF10Foundation24_convertNSStringToStringFGSqCSo8NSString_SS + 16
9 Gill 0x000000010d168486 _TToFC4Gill14ViewController8saveNamefS0_FSST_ + 54
10 UIKit 0x000000010defc194 -[UIApplication sendAction:to:from:forEvent:] + 92
11 UIKit 0x000000010e06b6fc -[UIControl sendAction:to:forEvent:] + 67
12 UIKit 0x000000010e06b9c8 -[UIControl _sendActionsForEvents:withEvent:] + 311
13 UIKit 0x000000010e06aaf8 -[UIControl touchesEnded:withEvent:] + 601
14 UIKit 0x000000010df6b49b -[UIWindow _sendTouchesForEvent:] + 835
15 UIKit 0x000000010df6c1d0 -[UIWindow sendEvent:] + 865
16 UIKit 0x000000010df1ab66 -[UIApplication sendEvent:] + 263
17 UIKit 0x000000010def4d97 _UIApplicationHandleEventQueue + 6844
18 CoreFoundation 0x000000010d609a31 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
19 CoreFoundation 0x000000010d5ff95c __CFRunLoopDoSources0 + 556
20 CoreFoundation 0x000000010d5fee13 __CFRunLoopRun + 867
21 CoreFoundation 0x000000010d5fe828 CFRunLoopRunSpecific + 488
22 GraphicsServices 0x0000000111d1dad2 GSEventRunModal + 161
23 UIKit 0x000000010defa610 UIApplicationMain + 171
24 Gill 0x000000010d16b2ad main + 109
25 libdyld.dylib 0x000000010ff2f92d start + 1
26 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
I test an app that uses a custom UIFont. This font is used in a UILabel that is zoomable -- it has a CATiledLayer layer.
This is the code for the UILabel class:
#import "ZoomableLabel.h"
#implementation ZoomableLabel
+ (Class)layerClass
{
return [CATiledLayer class];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self setupView];
}
return self;
}
//- (id)initWithCoder:(NSCoder *)aDecoder {
// self = [super initWithCoder:aDecoder];
// if (self) {
// // Initialization code
// [self setupView];
// }
// return self;
//}
-(void)awakeFromNib {
[super awakeFromNib];
[self setupView];
}
- (void)setupView {
CATiledLayer *layerForView = (CATiledLayer *)self.layer;
layerForView.levelsOfDetailBias = 3;
layerForView.levelsOfDetail = 1;
}
-(void)setText:(NSString *)value {
self.layer.contents = nil;
[super setText:value];
[self setNeedsDisplay];
}
-(void)setTextColor:(UIColor *)value {
self.layer.contents = nil;
[super setTextColor:value];
[self setNeedsDisplay];
}
#end
When I run the app on a device or the simulator for the first time (that is the app is installed for the first time on the device or the simulator) I get a crash. Then this crash never happens again! UPDATE: The crash happens VERY randomly (especially when demoing the app...) but not only the first time. This is all the info I managed to get from XCode:
Thread 3 name: Dispatch queue: com.apple.root.default-priority
Thread 3 Crashed: 0 WebCore 0x333adbfa WTF::HashTable<WebCore::FontData const*, std::__1::pair<WebCore::FontData const*, WebCore::GlyphPageTreeNode*>, WTF::PairFirstExtractor<std::__1::pair<WebCore::FontData const*, WebCore::GlyphPageTreeNode*> >, WTF::PtrHash<WebCore::FontData const*>, WTF::HashMapValueTraits<WTF::HashTraits<WebCore::FontData const*>, WTF::HashTraits<WebCore::GlyphPageTreeNode*> >, WTF::HashTraits<WebCore::FontData const*> >::rehash(int) + 42
1 WebCore 0x333adcd4 WTF::HashTableAddResult<WTF::HashTableIterator<WebCore::FontData const*, std::__1::pair<WebCore::FontData const*, WebCore::GlyphPageTreeNode*>, WTF::PairFirstExtractor<std::__1::pair<WebCore::FontData const*, WebCore::GlyphPageTreeNode*> >, WTF::PtrHash<WebCore::FontData const*>, WTF::HashMapValueTraits<WTF::HashTraits<WebCore::FontData const*>, WTF::HashTraits<WebCore::GlyphPageTreeNode*> >, WTF::HashTraits<WebCore::FontData const*> > > WTF::HashTable<WebCore::FontData const*, std::__1::pair<WebCore::FontData const*, WebCore::GlyphPageTreeNode*>, WTF::PairFirstExtractor<std::__1::pair<WebCore::FontData const*, WebCore::GlyphPageTreeNode*> >, WTF::PtrHash<WebCore::FontData const*>, WTF::HashMapValueTraits<WTF::HashTraits<WebCore::FontData const*>, WTF::HashTraits<WebCore::GlyphPageTreeNode*> >, WTF::HashTraits<WebCore::FontData const*> >::add<WTF::HashMapTranslator<WTF::HashMapValueTraits<WTF::HashTraits<WebCore::FontData const*>, WTF::HashTraits<WebCore::GlyphPageTreeNode*> >, WTF::PtrHash<WebCore::FontData const*> >, WebCore::FontData const*, WebCore::GlyphPageTreeNode*>(WebCore::FontData const* const&, WebCore::GlyphPageTreeNode* const&) + 56
2 WebCore 0x333a5cac WebCore::GlyphPageTreeNode::getChild(WebCore::FontData const*, unsigned int) + 264
3 WebCore 0x333a55d8 WebCore::Font::glyphDataAndPageForCharacter(int, bool, WebCore::FontDataVariant) const + 528
4 WebCore 0x333a53b6 WebCore::Font::glyphDataForCharacter(int, bool, WebCore::FontDataVariant) const + 18
5 WebCore 0x333a4b36 WebCore::WidthIterator::advance(int, WebCore::GlyphBuffer*) + 398
6 WebCore 0x333a4794 WebCore::Font::floatWidthForSimpleText(WebCore::TextRun const&, WebCore::GlyphBuffer*, WTF::HashSet<WebCore::SimpleFontData const*, WTF::PtrHash<WebCore::SimpleFontData const*>, WTF::HashTraits<WebCore::SimpleFontData const*> >*, WebCore::GlyphOverflow*) const + 60
7 WebCore 0x333a4546 WebCore::Font::width(WebCore::TextRun const&, WTF::HashSet<WebCore::SimpleFontData const*, WTF::PtrHash<WebCore::SimpleFontData const*>, WTF::HashTraits<WebCore::SimpleFontData const*> >*, WebCore::GlyphOverflow*) const + 250
8 WebCore 0x333a60e0 WebCore::truncateString(WTF::String const&, float, WebCore::Font const&, unsigned int (*)(WTF::String const&, unsigned int, unsigned int, unsigned short*, bool), bool, float*, bool, float, bool) + 296
9 WebCore 0x333a5fac WebCore::StringTruncator::rightTruncate(WTF::String const&, float, WebCore::Font const&, WebCore::StringTruncator::EnableRoundingHacksOrNot, float&, bool, float) + 60
10 WebKit 0x375fc718 applyEllipsisStyle(WTF::String const&, WebEllipsisStyle, float, WebCore::Font const&, WebCore::StringTruncator::EnableRoundingHacksOrNot, float*, bool, float, bool) + 464
11 WebKit 0x375ff3a8 -[NSString(WebStringDrawing) __web_drawInRect:withFont:ellipsis:alignment:letterSpacing:lineSpacing:includeEmoji:truncationRect:measureOnly:renderedStringOut:drawUnderline:] + 5036
12 WebKit 0x375fdfe8 -[NSString(WebStringDrawing) __web_drawInRect:withFont:ellipsis:alignment:letterSpacing:lineSpacing:includeEmoji:truncationRect:measureOnly:renderedStringOut:] + 112
13 WebKit 0x375fdf64 -[NSString(WebStringDrawing) __web_drawInRect:withFont:ellipsis:alignment:letterSpacing:lineSpacing:includeEmoji:truncationRect:measureOnly:] + 108
14 WebKit 0x375fdee4 -[NSString(WebStringDrawing) _web_drawInRect:withFont:ellipsis:alignment:lineSpacing:includeEmoji:truncationRect:measureOnly:] + 108
15 WebKit 0x375fde64 -[NSString(WebStringDrawing) _web_sizeInRect:withFont:ellipsis:lineSpacing:] + 80
16 UIKit 0x353698c2 -[NSString(UIStringDrawing) sizeWithFont:constrainedToSize:lineBreakMode:lineSpacing:] + 122
17 UIKit 0x3535daa6 -[UILabel _legacy_drawTextInRect:baselineCalculationOnly:] + 594
18 UIKit 0x35321c5a -[UILabel _drawTextInRect:baselineCalculationOnly:] + 162
19 UIKit 0x35320a26 -[UILabel drawTextInRect:] + 446
20 UIKit 0x35320860 -[UILabel drawRect:] + 68
21 UIKit 0x3531fd20 -[UIView(CALayerDelegate) drawLayer:inContext:] + 360
22 QuartzCore 0x37b84bb8 -[CALayer drawInContext:] + 108
23 QuartzCore 0x37c62624 tiled_layer_render(_CAImageProvider*, unsigned int, unsigned int, unsigned int, unsigned int, void*) + 1416
24 QuartzCore 0x37bd755c CAImageProviderThread(unsigned int*, bool) + 508
25 libdispatch.dylib 0x37b5e95c _dispatch_root_queue_drain + 248
26 libdispatch.dylib 0x37b5eabc _dispatch_worker_thread2 + 80
27 libsystem_c.dylib 0x38862a0e _pthread_wqthread + 358
28 libsystem_c.dylib 0x388628a0 start_wqthread + 4
Does anybody has any idea on this? I think this crash does not happen on an iOS 5 device...
Here is my take on Summon's answer which uses Core Text to address issues with languages other than English (although I have only tested Swedish) and odd font symbols. Note that it uses initWithCoder as I'm using StoryBoard. It also shows how to center the text in the label horizontally (had less luck with vertical where I simply had to test my way to the right placement).
Header:
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface DNLabel : UILabel
#end
Implementation:
#import "DNLabel.h"
#import <CoreText/CoreText.h>
#implementation DNLabel
+ (Class)layerClass
{
return [CATiledLayer class];
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self setupView];
}
return self;
}
-(void)awakeFromNib
{
[super awakeFromNib];
[self setupView];
}
- (void)setupView {
CATiledLayer *layerForView = (CATiledLayer *)self.layer;
layerForView.levelsOfDetailBias = 10;
layerForView.levelsOfDetail = 10;
}
// LEAVE IT EMPTY
-(void)drawRect:(CGRect)r
{
// UIView uses the existence of -drawRect: to determine if should allow its CALayer
// to be invalidated, which would then lead to the layer creating a backing store and
// -drawLayer:inContext: being called.
// By implementing an empty -drawRect: method, we allow UIKit to continue to implement
// this logic, while doing our real drawing work inside of -drawLayer:inContext:
}
// These calls inside this method are thread SAFE
-(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context
{
// Core Text version
CTFontRef ctFont = CTFontCreateWithName((__bridge CFStringRef)self.font.fontName,
self.font.pointSize,
NULL);
// set color
CGColorRef color = [[[UIColor blackColor] colorWithAlphaComponent:0.75f] CGColor];
// pack it into attributes dictionary
NSDictionary *attributesDict = [NSDictionary dictionaryWithObjectsAndKeys:
(id)CFBridgingRelease(ctFont), (id)kCTFontAttributeName,
color, (id)kCTForegroundColorAttributeName,
nil, (id)kCTUnderlineStyleAttributeName, nil];
// make the attributed string
NSAttributedString *stringToDraw = [[NSAttributedString alloc] initWithString:self.text
attributes:attributesDict];
// flip the coordinate system
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
// check size of text and set position centered horizontally
CGSize size = [self.text sizeWithFont:self.font];
CGContextSetTextPosition(context, self.bounds.size.width/2 - size.width/2, 1);
// draw
CTLineRef line = CTLineCreateWithAttributedString(
(CFAttributedStringRef)CFBridgingRetain(stringToDraw));
CTLineDraw(line, context);
}
#end
These are the .h and .m classes of a zoomable label based on CATiledLayer that never crashes:
Header:
#import <QuartzCore/QuartzCore.h>
#interface ZoomableLabel : UILabel {
CGPoint textDrawPoint;
CGPoint shadowDrawPoint;
}
#end
Implementation:
#import "ZoomableLabel.h"
#implementation ZoomableLabel
+ (Class)layerClass
{
return [CATiledLayer class];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self setupView];
}
return self;
}
-(void)awakeFromNib {
[super awakeFromNib];
[self setupView];
}
- (void)setupView {
CATiledLayer *layerForView = (CATiledLayer *)self.layer;
layerForView.levelsOfDetailBias = 3;
layerForView.levelsOfDetail = 1;
textDrawPoint = CGPointMake(11, -22);
shadowDrawPoint = CGPointMake(10, -23);
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
textDrawPoint = CGPointMake(11, -42);
shadowDrawPoint = CGPointMake(8, -46);
}
}
// DO NOT USER THESE METHODS ANYMORE
//-(void)setText:(NSString *)value {
//// self.layer.contents = nil;
// [super setText:value];
// [self setNeedsDisplayInRect:self.bounds];
//}
//
//-(void)setTextColor:(UIColor *)value {
//// self.layer.contents = nil;
// [super setTextColor:value];
// [self setNeedsDisplayInRect:self.bounds];
//}
// LEAVE IT EMPTY
-(void)drawRect:(CGRect)r
{
// UIView uses the existence of -drawRect: to determine if should allow its CALayer
// to be invalidated, which would then lead to the layer creating a backing store and
// -drawLayer:inContext: being called.
// By implementing an empty -drawRect: method, we allow UIKit to continue to implement
// this logic, while doing our real drawing work inside of -drawLayer:inContext:
}
// These calls inside this method are thread SAFE
-(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context
{
// Do all your drawing here. Do not use UIGraphics to do any drawing, use Core Graphics instead.
CGContextScaleCTM(context, 1.0f, -1.0f);
CGContextSelectFont(context, [self.font.fontName UTF8String], self.font.pointSize, kCGEncodingMacRoman);
CGContextSetTextDrawingMode(context, kCGTextFill);
// CGContextSetShouldAntialias(context, true);
CGContextSetFillColorWithColor(context, [[[UIColor blackColor] colorWithAlphaComponent:0.75f] CGColor]);
CGContextShowTextAtPoint(context, shadowDrawPoint.x, shadowDrawPoint.y, [self.text UTF8String], self.text.length);
CGContextSetFillColorWithColor(context, [self.textColor CGColor]);
CGContextShowTextAtPoint(context, textDrawPoint.x, textDrawPoint.y, [self.text UTF8String], self.text.length);
}
#end
I wrote code like:
+ (CGFloat)tableView:(UITableView*)tableView rowHeightForObject:(id)item {
CustomTTTableSubtitleItem* captionedItem = item;
CGFloat maxWidth = tableView.width - kHPadding*2;
CGSize titleSize = [captionedItem.title sizeWithFont:TTSTYLEVAR(myTitleFont) constrainedToSize:CGSizeMake(maxWidth, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];
}
Got this exception:
2011-07-24 03:10:18.762 xinyou[15941:b303] -[TTDefaultStyleSheet
myTitleFont]: unrecognized selector sent to instance 0x5b5e120
2011-07-24 03:10:18.765 xinyou[15941:b303] * Terminating app due to
uncaught exception 'NSInvalidArgumentException', reason:
'-[TTDefaultStyleSheet myTitleFont]: unrecognized selector sent to
instance 0x5b5e120'
* Call stack at first throw: ( 0 CoreFoundation
0x0119a5a9 exceptionPreprocess + 185 1 libobjc.A.dylib
0x012ee313 objc_exception_throw + 44 2 CoreFoundation
0x0119c0bb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187 3
CoreFoundation 0x0110b966 __forwarding + 966
4 CoreFoundation 0x0110b522
_CF_forwarding_prep_0 + 50 5 xinyou
0x000081f9 +[CustomTTTableSubtitleItemCell
tableView:rowHeightForObject:] + 186 6 xinyou
0x000a6c92 -[TTTableViewVarHeightDelegate
tableView:heightForRowAtIndexPath:] + 156 7 UIKit
0x0064a6d5 -[UISectionRowData
In this exception you can see [TTDefaultStyleSheet myTitleFont]: unrecognized selector sent to instance 0x5b5e120 but actually myTitleFont defined in XYDefaultStyleSheet and I've imported XYDefaultStyleSheet.h in my class. XYDefaultStyleSheet.h and XYDefaultStyleSheet.m are like:
XYDefaultStyleSheet.h
#import "Three20/Three20.h"
#interface XYDefaultStyleSheet : TTDefaultStyleSheet
#property(nonatomic,readonly) UIColor* myHeadingColor;
#property(nonatomic,readonly) UIColor* mySubtextColor;
#property(nonatomic,readonly) UIColor* myTitleColor;
#property(nonatomic,readonly) UIFont* myTitleFont;
#property(nonatomic,readonly) UIFont* myHeadingFont;
#property(nonatomic,readonly) UIFont* mySubtextFont;
#end
XYDefaultStyleSheet.m
#import "XYDefaultStyleSheet.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
#implementation XYDefaultStyleSheet
///////////////////////////////////////////////////////////////////////////////////////////////////
// styles
///////////////////////////////////////////////////////////////////////////////////////////////////
// public colors
- (UIColor*)myTitleColor {
return [UIColor blackColor];
}
- (UIColor*)myHeadingColor {
return RGBCOLOR(80, 110, 140);
}
- (UIColor*)mySubtextColor {
return [UIColor grayColor];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// public fonts
- (UIFont*)myTitleFont {
return [UIFont boldSystemFontOfSize:16];
}
- (UIFont*)myHeadingFont {
return [UIFont boldSystemFontOfSize:13];
}
- (UIFont*)mySubtextFont {
return [UIFont systemFontOfSize:12];
}
#end
why always tell [TTDefaultStyleSheet myTitleFont] ... if the problem is really myTitleFont, it should be [XYDefaultStyleSheet myTitleFont], why TTDefaultStyleSheet?
got it! Init my style sheet in AppDelegate.
This is an answer to #Jason Zhao's answer about initialising within the AppDelegate.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
[TTStyleSheet setGlobalStyleSheet:[[[CustomDefaultStyleSheet alloc]
init] autorelease]];
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
}
Original code is from here, which has a lot of useful information about using TTStyleSheet's:
Three20 Stylesheets iPhone Tutorial