Ask NSSlider if the user still has the mouse button pressed? (swift) - cocoa

Hi I'm implementing a subclass of NSSlider and NSSliderCell in swift, I would like to check/retrieve the _scFlags.isPressed property from NSSliderCell, I found that there is a 'hack' in Objective-C to do it when calling from another class (which is not really needed if you subclass NSSlider in Objective-C):
http://www.cocoabuilder.com/archive/cocoa/54913-nsslider.html
However, in swift, when I search in the API (AppKit -> NSSliderCell), I can find a struct which I suppose is the one I need, and nothing else but the init() inside:
public struct __sliderCellFlags {
public init()
}
and I can't even call it from the subclass. All these show as error:
self.__sliderCellFlags
self._scFlags
super.__sliderCellFlags
super._scFlags
Am I missing something? Is there a different way to call these properties?

Use Objective-C to implement a category on NSSliderCell which has a property to access the struct data and use the property from Swift.
NSSlider+FlagsAccessor.h
#interface NSSlider (FlagsAccessor)
#property (nonatomic, readonly) BOOL isPressed;
#end
NSSlider+FlagsAccessor.m
#import "NSSlider+FlagsAccessor.h"
#interface NSSliderCell (FlagsAccessor)
#property (nonatomic, readonly) BOOL isPressed;
#end
#implementation NSSlider (FlagsAccessor)
- (BOOL)isPressed
{
NSSliderCell *cell = self.cell;
return cell.isPressed;
}
#end
#implementation NSSliderCell (FlagsAccessor)
- (BOOL)isPressed
{
return self->_scFlags.isPressed == 1;
}
#end
Then to use It from Swift just call self.isPressed. Here's a sample project.
Don't forget to import your category header in your bridging header (Xcode will prompt you to create a bridging header when you add Objective-C code to a Swift project).

Related

Incorrect Delegate for Controls on Main Application Window

I am developing an application in XCode 4.6.
To get text-change notifications from NSTextField controls I:
Put NSTextField control on window.
Connect control delegate to File's Owner via right-click in IB, drag from delegate to File's Owner.
Implement controlTextDidChange in window class.
For the application, the window class is my AppDelegate and File's Owner is NSApplication. For the modal dialog, the window class an NSWindowController and File's Owner is of the same type.
If I put a breakpoint in controlTextDidChange, in the AppDelegate class, it never fires. If I do the same procedure with a modal dialog it works fine.
I know in the main application window case the delegate for the control is not my AppDelegate.
What am I doing wrong in hooking up my control delegate in the main window? I must be missing something simple. Is File's Owner the correct delegate to set for controls?
Any help would be appreciated.
Here is some code as requested.
// AppDelegate.h
// SimpleApplication
#import <Cocoa/Cocoa.h>
#import "SimpleTest/SimpleTest.h"
#interface AppDelegate : NSObject <NSApplicationDelegate>
#property (assign) IBOutlet NSWindow *window;
#property (assign) IBOutlet NSTextField *textField;
#end
// AppDelegate.m
// SimpleApplication
#import "AppDelegate.h"
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Not much to do here for now.
}
// Breakpoint set in this function never fires.
- (void)controlTextDidChange:(NSNotification *)obj
{
NSMutableString* description= [[NSMutableString alloc] init];
id aDelegate= [_textField delegate];
Class delegateClass= [aDelegate class];
[description setString:[delegateClass description]];
[description release];
}
// To provide some information about the delegates.
- (IBAction)textChange:(id)sender
{
NSTextField* theTextField= (NSTextField*)sender;
NSMutableString* description= [[NSMutableString alloc] init];
id aDelegate= [theTextField delegate];
Class delegateClass= [aDelegate class];
[description setString:[delegateClass description]];
[description release];
}
#end
Here is a shot of the right-click information for the NSTextField on the main window -
Identity inspector shows File's Owner as NSApplication, which is what I see in the debugger when I put a breakpoint in textChange and hit return in the text field. However, self, the implementor of controlTextDidChange, is AppDelegate. By contrast, in a modal dialog, self and File's Owner are the same object, derived from NSWindowController.
So, the upshot is that I do not have the correct delegate assigned to the control in the main window - how do I do that?
Can you post some code?
When using delegates make sure you specify that a class implements the required protocol.
#interface MyClass : NSObject <SomeProtocol>
Also make sure you are creating a property to store the delegate.
#property (strong, nonatomic) id<SomeProtocol> delegate;
RE this:
Note that although NSControl defines delegate methods, it does not
itself have a delegate. Any subclass that uses these methods must have
a delegate and the methods to get and set it. In addition, a formal
delegate protocol NSControlTextEditingDelegate Protocol also defines
delegate methods used by control delegates.
...
These include: controlTextDidBeginEditing:, controlTextDidChange:, and controlTextDidEndEditing:
Oh, wow - in adding more detail to my question, I think I figured out the answer. Instead of dragging from text field delegate to File's Owner, just drag to the blue cube that represents App Delegate!

Make a NSTableCellView editable

I created a View-Based NSTableView with a single column. This column is populated with a standard NSTableCellView from Interface Builder (I chose the version with image and textfield).
Now I want to make the textfield in the column editable.
My first attempt was to modify the NSTextField from Interface builder and set its behaviour as Editable. It works, indeed when I select a row and I push the enter key the field becomes editable and I can change its value. I thought I would be able to intercept this change thanks to some NSTableViewDataSource method like tableView:setObjectValue:forTableColumn:row: but this method never gets called in response of a textfield edit action.
Which is the right way to deal with editable field in a view-based NSTableView system? I suppose that the NSTableViewDataSource has something to do with it but I don't know how to get its methods called.
Create a subclass of NSTableCellView. (The appropriate .h and .m files) Make the class respond to the NSTextFieldDelegate protocol. Implement the control:textShouldEndEditing: method. Make this subclass the delegate of your label control.
Here is some example code.
CategoryListCell.h
#interface CategoryListCell : NSTableCellView
#end
CategoryListCell.m
#interface CategoryListCell()<NSTextFieldDelegate>
#property (weak) IBOutlet NSTextField *categoryLabel;
#property (assign) BOOL editing;
#property (copy) NSString* category;
#end
#implementation CategoryListCell
- (BOOL)control:(NSControl*)control textShouldBeginEditing:(NSText *)fieldEditor {
self.editing = YES;
return YES;
}
- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor; {
if (self.editing) {
self.editing = NO;
[self mergeFromSource:self.category toDestination:self.categoryLabel.stringValue];
}
return YES;
}
- (void)mergeFromSource:(NSString*)source toDestination:(NSString*) destination {
// your work here
}
#end
Sounds like you need to subclass the NSView that's in the NSTableView cell and make the subclassed view a delegate of the textfield. Your view will then get text change notifications via the NSTextField delegate method:
- (void)textDidChange:(NSNotification *)notification;

MKMapViewDelegate is nota called when inside a subclass of MKMapView

I am quite new in Objective C, but learning fast. My project is quite complete and I have implemented as well classes than delegates etc etc.
I am using an MKMapView to display things on a map. I also need the user to click on Pins which will give back some informations, but I do want that the MKViewMap makes some estimations before sending info.
As such I have subclassed MKMapView, and I am using this class to display. But I don't get the delegates called. It worked normally when I was using MKViewMap in a standard way. Here is some code. The subclass has a delegate protocol, and this works perfectly
// .h file
#import < MapKit/MapKit.h >
#protocol MyMapViewDelegate < NSObject >
#required
- (void) ReturnAddressToHail:(NSString*) FullAddresse andNumber:(NSString*) FullNumber;
- (void) ReturnSelectedDriverHash:(NSString*) DriverHash;
#end
#interface MyMapViewClass : MKMapView < MKMapViewDelegate >
{
id < MyMapViewDelegate > delegate;
CLLocationCoordinate2D mapCenter;
NSDictionary *Info;
CLLocation * ClientNewLocation;
}
#property (retain) id delegate;
// .m file
#import "MyMapViewClass.h"
#import "NSObject+MapAnnotationHelper.h"
#implementation MyMapViewClass
#synthesize geoCoder;
#synthesize delegate;
self.delegate = self;
-(void) mapView:(MKMapView *) mapView regionDidChangeAnimated:(BOOL)animated
{
(void) self.updateAddress;
NSLog(#"regionchange delegate");
}
The latter is never called. Any ideas?
I'm sure you have your reasons, but the docs state that you shouldn't subclass MKMapView, and instead use the delegate to change its behaviour. There may be an easier way to do whatever you're doing.
Although you should not subclass the MKMapView class itself, you can get information about the map view’s behavior by providing a delegate object.

Xcode Random Image Button, and email button

I'm trying to create an app that creates a random image button, and the code works. when my app generates an image, I'd like to create a button from which i can send an email with the screenshot attached...i know the codes for both actions, but when i put them in the controller h and m I've many errors...please help me!
#interface __3_ProductionsViewController : UIViewController
<MFMailComposeViewControllerDelegate>
-(IBAction)openMail:(id)sender;
-(IBAction)randomimagebutton;
{
IBOutlet UIImageView *imageview;
}
#end
Depending on the errors you are getting you might want to rearrange your formatting a little. This is how I would declare the h and m.
// __3_ProductionsViewController.h
#import <MessageUI/MessageUI.h>
#import <MessageUI/MFMailComposeViewController.h>
#interface __3_ProductionsViewController : UIViewController
<MFMailComposeViewControllerDelegate>
#property (nonatomic, retain) IBOutlet UIImageView *imageview;
-(IBAction)openMail:(id)sender;
-(IBAction)randomimagebutton:(id)sender;
#end
// __3_ProductionsViewController.m
#import "__3_ProductionsViewController.h"
#implementation UpdateViewController
#synthesize imageView;
-(IBAction)openMail:(id)sender {
}
-(IBAction)randomimagebutton:(id)sender {
}
#end
You'll need to connect the IBActions using interface builder as well as drag a connection to your imageView

NSTextView value changed

I'm pretty new to mac development (coming from a web and iOS background) and I can't work out how I could get a notification every time the value of an NSTextView changes. Any ideas?
Ups I just saw that you want a callback from NSTextView and not NSTextField
Just add in the header of the object which should be the delegate the protocol
#interface delegateAppDelegate : NSObject <NSApplicationDelegate, NSTextViewDelegate> {
NSWindow *window;
}
After that you add a method like
-(void)textDidChange:(NSNotification *)notification {
NSLog(#"Ok");
}
Make sure you connected the delegate property of the NSTextView (not NSScrollView) with the object which should receive the delegate
Here's the solution:
NSTextView *textView = ...;
#interface MyClass : NSObject<NSTextStorageDelegate>
#property NSTextView *textView;
#end
MyClass *myClass = [[MyClass alloc] init];
myClass.textView = textView;
textView.textStorage.delegate = myClass;
#implementation MyClass
- (void)textStorageDidProcessEditing:(NSNotification *)aNotification
{
// self.textView.string will be the current value of the NSTextView
// and this will get invoked whenever the textView's value changes,
// BOTH from user changes (like typing) or programmatic changes,
// like textView.string = #"Foo";
}
#end
set the nstextfield's delegate. in the .h file of the delegate you add the delegate protocol
In the .m file you add a method like -(void)controlTextDidChange:(NSNotification *)obj {
NSLog(#"ok");
}
I hope that helps
Set the delegate and then use
- (void) controlTextDidChange: (NSNotification *) notification
{
}

Resources