How do I delegate the textStorageDidProcessEditing notification? - objective-c

I try to make it as short as possible, please don't get me wrong if I provide not enough information:
I got a NSTextView in a document-based cocoa application which is the result of a tutorial by Apple for programming a text editor within 15 minutes. In my "PureBasicDocument.m" implementation I got the textDidChange method which is called every time I change something in the NSTextView. I also got the method for the textStorageDidProcessEditing notification, but it is never called. How do I invoke it? I am sure I simply just forgot to assign outlets or something like that. But staring and looking over and over again at the textView and the window for their outlets did not bring me further. I am clueless. Better than nothing, here's at least the header file ("PureBasicDocument.h") of my document class for now:
#import <Cocoa/Cocoa.h>
#interface PureBasicDocument : NSDocument {
IBOutlet NSTextView *textView;
NSAttributedString *mString;
}
- (NSAttributedString *) string;
- (void) setString: (NSAttributedString *) value;
- (void) textDidChange: (NSNotification *) notification;
- (void) textStorageDidProcessEditing: (NSNotification *) notification;
#end
I apologize again if I did not use the "delegate" (and further) expressions right, I am still completely new to Objective-C and programming on a Mac in general.

right click the pureBasicDocument Object in the MainMenu.xib.You can see the outlets(textView).
from there you can make the connection to the respective tableview.
make sure whether you have include the delegate

Related

Why is this delegate method automatically called in Objective-C?

I'm going through this book called "cocoa programming for mac os x" and I just started with delegates. This whole thing with delegates is still a little bit wacky to me but I think I just need to let it settle.
However there was this one exercise where I should implement a delegate of the main window so that if resized height is always 2xwidth.
So I got 4 files:
AppDelegate.h
AppDelegate.m
WindowDelegate.h
WindowDelegate.m
AppDelegate are just the two standard files that get created when you open a new Cocoa project. I had to look up the solution because I didn't quite know how to accomplish this task.
The solution was just to create a new cocoa class, "WindowDelegat.h/.m" and add this to it's implementation file:
- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize {
NSSize newSize = frameSize;
newSize.height = newSize.width * 2;
return newSize;
}
Then I opened the interface builder, added a new object and made it my WindowDelegate. I then had to ctrl drag from the WindowDelegate to the actual window and made it the window's delegate.
Clicked run and it worked. Yay! But why?
First I thought that "windowWillResize" is just one of these callback functions that get's called as soon as the window is resized but it isn't. Normally methods get invoked because the general lifecycle of an program invokes them or because they are an #IBAction, a button or different control elements.
But "windowWillResize" is non of them. So why is it called?
EDIT: Problem solved! Thanks a lot!
Now I'm trying to connect the delegate to the window programmatically. Therefore I deleted the referencing outlet from WindowDelegate to the actual window in interface builder. It works but I just want to verify that this it the correct way how it's done:
AppDelegate.h
#import <Cocoa/Cocoa.h>
#import "WindowDelegate.h"
#interface AppDelegate : NSObject <NSApplicationDelegate>
#end
AppDelegate.m
#import "AppDelegate.h"
#interface AppDelegate ()
#property (weak) IBOutlet NSWindow *window;
#property (strong) WindowDelegate *winDeleg;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
- (void)awakeFromNib {
[_window setOpaque:NO];
NSColor *transparentColor = [NSColor colorWithDeviceRed:0.0 green:0.0 blue:0.0 alpha:0.5];
[_window setBackgroundColor:transparentColor];
NSSize initialSize = NSMakeSize(100, 200);
[_window setContentSize:initialSize];
_winDeleg = [[WindowDelegate alloc] init];
[_window setDelegate: _winDeleg];
}
#end
WindowDelegate.h
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#interface WindowDelegate : NSObject <NSWindowDelegate>
#end
WindowDelegate.m
#import "WindowDelegate.h"
#implementation WindowDelegate
- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize {
NSSize newSize = frameSize;
newSize.height = newSize.width * 2;
return newSize;
}
- (id)init {
self = [super init];
return self;
}
#end
Why does the #property of WindowDelegate need to be strong?
And isn't my winDeleg an object? Why do I have to access it through _winDeleg when it's an object. I though the underscore is used to access variables?
Thank you for your help!
Clicked run and it worked. Yay! But why?
Because instances of NSWindow have a delegate property that can point to any object that implements the NSWindowDelegate protocol, and that protocol includes the -windowWillResize:toSize: method.
Read that a few times. The reason it's important is that you can create your own object, say that it implements NSWindowDelegate, implement -windowWillResize:toSize:, and set that object as your window's delegate. Then, whenever the user resizes the window, your method will be called and can modify the proposed new size.
Normally methods get invoked because the general lifecycle of an program invokes them or because they are an #IBAction, a button or different control elements. But "windowWillResize" is non of them. So why is it called?
This really isn't so different. Think of delegates as "helper objects." They let you customize the behavior of an object without having to create a whole new subclass. The NSWindowDelegate object is essentially a contract that the NSWindow promises to follow: whenever certain things happen, such as the user resizing the window, the window will call certain methods in its delegate object, if the delegate exists and implements those methods. In the case of NSApplication, a lot of those delegate methods are application lifecycle events, like the app starting up or quitting or getting a message from the operating system. In the case of NSWindow, delegate methods correspond to interesting events that can happen to a window, like the user moving it, hiding it, showing it, maximizing it, moving it to a different screen, etc. Other classes, like text views or network connections or movie players, have their own sets of interesting events and their own delegate protocols to match.
Note that methods marked IBAction really aren't delegate methods, they're just methods that get called by objects like controls that use a target/action paradigm. The IBAction keyword lets the IDE know which methods it should present as possible actions for things like buttons. You often find actions in window controllers and view controllers, and those objects frequently act as a delegate for some other object, but the actions themselves aren't part of the delegate protocol. For example, NSTableView takes a delegate object that determines how the table will act and what's displayed in it. It often makes sense for the view controller that manages the table to be the table's delegate, and that same view controller might also manage some buttons and contain the action methods that said buttons trigger, but the actions aren't part of the NSTableViewDelegate protocol and you therefore wouldn't call them delegate methods.

NSTextField Subclass textDidEndEditing: Deleting Text

I have an NSTextFeild Subclass in which I would like to implement textDidEndEditing: to check after each edit if it is empty or not. The method is being called perfectly, but when I click into another NSTextField (or a subclass), all the text that was in the first textfield is immediately deleted. If I click out into the view, the text stays, but is deleted the next time i click into another textfeild. All I have in the method right now is an NSLog. Does anyone have any ideas as to why this could be happening?
#import "BufferTableCellViewTextField.h"
#implementation BufferTableCellViewTextField
- (void)textDidEndEditing:(NSNotification *)notification{
NSLog(#"END");
}
#end
You need to call -super:
- (void)textDidEndEditing:(NSNotification *)notification;
{
[super textDidEndEditing:notification];
NSLog(#"END");
}
This delegate method wouldn't be causing your problem. I'd look back to your subclass and check to see that you are not using any UITextField delegate methods that are expecting a YES response that you may have inadvertently changed the return responses for. It may be helpful to post you subclass so we can see what is going on in there too...

Dismissing view using delegation not working

I am trying to use delegation, which I am new at, to dismiss a modally presented view. I am trying to get it to work along the lines of the apple documentation seen here. So far my code is as follows:
Put both views on storyboard, connect first to second view with modal segue. (the segue to view2 works fine)
create delegate inside second viewcontroller/create method to call when returned:
//inside of view2ViewController.h
#class view2ViewController;
#protocol view2ViewControllerDelegate <NSObject>
-(void)goBack:(OptionsViewController *)controller;
#end
#interface OptionsViewController : UIViewController
#property (nonatomic, weak) id <view2ViewControllerDelegate>delegate;
- (IBAction)return:(id)sender;//connected to button
#end
implement delegate in view1ViewController #interface view1ViewController : UIViewController <view2ViewControllerDelegate>
write code for delegate method goBack in view1Controller.m
-(void)goBack:(view2ViewController *)controller{
[self dismissViewControllerAnimated:YES completion:nil];}
finish by writing code for return method in view2ViewController.m
- (IBAction)return:(id)sender {
[self.delegate goBack:self];}
I'm not sure where this code is going wrong. The return method is called, but then goBack isn't. I did read the developer documentation, and thought I understood, but I guess not...
PS I change the names of all of my class/variable names on StackOverflow to be more generic, so if there is a slight discrepancy between variable name spellings, it's probably because i typed one wrong.
The best shot I can try -
Make sure you assigned the SplashViewController as the delegate of the view2ViewController.
By code you can do it like that (in the SplashViewController m file):
view2ViewController.delegate = self;
Or you can do to on Story board.
BTW
I a not sure calling your function "return" is a good idea.

Populate text in one textfield from text in another

Working on an experiment on the iPad. Tried some variations on how to do this, but I can't seem to get it to work correctly...
I tap a UIButton on my MainViewController and a TextEntryModule is added to the view. TextEntryModule is its own class (for multiple instantiation) and it contains a UITextView called TextEntry (this all works at the moment).
I tap on the TextEntry UITextView and it brings up the keyboard and another view (located in MainViewController) with a UITextView called TextPreview. (this also works at the moment).
The part I'm having trouble with is synching the two UITextViews. The idea being that when I type into TextEntry, the text in TextPreview will also be updated.
Outlets are linked properly for the text fields, but I think I'm missing something "obvious":
TextEntryModule *tm = (AnnotationModule *)currentModule;
TextPreview.text = tm.TextEntry.text
Thanks in advance!
UITextView: delegate.
- (void)textViewDidChange:(UITextView *)textView
Then assign it the value of the other textview in this method.
Edit
#interface MainViewController <UITextViewDelegate> {
...
}
...
#end
Then you implement this method in the implementation file of MainViewController
#implementation MainViewController
//More code
- (void)textViewDidChange:(UITextView *)textView {
TextEntryModule *tm = (AnnotationModule *)currentModule;
TextPreview.text = tm.TextEntry.text
}
#end
Then you will have to set the TextEntryModule object's delegate to self since the controller now conform to the protocol and can "act" upon this notification.
You need to become a UITextFieldDelegate and monitor when text changes in the one field and then update the other field. Take a look at the documentation on it.

How do I handle a mousedown event inside a window in Cocoa

How do I handle a mousedown event inside a window in Cocoa?
My code:
-(void)mouseDown:(NSEvent *)event {
NSLog(#"yay");
}
I am using Mac OS10.6, in xcode 4.0.1.
EDIT:
Yes, this is in the app delegate, but this is my .h:
#interface jumperAppDelegate : NSWindow {
Which I have done before in app delegates (just not for mouse events). This is really annoying me
Make sure you inherit from NSWindow, as well as conform to the <NSWindowDelegate> protocol. Like this:
#interface YourWindow : NSWindow <NSWindowDelegate> {}
#end
Then you should receive the event notification.
-(void)mouseDown:(NSEvent *)event {
}
For this method to be called the class it is being called in needs to inherit from NSResponder. Windows and views are all subclasses of NSResponder. If the class you are calling this from is not a subclass of NSResponder then the method will not fire.
* Update *
Also be sure to override acceptsFirstResponder to return yes.
- (BOOL)acceptsFirstResponder {
return YES;
}
I don't know for sure, but I have heard that in your header file (.h) that you need to replace the "NSObject" with "NSWindow". I would test it but I am not at my computer right now.
Also, make sure that you put the following code into your header file:
- (void) mouseDown:(NSEvent*)event;
EDIT: I have done some tests and research, but I cannot get it to work. I have two tips though.
Use the '-acceptsFirstMouse method.
Try creating an NSEvent:
NSEvent * someEvent;
-(void)mouseDown:(NSEvent*)someEvent;
This probably won't work, but I will have more information tomarrow