I am trying to add this category to CPView but XCodeCapp gives an error and I get unrecognized selector sent to instance error when I try to use this method.
#import <AppKit/CPView.j>
#implementation CPView (Custom)
- (void) addSomething
{
var bounds = [self bounds];
var context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSetFillColor(context, [CPColor blueColor]);
CGContextFillRect(context, CGRectMake(100,100,100,100));
}
#end
The syntax is correct as far as I can tell, the file name I am using is CPView_Custom.j
EDIT
I am also using IB to connect a CPView ivar to a custom view in the XIB/NIB file. Not sure if this makes a difference or not.
XCodeCapp will always throw errors regarding Categories because the objj CLI cannot understand them as a single file.
You should ignore your categories by adding some entries in .xcodecapp-ignore.
Related
I'm making an application with xcode, and I have a trouble with passing data between views.
I want to set in detail view, a date of a calendar. Then when I go back to the master view I want to see the events in the selected date, but I don`t know how I make it.
Can you help me?
this is how you can communicate between 2 class
ViewController *dvController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:[NSBundle mainBundle]];
// ViewController is controler where you want to send date from particular controler we are making object of ViewController where you want to send data
dvController.selectedBirthdate = selectedbirthdate;
dvController.selectedName = selectedname;
//you are sending data in above two lines just imagine you are sending string
[self.navigationController pushViewController:dvController animated:YES];
//then pushviewcontroller and there you go
[dvController release];
simple as that
there is another way to comunicate between 2 classes is that app delegate make object of you app delegate and then assing what you want to particular varible of app delegate and then you can use that variable anywhere in project
create app delegate object like this
YourAppDelegate *appDelegate = (YourAppDelegate *)[[UIApplication sharedApplication] delegate];
//and then access the variable by appDelegate.variable
if you are using storyboard then you can use prepareForSegue like below
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:...]) {
MyViewController *controller = (MyViewController *)segue.destinationViewController;
controller.myProperty1 = ...;
controller.myProperty2 = ...;
}
}
There are basically two most common approaches:
1) use unwind segue if you're using storyboard in the project. The approach is perfectly discussed here:
http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/SecondiOSAppTutorial/CreatingAddView/CreatingAddView.html
2) use delegate pattern. I found the below tutorial quite useful when I had started to learn delegation:
http://www.roostersoftstudios.com/2011/04/12/simple-delegate-tutorial-for-ios-development/
I'm new to Xcode and objective c. I want to create a button (probably a UIBarButtonItem, for a navigation bar) with a particular appearance, which I will use repeatedly in different views. I've searched at length but can't figure out how.
Would it be appropriate to subclass UIBarButtonItem? I tried to do that, but I was quickly in over my head. Once I create the .h and .m files as a subclass of UIBarButtonItem, do I then have to instantiate a UIBarButtonItem? Do those files not automatically create a button object for me (imported from the parent class), which I can refer to as self? It seems like it would be weird to instantiate a button within its own subclass.
One thing I want to do is add the line,
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
but I'm at a loss as to how to create reusable button with that property.
Even if that is completely the wrong approach to creating a reusable custom button, I clearly need to improve my understanding of objects, so explanation of my misunderstandings would be much appreciated!
Please?
You can do this without subclassing - by making a category (a preferred way of doing things in Objective-C). With a category you can provide custom methods for an object without having to subclass it. You can't (easily) provide custom properties, but in your case this is not relevant.
Using a Category
This is how your category header file could look:
// UIButton+StyledButton.h
#import <UIKit/UIKit.h>
#interface UIButton (StyledButton)
- (void) styleButton;
#end
Then in the implementation file:
//
// UIButton+StyledButton.m
//
#import "UIButton+StyledButton.h"
#implementation UIButton (StyledButton)
- (void) styleButton {
//style your button properties here
self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
}
('self' refers to the button object, which also acquires the custom methods you write in the category.)
To use it, #import "UIButton+StyledButton.h" then you can do this sort of thing...
on viewDidLoad {
[super viewDidLoad];
UIButton* myButton = [[UIButton alloc] initWithFrame:myFrame];
[myButton styleButton];
}
Using a Subclass
The subclassed equivalent would look something like this:
The header file...
// MyCustomButton.h
#import <UIKit/UIKit.h>
#interface MyCustomButton : UIButton
- (id)initWithCoder:(NSCoder *)coder;
- (id)initWithFrame:(CGRect)frame;
#end
The implementation file...
// MyCustomButton.m
#import "MyCustomButton.h"
#implementation MyCustomButton
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self styleButton];
}
return self;
}
- (id)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self styleButton];
}
return self;
}
- (void) styleButton {
//style your button properties here
self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
}
You provide two init methods - initWithFrame is the method to call when alloc/initing the object in code; initWithCoder is the init method called by the system if loading the object from a storyboard or xib.
To create one of your custom buttons in code, you alloc/init as you would any other object:
MyCustomButton* button = [[MyCustomButton alloc] initWithFrame:buttonFrame];
You wouldn't also alloc/init the superclass instance, this is done by the initWithFrame: method in the subclass when it calls [super initWithFrame:frame]. self refers to your custom subclass instance, but that includes all of the (public) properties and methods from it's superclass - unless you have implemented overrides in the subclass.
To use your subclassed button in a storyboard/xib, just drag out a regular button then set it's type to your custom button class in the Identity Inspector. The initWithCoder method is called automatically when the button is loaded from the storyboard/xib into a view.
update
From your comments, you seem to harbour a few confusions still, so here are some highly compressed de-obfuscating notes...
Keep away from subclassing UINavigationController unless you really know what you are doing. It's rarely necessary.
The buttons on a navController's interface are properties of it's contained viewControllers. Look up the navigationItem property of UIViewController (similarly - in the case of a UIToolbar - the View Controller has a toolbarItems property). This allows Navigation Controllers to be context-aware.
The 'viewDidLoad' in my example is assumed to be in a regular UIViewController. My example is also a category on the regular UIBUtton which has no formal relationship with UIBarButtonItem.
Try getting a UIButton category to work with a regular ViewController first before experimenting with UIBarButtonItem (which does not inherit from UIButton).
UIBarbuttonItem has no initWithFrame, because the thing that organises the bar (UINavigationBar or UIToolbar) - in this case a Navigation Controller - is responsible for it's ultimate size and positioning. The viewController governs the relative order of barButtonItems, and whether they appear on the left or the right, and the content and (some aspects of) it's appearance, but the rest is up to the NavController.
I am new to iPhone programming. I want to use CATiledLayer to load an image.
I am creating the subclass of UIVIew class and in the init method of that class, I am writing,
CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
But when I am writing
tiledLayer.levelsOfDetail = 4;
It gives me the error that
[CALayer setLevelsOfDetail:]: unrecognized selector sent to instance 0xcd04450
So to check the class-type of tiledLayer,I am writing following statements :
NSString *pqr = [[NSString alloc]initWithFormat:#"%#", [tiledLayer class]];
NSLog(pqr);
But it prints CALayer instead of CATiledLayer. Why is it so?? What am I missing??
Now I am stuck here. :(
Applying a typecast to a pointer in Objective-C has no effect at runtime (it does have some effect during compile time, so this syntax is still used at times).
So, your "typecast" is not actually doing a typecast. It's just informing the compiler (in that one line of code only) that this is a CATiledLayer and not a CALayer as it has been declared. The actual object is really still a CATiledLayer.
In order to change the class of self.layer, you define a static method to return the class:
#implementation MyView
+ (Class)layerClass
{
return [CATiledLayer class];
}
#end
And now, when the layer for any MyView instance is created, it will be a CATiledLayer instead of a CALayer.
I have an NSTableView that contains 2 different Columns - one is an NSImageCell that shows a file icon, and the second is a custom subclass of NSTextFieldCell that contains a quick look button on the right of the text. When I click the Quick Look button, the following code is invoked:
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil];
This does it's job and shows the blank Quick Look panel saying "No Items Selected." After I did a bit of research on the internet, I implemented a custom NSTableView subclass to be the Delegate and Data Source for the Quick Look panel. I get the notification that Quick Look asks if I want to be the delegate, and I respond with return YES. Even though I implement all methods in both QLPreviewPanelDataSource and QLPreviewPanelDelegate, at runtime I get this error on the console:
2010-12-24 15:32:17.235 BackMeUp[4763:80f] clicked: ~/Desktop/HUDTape.mov
2010-12-24 15:32:17.489 BackMeUp[4763:80f] [QL] QLError(): -[QLPreviewPanel setDelegate:] called while the panel has no controller - Fix this or this will raise soon.
See comments in QLPreviewPanel.h for -acceptsPreviewPanelControl:/-beginPreviewPanelControl:/-endPreviewPanelControl:.
2010-12-24 15:32:17.490 BackMeUp[4763:80f] [QL] QLError(): -[QLPreviewPanel setDataSource:] called while the panel has no controller - Fix this or this will raise soon.
See comments in QLPreviewPanel.h for -acceptsPreviewPanelControl:/-beginPreviewPanelControl:/-endPreviewPanelControl:.
2010-12-24 15:32:17.491 BackMeUp[4763:80f] We can now receive QL Events.
2010-12-24 15:32:18.291 BackMeUp[4763:80f] -[NSPathStore2 stringValue]: unrecognized selector sent to instance 0x5ecb10
2010-12-24 15:32:18.292 BackMeUp[4763:80f] -[NSPathStore2 stringValue]: unrecognized selector sent to instance 0x5ecb10
And the Quick Look panel does not show up, which I find rather odd. The first line above is just that I know the cell has been clicked. Anyways, here is the .m file of the custom table view subclass:
//
// BackupListTableView.m
// BackMeUp
//
// Created by Tristan Seifert on 12/24/10.
// Copyright 2010 24/7 Server. All rights reserved.
//
#import "BackupListTableView.h"
#implementation BackupListTableView
- (void) awakeFromNib {
}
// Quick Look Delegates
- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel;
{
[QLPreviewPanel sharedPreviewPanel].delegate = self;
[QLPreviewPanel sharedPreviewPanel].dataSource = self;
NSLog(#"We can now receive QL Events.");
return YES;
}
- (void)beginPreviewPanelControl:(QLPreviewPanel *)panel
{
// This document is now responsible of the preview panel
// It is allowed to set the delegate, data source and refresh panel.
[QLPreviewPanel sharedPreviewPanel].delegate = self;
[QLPreviewPanel sharedPreviewPanel].dataSource = self;
}
- (void)endPreviewPanelControl:(QLPreviewPanel *)panel
{
// This document loses its responsisibility on the preview panel
// Until the next call to -beginPreviewPanelControl: it must not
// change the panel's delegate, data source or refresh it.
return;
}
// Quick Look panel data source
- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel
{
return 1;
}
- (id <QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index
{
int selectedRow = [self selectedRow];
return [NSURL URLWithString:[[[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow] stringValue]];
}
// Quick Look panel delegate
- (BOOL)previewPanel:(QLPreviewPanel *)panel handleEvent:(NSEvent *)event
{
// redirect all key down events to the table view
return NO;
}
// This delegate method provides the rect on screen from which the panel will zoom.
- (NSRect)previewPanel:(QLPreviewPanel *)panel sourceFrameOnScreenForPreviewItem:(id <QLPreviewItem>)item
{
NSRect iconRect = [self rectOfColumn:1];
/*
// check that the icon rect is visible on screen
NSRect visibleRect = [self visibleRect];
// convert icon rect to screen coordinates
iconRect = [self convertRectToBase:iconRect];
iconRect.origin = [[self window] convertBaseToScreen:iconRect.origin];
*/
return iconRect;
}
// This delegate method provides a transition image between the table view and the preview panel
- (id)previewPanel:(QLPreviewPanel *)panel transitionImageForPreviewItem:(id <QLPreviewItem>)item contentRect:(NSRect *)contentRect
{
int selectedRow = [self selectedRow];
NSImage *fileIcon = [[NSWorkspace sharedWorkspace] iconForFile:[[[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow] stringValue]];
return fileIcon;
}
#end
Thanks for any help.
The documentation isn't the best for this, since it's a new feature that was added in 10.6. (Well, there is obviously the class and protocol references, but in my experience, I've always found the Companion Guides to be more helpful in understanding how the objects are intended to be used in a real-world scenario).
The QLPreviewPanelController Protocol Reference defines 3 methods:
QLPreviewPanelController Protocol Reference
The Quick Look preview panel shows previews for items provided by the first object in the responder chain that implements the methods in this protocol. You typically implement these methods in your window controller or delegate. You should never try to modify preview panel state if you’re not controlling the panel.
- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel;
- (BOOL)beginPreviewPanelControl:(QLPreviewPanel *)panel;
- (void)endPreviewPanelControl:(QLPreviewPanel *)panel;
I'm guessing that your code should look like this:
- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel
{
return YES;
}
You shouldn't be doing anything in that method besides returning YES. acceptsPreviewPanelControl: is sent to every object in the responder chain until something returns YES. By returning YES, that object effectively becomes "the controller". The latter 2 methods are called on the controller object after it returns YES from the first method. So you should only be setting the delegate and datasource in the beginPreviewPanelControl: method (at which time you will be regarded as the current controller).
- (void)beginPreviewPanelControl:(QLPreviewPanel *)panel
{
// This document is now responsible of the preview panel
// It is allowed to set the delegate, data source and refresh panel.
[QLPreviewPanel sharedPreviewPanel].delegate = self;
[QLPreviewPanel sharedPreviewPanel].dataSource = self;
NSLog(#"We can now receive QL Events.");
}
First:
-acceptsPreviewPanelControl should only return YES and not try to set delegate and datasource.
Then, the problem is that you get an exception breaking the panel:
2010-12-24 15:32:18.291 BackMeUp[4763:80f] -[NSPathStore2 stringValue]: unrecognized selector sent to instance 0x5ecb10
The exception is very likely caused by these invocations:
[[[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow] stringValue]
Very likely, [[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow] is a file path (a NSPathStore instance which is a subclass of NSString) so it does not respond to -stringValue
So replace:
[NSURL URLWithString:[[[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow] stringValue]]
by:
[NSURL fileURLWithPath:[[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow]]
Also remove the call to -stringValue in transitionImageForPreviewItem.
As a side note, it seems to be suboptimal to load the image at each call of transitionImageForPreviewItem. I suppose you already have the image computed elsewhere (displayed in your table view), try to use it.
Trying to make a simple link clicking activity work. I think I understand TTNavigator and TTStyledLabel, but can't get it to work.
Code:
#interface SomeVc : UIViewController <TTNavigatorDelegate> {
IBOutlet TTStyledTextLabel *styledTextLabel;
}
#end
#implementation SomeVc
- (void)viewDidLoad {
[super viewDidLoad];
navigator = [TTNavigator navigator];
navigator.persistenceMode = TTNavigatorPersistenceModeNone;
navigator.delegate = self;
TTURLMap* map = navigator.URLMap;
[map from:#"*" toViewController:[TTWebController class]];
styledTextLabel.text = [TTStyledText textWithURLs:someText];
[navigator openURLAction:[TTURLAction actionWithURLPath:#"http://www.cnn.com/"]];
}
- (BOOL)navigator: (TTNavigator*)navigator shouldOpenURL: (NSURL*)URL {
NSLog(#"trying to open %#", [URL absoluteString]);
return NO;
}
#end
I.e inside a viewcontroller, get the navigator and set self to be its delegate. When a link is opened, the shouldOpenURL delgate method gets called, where I will handle the URL opening myself. (I plan to let navigator handle more of it, but want to get this simple case working first.)
I have a test call at the end of viewDidLoad: which fires the delegate method fine.
Problem: I see the styledTextLabels rendered fine with URL-s, but when I tap on those, nothing happens. They don't reach the TTNavigator for some reason and I can't understand why. Feels like I'm missing some simple connection/scaffolding somewhere, but can't figure it out.
How to make it so that the links tapped in the styledtextlabel will reach the navigator delegate? Or how else should I implement this simple case with styledtextlabel? (just want to get callbacks for url taps.)
try setting the window property :
TTNavigator* navigator = [TTNavigator navigator];
navigator.window = window;
If you don't have one you can add one
navigator.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]
You might also need:
[navigator.window makeKeyAndVisible];