SIGABRT using NSDictionary for text and shadow attributes - objective-c

I'm attempting to build a simple app in Objective C, utilizing an attributes Dictionary in my AppDelegate module to allow me to customize the look of various navigation items of my story layout.
The code builds fine with no errors but as it deploys onto my test device I get a SIGABRT.
I'm using latest version Xcode(9.2); storyboards are all set to "Builds for iOS 8.2 and Later"; Deployment Target is set at 8.1.
I had utilized UITextAttributeTextShadowColor, nil in my code without issues, but that is deprecated since iOS 7.0 so I updated it to NSShadowAttributeName, nil and now it won't work.
What am I doing wrong?
The specific SIGABRT error reads: Terminating app due to uncaught
exception 'NSInvalidArgumentException', reason: '-[UIDeviceRGBColor
shadowColor]: unrecognized selector sent to instance 0x1d447cf00'.
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSDictionary *attribs = [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor colorWithRed:170.0/255.0 green:21.0/255.0 blue:29.0/255.0 alpha:1.0],
NSForegroundColorAttributeName,
[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.0],
NSShadowAttributeName, nil];
[[UINavigationBar appearance] setTitleTextAttributes: attribs];
[[UIBarButtonItem appearance] setTitleTextAttributes: attribs forState:UIControlStateNormal];
return YES;
}

You need to do your code updation like this :
NSShadow *shadow = [[NSShadow alloc] init];
shadow.shadowColor = [UIColor blackColor];
shadow.shadowOffset = CGSizeMake(1, 0);
NSDictionary * attribs = #{NSForegroundColorAttributeName: [UIColor whiteColor],
NSShadowAttributeName: shadow,
NSFontAttributeName: [UIFont titleBolder]};
[[UINavigationBar appearance] setTitleTextAttributes: attribs];
This will solve your problem of crash.

Documentation: of NSShadowAttributeName:
The value of this attribute is an NSShadow object. The default value
of this property is nil.
Clearly that's not what you do. You gave a UIColor object.
And that's exactly what is saying the error:
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[UIDeviceRGBColor
shadowColor]: unrecognized selector sent to instance 0x1d447cf00'
It's saying: I tried to call a method shadowColor on a UIDeviceRGBColor (surely a cluster for UIColor) object. But since it doesn't know that method (~ selector, for your level that's the case), I crashed.
Clearly, that's where you can get suspicious. shadowColor that's an available method on NSShadow object. Maybe I did something wrong. And reading the doc you'll know it's the case.
So put a NSShadow object instead of a UIColor one for the value corresponding.

Related

Cannot set text color of Send and Cancel buttons in the mail composer when presented from the UIActivityViewController in iOS7

I am using the UIActivityViewController to share items in iOS7. When I tap on the Mail option, it pops up the mail composer, but the Cancel and Send buttons on the navigation bar and the navigation bar itself are blue, making it very difficult to read, so I want to change their color. It's working in iOS6 but not in iOS7.
I tried
[[UIBarButtonItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor redColor], UITextAttributeTextColor, [UIColor clearColor], UITextAttributeTextShadowColor, nil] forState:UIControlStateNormal];
which works in iOS6, and I tried
[[UIBarButtonItem appearance] setTintColor:[UIColor redColor]];
[[UINavigationBar appearance] setBarTintColor:[UIColor redColor]];
which causes the color to flash red the first time the app is run before immediately switching back to the blue color.
Managed to change the text color of the Send and Cancel buttons, which are on the UINavigationBar in the MFMailComposerViewController (both Send and Cancel) and MFMessageComposeViewController (only Cancel), when presented from UIActivityViewController.
Using an UIActivityViewController, tap on Messageor Mail:
You'll notice that the default text color of the Send and Cancel buttons is blue:
In order to change that, in the AppDelegate.m class, in the didFinishLaunchingWithOptions method, insert the following line:
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTintColor:[UIColor whiteColor]];
This results in:
You can also use other colors, for example:
[UIColor purpleColor];
[UIColor greenColor];
How did I test this? I noticed this solution works for the following:
with Xcode 5.1, in the iOS 7.1 simulator, building as base iOS SDK 7.1 (can be chosen from selecting the project file -> Build Settings -> Base SDK. Also, selected from General -> Deployment Target -> 7.1)
with Xcode 5.1, on an iPhone 4, building as base iOS SDK 7.0 (can be chosen from selecting the project file -> Build Settings -> Base SDK. Also, selected from General -> Deployment Target -> 7.0)
with Xcode 5.1, on an iPhone 4, building as base iOS SDK 7.1 (can be chosen from selecting the project file -> Build Settings -> Base SDK. Also, selected from General -> Deployment Target -> 7.1)
It didn't work when testing with:
with Xcode 5.1, in the iOS 7.0 simulator, building as base iOS SDK 7.0 (can be chosen from selecting the project file -> Build Settings -> Base SDK. Also, selected from General -> Deployment Target -> 7.0)
Therefore it should be safe to use, as I believe the behavior on the actual device matters more than the behavior in the iOS simulator.
If anyone knows why it doesn't work in the iOS 7.0 simulator, I would like to know. :)
Bar tint color and status bar color in UIActivityViewController.
Swift 3 solution:
extension MFMailComposeViewController {
override open func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIApplication.shared.statusBarStyle = UIStatusBarStyle.lightContent
}
open override func viewDidLoad() {
super.viewDidLoad()
navigationBar.isTranslucent = false
navigationBar.isOpaque = false
navigationBar.barTintColor = UIColor.white
navigationBar.tintColor = UIColor.white
}
}
Here is what works on iOS 7.1 as of today.
Subclass the UIActivityViewController and override the following method:
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
{
viewControllerToPresent.view.tintColor = [UIColor whiteColor];
[super presentViewController:viewControllerToPresent animated:flag completion:^{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
if (completion) {
completion();
}
}];
}
This will make the buttons white and the status bar white.
For Swift:
self.navigationController?.presentViewController(activityViewController, animated: true, completion: { () in
UIBarButtonItem.appearance().tintColor = UIColor.whiteColor()
UINavigationBar.appearance().barTintColor = UIColor.whiteColor() // optional to change bar backgroundColor
}
This will change Send & Cancel button color to White (tested on iOS 7,8) but am still not able to make status bar text color white.( Although I have not tried that Subclass UIActivityViewController solution to change statusbar text color )
I fixed my issue by extending the UIActivityViewController and overriding the viewWillAppear and viewWilldisapper methods:
extension UIActivityViewController {
override open func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UINavigationBar.appearance().barTintColor = .white
}
open override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.isTranslucent = false
navigationController?.navigationBar.isOpaque = false
navigationController?.navigationBar.barTintColor = UIColor(red: (247/255), green: (247/255), blue: (247/255), alpha: 1)
//navigationBar.tintColor = UIColor.white
}
open override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(true)
UINavigationBar.appearance().barTintColor = mycustomColor
}
}
This appears to be a bug with iOS 7. I've seen other reports of this online. It also doesn't appear to be fixed in iOS 7.1.
To be specific, no matter what you do, you cannot set tint colors on navigation bars for dialogs shown from the UIActivityViewController.
I had the same problem with my app where the tintColor property of UINavigationBar is white everywhere thanks to the appearance proxy. The resulting effect is that UIBarButtonItem from the mail composer view controller navigationBar were not visible (white buttons on a white navigation bar).
I have this call in my application:didFinishLaunchingWithOptions: method:
[[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];
As it is impossible (for now ?) to access the UINavigationBar of the mail composer view controller in the UIActivityViewController, I did the following workaround which is inspired from Alex's answer:
UIColor *normalColor = [[UINavigationBar appearance] tintColor];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:dataToShare applicationActivities:nil];
[activityViewController setCompletionHandler:^(NSString *activityType, BOOL completed) {
// back to normal color
[[UINavigationBar appearance] setTintColor:normalColor];
}];
[self presentViewController:activityViewController animated:YES completion:^{
// change color temporary
[[UINavigationBar appearance] setTintColor:[UIColor colorWithRed:232.0f/255.0f green:51.0f/255.0f blue:72.0f/255.0f alpha:1.0f]];
}];
PS: this code is intented for iOS 7, but you can use [[UIBarButtonItem appearance] setTintColor:] in iOS 6 (cf Kevin van Mierlo's answer)
Well there are reasons for why we cannot change the way that the UI in apple's code is the way it is. Mostly because it is apple's. They do not allow you to edit the way the UI in MFMailComposerViewController looks in any way. If there is a way, then I have no clue about it, but I have never seen any way to do it. MFMailComposeViewController doesn't support the appearance attribute as it was created in iOS 3.0, and appearance didn't become a thing until iOS 5.0
Here is a link to the MFMailComposeViewController apple documentation: MFMailComposeViewController
Hope this helps!
If you want to set the color of the cancel and send buttons in iOS 7 you should use this:
// Change the colours of the buttons in iOS 7
[[UINavigationBar appearance] setTintColor:[UIColor redColor]];
In iOS 6 it is indeed these and you should also leave this in your code:
// Change the colours of the buttons in iOS 6
[[UIBarButtonItem appearance] setTintColor:[UIColor redColor]];
// Change the color of the the navigation bar in iOS 6 and 7
[[UINavigationBar appearance] setBarTintColor:[UIColor redColor]];
Try this code for may be it will help you
[[mailComposer navigationBar] setTintColor:[UIColor blackColor]];
I couldn't get Alex's solution to work, however I have managed to get a variation of Paillou's answer to work although I had to set both the barTintColor and the titleTextAttributes in my situation:
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:applicationActivities];
activityViewController.excludedActivityTypes = #[UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll, UIActivityTypeAddToReadingList, UIActivityTypePostToVimeo, UIActivityTypePostToFlickr, UIActivityTypeAirDrop];
[activityViewController setCompletionHandler:^(NSString *activityType, BOOL completed) {
// back to normal color
[[UINavigationBar appearance] setBarTintColor:AAColorInputBorder];
[[UINavigationBar appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:#"Avenir-Medium" size:18], NSFontAttributeName,
[UIColor whiteColor], NSForegroundColorAttributeName,
nil]];
}];
[self presentViewController:activityViewController animated:YES completion:^{
// change color temporary
[[UINavigationBar appearance] setBarTintColor:[UIColor whiteColor]];
[[UINavigationBar appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:#"Avenir-Medium" size:18], NSFontAttributeName,
AAColorInputBorder, NSForegroundColorAttributeName,
nil]];
Thanks Paillou!
This has worked for me:
in AppDelegate.m in the function:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
I've entered the following code:
//mail composer
[[UINavigationBar appearanceWhenContainedIn:[MFMailComposeViewController class], nil] setBarTintColor:myBackgroundColor];
[[UINavigationBar appearanceWhenContainedIn:[MFMailComposeViewController class], nil] setTintColor:myBarItemsColor];
It works just fine on iOS7 + iOS8, did not try on newer versions
For ios7 i think that you should go through this code
[[UINavigationBar appearance] setTintColor:[UIColor redColor]];
If it is also not working then try Mail Compose View Controller apple documentation available on the internet.
Before presenting the mail composer insert this line like this:
[mailComposer.navigationBar setTintColor:[UIColor whiteColor]];
[self presentViewController:mailComposer animated:YES completion:nil];
Even though I set the status bar style in application did finish launching I also needed to set it again in the completion block like this:
[self presentViewController:mailComposer animated:YES completion:^{[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];}];
I had enormous trouble with this, especially when MFMailComposeViewController/MFMessageViewController are themselves displayed by UIActivityViewController.
I resorted to using method swizzling on viewDidAppear/viewDidDisappear to undo and then redo my app's customisation of colors and fonts, with some help from https://github.com/rentzsch/jrswizzle:
SwizzledComposeViewControllers.h
#import <MessageUI/MessageUI.h>
#interface MFMailComposeViewController (GMSwizzling)
#end
#interface MFMessageComposeViewController (GMSwizzling)
#end
SwizzledComposeViewControllers.m
#import "SwizzledComposeViewControllers.h"
#import "AppDelegate.h"
#import "JRSwizzle.h"
#implementation MFMailComposeViewController (GMSwizzling)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self jr_swizzleMethod:#selector(init) withMethod:#selector(gmswizzled_init) error:nil];
[self jr_swizzleMethod:#selector(viewWillAppear:) withMethod:#selector(gmswizzled_viewWillAppear:) error:nil];
[self jr_swizzleMethod:#selector(viewWillDisappear:) withMethod:#selector(gmswizzled_viewWillDisappear:) error:nil];
});
}
- (instancetype)gmswizzled_init {
[(AppDelegate*)UIApplication.sharedApplication.delegate uncustomiseAppearance];
return [self gmswizzled_init];
}
- (void)gmswizzled_viewWillAppear:(BOOL)animated {
[(AppDelegate*)UIApplication.sharedApplication.delegate uncustomiseAppearance];
[self gmswizzled_viewWillAppear:animated];
}
- (void)gmswizzled_viewWillDisappear:(BOOL)animated {
[(AppDelegate*)UIApplication.sharedApplication.delegate customiseAppearance];
[self gmswizzled_viewWillDisappear:animated];
}
#end
#implementation MFMessageComposeViewController (GMSwizzling)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self jr_swizzleMethod:#selector(init) withMethod:#selector(gmswizzled_init) error:nil];
[self jr_swizzleMethod:#selector(viewWillAppear:) withMethod:#selector(gmswizzled_viewWillAppear:) error:nil];
[self jr_swizzleMethod:#selector(viewWillDisappear:) withMethod:#selector(gmswizzled_viewWillDisappear:) error:nil];
});
}
- (instancetype)gmswizzled_init {
[(AppDelegate*)UIApplication.sharedApplication.delegate uncustomiseAppearance];
return [self gmswizzled_init];
}
- (void)gmswizzled_viewWillAppear:(BOOL)animated {
[(AppDelegate*)UIApplication.sharedApplication.delegate uncustomiseAppearance];
[self gmswizzled_viewWillAppear:animated];
}
- (void)gmswizzled_viewWillDisappear:(BOOL)animated {
[(AppDelegate*)UIApplication.sharedApplication.delegate customiseAppearance];
[self gmswizzled_viewWillDisappear:animated];
}
#end
(I have to admit I can't recall why I uncustomised appearances both in init and viewWillAppear, but I'm fairly sure there was a reason ...).
In Swift I made an extension for UIViewController:
extension UIViewController {
func presentActivityViewController(viewControllerToPresent: UIViewController) {
self.presentViewController(viewControllerToPresent, animated: true) { _ in
UIBarButtonItem.appearance().tintColor = UIColor.whiteColor()
UINavigationBar.appearance().barTintColor = Config.primaryColor
}
}
}
When I need to present an UIActivityViewController I call:
let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: [])
presentActivityViewController(activityViewController)
In Swift, on iOS9, setting
UINavigationBar.appearance().barTintColor = UIColor.greenColor() // eg
UINavigationBar.appearance().translucent = false
before presenting the activity view controller did the trick for me.
I tried many different methods in iOS 9 and 10, but this is the only one that worked. Note that I have a background image behind the navigationBar as well:
[UIApplication.sharedApplication setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];
NSDictionary *attribs = #{NSForegroundColorAttributeName:UIColor.whiteColor};
UINavigationBar.appearance.titleTextAttributes = attribs;
UINavigationBar.appearance.tintColor = UIColor.whiteColor;
[UINavigationBar.appearance setBackgroundImage:[UIImage imageNamed:#"IOSNavigationBar"] forBarMetrics:UIBarMetricsDefault];
UIBarButtonItem.appearance.tintColor = UIColor.whiteColor;
You can set your appearance before presenting UIActivityViewController. Add resetting of appearance to completionWithItemsHandler of your activity VC:
setNavBarAppearance()
activityVC.completionWithItemsHandler = { [weak self] _, _, _, _ in
self?.resetNavBarAppearance()
}
present(activityVC, animated: true, completion: nil)
The only problem, that if activity is like mail sending, it is full screen. Your appearance will not be applied to current visible views. A little hacks to solve it:
setNavBarAppearance()
activityVC.completionWithItemsHandler = { [weak self] _, _, _, _ in
self?.resetNavBarAppearance()
// Hacks(choose one of them):
// 1)
self?.navigationController?.isNavigationBarHidden = true
self?.navigationController?.isNavigationBarHidden = false
// 2)
let redrawTriggerVC = UIViewController()
redrawTriggerVC.modalPresentationStyle = .popover
self.present(redrawTriggerVC, animated: false, completion: nil)
redrawTriggerVC.dismiss(animated: false, completion: nil)
}
present(activityVC, animated: true, completion: nil)
I haven't found a mechanism I liked, so for what it's worth here's mine. Part of the trouble is later versions of iOS add the capability for apps to add system-wide Share and Action Extensions. These third-party items seem to be coded all sorts of ways. Some inherit the app's nav bar style, some use their own, and some seem to assume a white nav bar (but actually inherits from the app).
This is tested on iOS 12.2.
I create an UIActivityItemSource, to which I have:
- (nullable id)activityViewController:(nonnull UIActivityViewController *)activityViewController itemForActivityType:(nullable UIActivityType)activityType {
if (activityType == UIActivityTypePrint || [activityType.lowercaseString containsString:#"extension"] || [activityType containsString:#"AssignToContact"]) {
//What a hack, but the best I can do. Seems some extensions inherit nav style from parent, others don't.
//ActionExtension is bottom row; all those I tested need this. The string comparison catches most non-OS extensions (the type is set by developer).
[[UINavigationBar appearance] setBarTintColor:[UIColor kNavigationBarBackgroundColor]]; //kNavigationBarBackgroundColor is my app's custom nav bar background color
} else {
[[UINavigationBar appearance] setBarTintColor:[UIColor whiteColor]];
}
return self.pdfData; //In my case I'm sharing a PDF as NSData - modify as needed for your shared item
}
Then in my UIActivityViewController's completionWithItemsHandler I include:
[[UINavigationBar appearance] setBarTintColor:[UIColor kNavigationBarBackgroundColor]]; //Again, this is my app's custom nav bar background color
Unrelated to the specific issue, but if you don't currently have a UIActivityItemSource you need to do something like this:
NSArray *activities=#[self]; //And set self to be a UIActivityItemSource
UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:activities applicationActivities:nil];
I'm sure this isn't 100% reliable, but worked with all extensions I tried.

Unrecognized Selector sent to Instance in another class

I've been trying to figure out something that might be obvious and I'm missing the point or losing it. Is something wrong with my toggleStormButtons function that XCode isn't seeing it?
In my main class I have the following to call a function in another class:
STopLeftMenu *mTopLeft = [[STopLeftMenu alloc]init];
[mTopLeft drawStormToggleButton];
Then in the other class I have 2 functions:
- (void)toggleStormButtons{
[UIButton animateWithDuration:0.50 animations:^{
if (stormToggleBtn.transform.tx == 0){
[stormToggleBtn setTransform:CGAffineTransformMakeTranslation(307, 0)];
UIImage* hideButtonImg = [UIImage imageNamed:#"aiga_right_arrow_mod_hide_resize.png"];
[stormToggleBtn setBackgroundImage:hideButtonImg forState:UIControlStateNormal];
}
else{
[stormToggleBtn setTransform:CGAffineTransformMakeTranslation(0, 0)];
UIImage* showButtonImg = [UIImage imageNamed:#"aiga_right_arrow_mod_show_resize.png"];
[stormToggleBtn setBackgroundImage:showButtonImg forState:UIControlStateNormal];
}
}];
for(UIView* storm in stormButtonSaves){
[UIView animateWithDuration:0.50 animations:^{
if (storm.transform.tx == 0){
[storm setTransform:CGAffineTransformMakeTranslation(307, 0)];
storm.alpha = .65;
}
else{
[storm setTransform:CGAffineTransformMakeTranslation(0, 0)];
storm.alpha = 0;
}
}];
}
}
- (void)drawStormToggleButton{
//Storm Pullout Toggle Button
UIImage *buttonImageNormal = [UIImage imageNamed:#"aiga_right_arrow_mod_show_resize.png"];
stormToggleBtn = [[UIButton alloc] initWithFrame:CGRectMake(10, 10, 65, 75) ];
[stormToggleBtn setBackgroundImage:buttonImageNormal forState:UIControlStateNormal];
stormToggleBtn.backgroundColor = [UIColor clearColor];
stormToggleBtn.alpha = 0.5;
[stormToggleBtn addTarget:self action:#selector(toggleStormButtons) forControlEvents:UIControlEventTouchUpInside];
[viewsToRemove addObject:stormToggleBtn];
[mv addSubview:stormToggleBtn];
}
I seem to be getting an unrecognized selector message:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSMallocBlock__ toggleStormButtons]: unrecognized selector sent to instance 0x7bc9ca0'
*** First throw call stack:
(0x1b9e012 0x1966e7e 0x1c294bd 0x1b8dbbc 0x1b8d94e 0x197a705 0x8ae2c0 0x8ae258 0x96f021 0x96f57f 0x96e6e8 0x8ddcef 0x8ddf02 0x8bbd4a 0x8ad698 0x2599df9 0x2599ad0 0x1b13bf5 0x1b13962 0x1b44bb6 0x1b43f44 0x1b43e1b 0x25987e3 0x2598668 0x8aaffc 0x2285 0x2185)
libc++abi.dylib: terminate called throwing an exception
It sounds like your STopLeftMenu is being deallocated too early. The button does not retain its target, so you'll need to keep this object around as long as it needs to respond to the button's messages. If you're not sure how the object is getting deallocated, try debugging with Instruments.
I don't see anything wrong with the code you have shown. I tried it in an existing app of mine and while I had to a) declare a UIButton local variable, b) change the image used for the button and c) comment out the stuff in toggleStormButtons, the method was called every time I tapped the button, no problems.
You don't show your storage for the button. Are you using ARC? Is the button strong? If ARC it should be strong. If not ARC and you are not using a property to assign with a retain, that could cause problems.
What does viewsToRemove do? Looks like an array but it could be something else.
Why don't you use + buttonWithType: and set the frame later?

Unrecognized Selector - [NSView borderRect]

I'm having trouble getting the NSRect of a view's border. I keep getting an unrecognized selector error.
Here is the code:
NSGradient *BorderGradient = [[NSGradient alloc] initWithStartingColor:[NSColor blackColor] endingColor:[NSColor whiteColor]];
[BorderGradient drawInRect:[self.window.contentView borderRect] angle:-90];
// Unrecognized Selector error here
I'm trying to access the border rect to add a color gradient to the border. The code also crashes when I try to access the borderRect by itself, like this:
NSRect rect = [self.window.contentView borderRect];
NSLog(#"origin.x = %f", rect.origin.x);
And if trying to convert the drawInRect: to CGRect. Like so:
NSGradient *BorderGradient = [[NSGradient alloc] initWithStartingColor:[NSColor blackColor] endingColor:[NSColor whiteColor]];
[BorderGradient drawInRect:NSRectToCGRect([self.window.contentView borderRect]) angle:-90];
// Unrecognized Selector error here
Any help would be greatly appreciated.
Thanks!
NSView doesn't have a method named -borderRect. Is it a custom method you've implemented? NSBox does have a -borderRect method. Are you expecting your window's content view to be an instance of NSBox? Have you checked to see that that's actually true.
Perhaps you really want -frame or -bounds?
NSView (what is returned from self.window.contentView) does not have a borderRect method, which is causing the Unrecognized Selector error.
You probably want frame or bounds instead.

Use NSLayoutConstraints on a UITableView's header view

I am trying to add a UIView to a UITableView's header, then, using the NSLayoutConstraints I want to give it a height.
I've looked through the Apple Docs and the WWDC 2012 videos but I cannot find this particular error anywhere!
I have the following code:
- (UIImageView *)logoImageView
{
if (!_logoImageView) {
_logoImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"logo"]];
[_logoImageView setTranslatesAutoresizingMaskIntoConstraints:NO];
}
return _logoImageView;
}
... in viewDidLoad
UIView *tableHeaderView = [[UIView alloc] init];
tableHeaderView.translatesAutoresizingMaskIntoConstraints = NO;
[tableHeaderView addSubview:self.logoImageView];
[self.tableView setTableHeaderView:tableHeaderView];
NSDictionary *constraintViews = #{#"tableView" : self.tableView, #"tableHeaderView" : tableHeaderView, #"logoImageView" : self.logoImageView};
[self.tableView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[tableHeaderView(50)]"
options:0
metrics:nil
views:constraintViews]];
However when I run it I get the following error:
2012-10-08 16:31:34.559 myApp[6934:c07] *** Assertion failure in -[UITableView layoutSublayersOfLayer:], /SourceCache/UIKit_Sim/UIKit-2372/UIView.m:5776
2012-10-08 16:31:34.561 myApp[6934:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. UITableView's implementation of -layoutSubviews needs to call super.'
*** First throw call stack:
(0x199b012 0x17c0e7e 0x199ae78 0x1256f35 0x7589ef 0x17d46b0 0x622fc0 0x61733c 0x622eaf 0x7f78cd 0x7401a6 0x73ecbf 0x73ebd9 0x73de34 0x73dc6e 0x73ea29 0x741922 0x7ebfec 0x738bc4 0x738dbf 0x738f55 0x741f67 0x705fcc 0x706fab 0x718315 0x71924b 0x70acf8 0x27e8df9 0x27e8ad0 0x1910bf5 0x1910962 0x1941bb6 0x1940f44 0x1940e1b 0x7067da 0x70865c 0x6d5d 0x2395)
libc++abi.dylib: terminate called throwing an exception
I had the same exception when I was trying to set the table header view.
When I noticed that the view had Contraints I just unchecked the "Use Autolayout" option from Storyboard.
Screenshot: http://i.stack.imgur.com/5jWHy.png
This solved for me.
The best way to overcome this is to use Interface Builder to setup the UITableView header, then add an Outlet to the height NSLayoutConstraint.
Try this:
logoImageView.translatesAutoresizingMaskIntoConstraints = YES;
(If not works, try to remove:
tableHeaderView.translatesAutoresizingMaskIntoConstraints = NO; //Remove this line
:)
I didn't get any proper solution for this issue but you can fix it by using frames and not setting translatesAutoresizingMaskIntoConstraints property to No (by default its yes, so don't set it)
CGRect headerViewFrame = CGRectMake(0,0,320,60); //Frame for your header/footer view
UIView *tableHeaderView = [[UIView alloc] initWithFrame:headerViewFrame];
tableHeaderView.translatesAutoresizingMaskIntoConstraints = Yes; //Or don't set it at all
[self.tableView setTableHeaderView:tableHeaderView];

Exception with custom font on Cocos2d

I'm trying to make menu with custom font, but it doesn't seem to work.
Here is the code:
- (id) init
{
if (self = [super init])
{
CGSize size = [[CCDirector sharedDirector] winSize];
[CCMenuItemFont setFontName:#"PC Senior Regular"];
[CCMenuItemFont setFontSize:18];
CCMenuItemFont *menu1 = [CCMenuItemFont itemFromString:#"Music ON" target:self selector:#selector(musicToggle)];
CCMenuItemFont *menu2 = [CCMenuItemFont itemFromString:#"Back" target:self selector:#selector(back)];
CCMenu *menu = [CCMenu menuWithItems:menu1, menu2, nil];
[menu setPosition:ccp(size.width / 2 , size.height / 2)];
[menu alignItemsVertically];
[self addChild:menu];
}
Here is the code in my info.plist:
<key>UIAppFonts</key>
<array>
<string>PC Senior Regular.ttf</string>
<string>senior.ttf</string>
</array>
Exception:
2012-07-27 05:42:35.369 Busterball[16089:10a03] In options
2012-07-27 05:42:35.371 Busterball[16089:10a03] -[__NSCFConstantString sizeWithZFont:]: unrecognized selector sent to instance 0xb0670
2012-07-27 05:42:35.372 Busterball[16089:10a03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString sizeWithZFont:]: unrecognized selector sent to instance 0xb0670'
I have tried using senior.ttf, just senior, etc.
Both fonts are added as targets for the project. I double checked for correct type case.
What is going wrong?
Have you tried something like this?
CCLabelTTF *label = [CCLabelTTF labelWithString:"Some Text" fontName:#"MyFont.TTF" fontSize:24.0];
CCMenuItem *item = [CCMenuItemLabel itemWithLabel:label target:self selector:#selector(myFunction)];
CCMenu *menu = [CCMenu menuWithItems:item];
[self addChild:menu];
Your info.plist looks right, and this code has worked for me. That said, I do recommend setting breakpoints and trying to find where your error is coming from.
An invalid argument exception means that you are trying to use a method that is not recognized. The problem is your sizeWithZFont method. I have tried to search in the cocos2d documentation and that is not a method in there.