I want to clear all objects which added to NSVIew before call any function.
How can I do that?
I use the following function
-(void)clearAllSubviewsOfView :(NSView *)parent
{
for (NSView *subview in [parent subviews]) {
[subview removeFromSuperview];
}
}
You can make something like this:
// TSClearSupporting.h
#protocol TSClearSupporting <NSObject>
- (void) clear;
#end
// TSTextField.h
#import <Cocoa/Cocoa.h>
#import "TSClearSupporting.h"
#interface TSTextField : NSTextField <TSClearSupporting>
#end
// TSTextField.m
#import "TSTextField.h"
#implementation TSTextField
- (void) clear
{
self.stringValue = #"";
}
#end
// TSMainView.m
#import "TSMainView.h"
#import "TSClearSupporting.h"
#implementation TSMainView
- (IBAction) clearAll: (id)sender
{
NSArray* subViews = self.subviews;
for (NSView* view in subViews)
{
if ([view conformsToProtocol: #protocol(TSClearSupporting)])
{
[view performSelector: #selector(clear)];
}
}
}
Related
My cpViewController has a button that modal segues to cpScanViewController. I want to have cpScanViewController inform ViewController with a string when it has completed a successful scan. After reading numerous articles online, I believe delegation is the best way to do this?
Is the delegate being set correctly?
How does the delegate inform the cpViewController?
cpScanViewController.h
#import <UIKit/UIKit.h>
#protocol ScanDelegate <NSObject>
-(void)receivedUPC:(NSString *)Scan;
#end
#interface cpScanViewController : UIViewController
#property (nonatomic, weak) id <ScanDelegate> delegate;
#property (nonatomic, retain) NSString *UPC;
-(void)checkUPC;
#end
cpScanViewController.m
#interface cpScanViewController ()
{
NSString *UPC;
}
#end
#implementation cpScanViewController
#synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
-(void)doSomeScanStuff
{
UPC = #"a string"
// even tried
[delegate receivedUPC:UPC];
}
-(void)checkUPC
{
}
#end
cpViewController.h
#import <UIKit/UIKit.h>
#import "cpScanViewController.h"
#interface cpViewController : UIViewController <ScanDelegate>
#end
cpViewController.m
#interface cpViewController ()
{
cpScanViewController *cp;
}
#end
#implementation cpViewController
- (void)viewDidLoad
{
// set delegate
cp = [[cpScanViewController alloc] init];
[cp setDelegate:self];
}
-(void)receivedUPC:(NSString *)Scan{
// Nothing happening
NSLog(#"%#", Scan);
NSLog(#"The %#", cp.UPC);
}
#end
Because you are not calling receivedUPC method from your cpScanViewController class. You need to add [_delegate receivedUPC:self], some where in order to invoke this delegat method in cpViewController class.
I was able to get it working by using the method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
cpScanViewController *vd = (cpScanViewController *)[segue destinationViewController];
vd.delegate = self;
}
Because I made the connection in storyboards I didn't realize it needed to have the method.
my problem - I want to pass information from the TableView in DetailView, but somewhere in the self.detailViewController.detailItem no value is passed.
that is:
self.detailViewController.detailItem =#"123";
NSString *sss = self.detailViewController.detailItem;
NSLog(#"%#", sss);
In NSLog output (null)
Here is my source code:
DetailViewController.h
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController <UISplitViewControllerDelegate>
#property id detailItem;
#property id TitleOfDetail;
#property (weak, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
#end
DetailViewController.m
#import "DetailViewController.h"
#interface DetailViewController ()
#property (strong, nonatomic) UIPopoverController *masterPopoverController;
- (void)configureView;
#end
#implementation DetailViewController
#pragma mark - Managing the detail item
-(void)setTitleOfDetail:(id)newTitleOfDetail {
NSLog(#"123");
if (_TitleOfDetail != newTitleOfDetail) {
_TitleOfDetail = newTitleOfDetail;
// Update the view.
[self configureView];
}
}
-(void)setDetailItem:(id)newDetailItem
{
NSLog(#"123");
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
if (self.masterPopoverController != nil) {
self.title = self.TitleOfDetail;
[self.masterPopoverController dismissPopoverAnimated:YES];
}
}
- (void)configureView
{
// Update the user interface for the detail item.
NSLog(#"1%#", self.TitleOfDetail);
NSLog(#"2%#", [self.detailItem description]);
if (self.TitleOfDetail) {
self.title = self.TitleOfDetail;
}
if (self.detailItem) {
self.detailDescriptionLabel.text = [self.detailItem description];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
}
…
myclass.h
#class DetailViewController;
#interface myclass : UITableViewController
#property DetailViewController *detailViewController;
#end
myclass.m
#import "choiseAvtoController.h"
#import "DetailViewController.h"
#interface myclass ()
#end
#implementation myclass
#synthesize detailViewController;
…
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.detailViewController.detailItem =#"123";
NSString *sss = self.detailViewController.detailItem;
NSLog(#"%#", sss);
}
In what may be the problem and how to fix it?
P.S. Sorry for my english, I'm just learning))
Since you are using a storyboard, you should be opening the detail controller on a segue.
Look up the segue identifier (say, it's OpenDetail) in the story board, then add the following code to your initial controller:
-(void)prepareForSegue:(UIStoryboardPopoverSegue*)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"OpenDetail"]) {
DetailViewController *dest = segue.destinationViewController;
dest.detailItem =#"123";
}
}
The idea is that I hava a custom view where the user can drag and drop one or more files and the controller is able to save the path of files into an array.
How can I run a method from AppDelegate after the user drops the file in the interface?
I have these files:
AppDelegate.h:
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate>
#property (assign) IBOutlet NSScrollView *table;
#property (assign) IBOutlet NSWindow *window;
#end
AppDelegate.m:
#import "AppDelegate.h"
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
}
#end
DropView.h:
#import <Cocoa/Cocoa.h>
#interface DropView : NSView <NSDraggingDestination>
#property (assign) IBOutlet NSScrollView *table;
#property NSArray *draggedFilePaths;
#end
DropView.m:
#import "DropView.h"
#implementation DropView
#synthesize draggedFilePaths;
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self registerForDraggedTypes:[NSArray arrayWithObject:NSURLPboardType]];
}
return self;
}
-(NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender{
return NSDragOperationGeneric;
}
-(NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender{
return NSDragOperationCopy;
}
-(BOOL)prepareForDragOperation:(id<NSDraggingInfo>)sender{
return YES;
}
-(BOOL)performDragOperation:(id<NSDraggingInfo>)sender{
NSPasteboard* prb;
prb= [sender draggingPasteboard];
draggedFilePaths = [prb propertyListForType:NSFilenamesPboardType];
return YES;
}
- (void)concludeDragOperation:(id<NSDraggingInfo>)sender{
[self setNeedsDisplay:YES];
NSLog(#"path %#",draggedFilePaths);
[self populateTable];
}
- (void)drawRect:(NSRect)dirtyRect
{
}
-(void)populateTable{
NSLog(#"yes");
}
#end
Import AppDelegate.h into DropView.m, and call the method you want to run from the performDragOperation: method.
-(BOOL)performDragOperation:(id<NSDraggingInfo>)sender{
NSPasteboard* prb;
prb= [sender draggingPasteboard];
draggedFilePaths = [prb propertyListForType:NSFilenamesPboardType];
[(AppDelegate *)[[NSApplication sharedApplication]delegate] doWhatever:draggedFilePaths];
return YES;
}
Where doWhatever: is a method implemented in the app delegate.
I have a UIButton which calls a method from another UIViewController, that method calls a delegate method which is not happening.
Something like:
FirstViewController
-(void)viewWillAppear:(BOOL)animated {
//Submit Button
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(someMethod)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Submit" forState:UIControlStateNormal];
button.frame = CGRectMake(100.0, 120.0, 80.0, 40.0);
[self addSubview:button];
}
- (void)someMethod {
SecondViewController *viewC = [[SecondViewController alloc] init];
[viewC otherMethod];
}
SecondViewController
- (void)otherMethod {
NSLog(#"Verification.....");
[self.delegate foo:self Bar:self.text]; //not working when called the otherMethod from FirstViewController
}
I know I'm doing it wrong way.
A very simple example of the way protocols and delegates work in objective-c
#class A;
#protocol DelegateName<NSObject>
#optional
- (void)doSomething:(NSString *)text;
#end
#interface A: NSObject {
NSString *bar;
id <DelegateName> delegate;
}
#property (nonatomic, retain) NSString *bar;
#property (nonatomic, assign) id <DelegateName> delegate;
- (void)someAction;
#end
This is your protocol declaration.
Then when you are calling the delegate method, you need an object of the class to invoke the delegate method. In your case it is vc. You set delegate like this:
[vc setdelegate: self];
Then you invoke method, like you have done.
See if you are missing any point from this example.
Try to understand how delegate methods work .
#protocol CPUPerformanceDelegate <NSObject>
-(void)getUsedCpuOperations:(float)percent;
-(void)getKernelCpuOperations:(float)percent;
-(void)getIdleCpuOperations:(float)percent;
-(void)getUserCpuOperations:(float)percent;
-(void)getNiceCpuOperations:(float)percent;
#end
#interface CPUPerformance : NSObject{
processor_info_array_t cpuInfo, prevCpuInfo;
mach_msg_type_number_t numCpuInfo, numPrevCpuInfo;
unsigned numCPUs;
NSLock *CPUUsageLock;
}
#property(nonatomic,assign)id<CPUPerformanceDelegate>delegate;
#property(nonatomic,retain)NSTimer *updateTimer;
#end
Then
#import "CPUPerformance.h"
#implementation CPUPerformance
#synthesize delegate,updateTimer;
- (void)updateInfo
{
idlepercent = ((idle/total)*100);
userpercent = (user/total)*100;
syspercent = (sys/total)*100;
nicepercent = (nice/total)*100;
inUsepercent = (inUse/total)*100;
[delegate getIdleCpuOperations:idlepercent];
[delegate getKernelCpuOperations:syspercent];
[delegate getNiceCpuOperations:nicepercent];
[delegate getUsedCpuOperations:inUsepercent];
[delegate getUserCpuOperations:userpercent];
}
and finally
#import "CPUPerformance.h"
#interface SpecProjectFirstViewController : UIViewController<UITableViewDataSource,UITableViewDelegate,CPUPerformanceDelegate>{
//Ivars
NSMutableArray *processArray;
//User Interface Object
UILabel *cpuUsage;
UILabel *cpuIdle;
UILabel *cpuUser;
UILabel *cpuNice;
UILabel *cpuKernel;
IBOutlet UITableView *tableViews;
CPUPerformance *cpuObject;
}
=================
#import "SpecProjectFirstViewController.h"
#implementation SpecProjectFirstViewController
-(void)getIdleCpuOperations:(float)percent{
[cpuIdle setText:nil];
[cpuIdle setText:[NSString stringWithFormat:#"Idle :%.0f %%",percent]];
[cpuIdle setTextAlignment:UITextAlignmentCenter];
}
-(void)getKernelCpuOperations:(float)percent{
[cpuKernel setText:nil];
[cpuKernel setText:[NSString stringWithFormat:#"Kernel :%.0f %%",percent]];
[cpuKernel setTextAlignment:UITextAlignmentCenter];
}
-(void)getNiceCpuOperations:(float)percent{
[cpuNice setText:nil];
[cpuNice setText:[NSString stringWithFormat:#"Nice :%.0f %%",percent]];
[cpuNice setTextAlignment:UITextAlignmentCenter];
}
-(void)getUsedCpuOperations:(float)percent{
[cpuUsage setText:nil];
[cpuUsage setText:[NSString stringWithFormat:#"Used :%.0f %%",percent]];
[cpuUsage setTextAlignment:UITextAlignmentCenter];
}
It is customary to validate that the delegate responds to the method you want to call, so your otherMethod method should be implemented like this, adding more logging to help debug:
- (void)otherMethod
{
NSLog(#"delegate = %p", self.delegate);
if ([self.delegate respondsToSelector:#selector(foo::)])
{
NSLog(#"Calling delegate foo");
[self.delegate foo:self Bar:self.text];
}
else
{
NSLog(#"Delegate doesn't respond to foo");
}
}
MyNSImageView is a subclass of NSImageView, here I have:
#interface MyNSImageView : NSImageView
{
}
#end
#implementation MyNSImageView
//- (void) mouseDown: (NSEvent *) theEvent
//{
// do not wish to implement mouseDown event handler from here
//}
#end
In another class called MainView, I have:
#interface MainView : NSView
{
MyNSImageView *ImageView1;
MyNSImageView *ImageView2;
}
#end
- (void)awakeFromNib
{
ImageView1 = [[[MyNSImageView alloc] initWithFrame:NSMakeRect(5, 5, 240, 240)] autorelease];
NSImage* image1 = [[[NSImage alloc] initWithContentsOfFile: #"/Volumes/MAC DAT2/pictures/MP6107.jpg"] autorelease];
[ImageView1 setImage:image1];
[self addSubview:ImageView1];
ImageView2 = [[[MyNSImageView alloc] initWithFrame:NSMakeRect(300, 5, 240, 240)] autorelease];
image1 = [[[NSImage alloc] initWithContentsOfFile: #"/Volumes/MAC DAT2/pictures/MP5784.jpg"] autorelease];
[ImageView2 setImage:image1];
[self addSubview:ImageView2];
}
- (void) mouseDown2: (NSEvent *) theEvent
{
NSLog(#"mousedown2 from MainView");
}
- (void) mouseDown1: (NSEvent *) theEvent
{
NSLog(#"mousedown1 from MainView");
}
#end
- (void) mouseDown: (NSEvent *) theEvent
{
NSLog(#"mousedown from MainView");
}
In the MainView, when I click on the ImageView1 or ImageView2, I would like to have the mouseDown1 or mouseDown2 method to handle the event accordingly not the mouseDown method.
I have read about target/action/delegate and responder stuff, but still could not see the exact syntax to do this.
One way to handle this is with a delegate:
First you declare a delegate protocol for your NSImageView subclass:
#class MyNSImageView;
#protocol MyNSImageViewDelegate <NSObject>
- (void)myImageView:(MyNSImageView *)view mouseDown:(NSEvent *)event;
#end
#interface MyNSImageView : NSImageView {
}
// declare the delegate member
#property (assign) id<MyNSImageViewDelegate> delegate;
#end
#implementation MyNSImageView
#synthesize delegate = _delegate;
// In your mouseDown method, notify the delegate
- (void)mouseDown:(NSEvent *)event {
if([self.delegate respondsToSelector:#selector(myImageView:mouseDown:)]) {
[self.delegate myImageView:self mouseDown:event];
}
}
#end
Then, declare your MainView class to implement the MyNSImageViewDelegate protocol:
#interface MainView : NSView <MyNSImageViewDelegate> {
MyNSImageView *imageView1;
MyNSImageView *imageView2;
}
#end
And in your MainView implementation:
- (void)awakeFromNib {
// create your image views then add our instance as the delegate to each
ImageView1.delegate = self;
ImageView2.delegate = self;
}
// here we implement the `MyNSImageViewDelegate` method, which will get
// called when any `MyImageNSView` instance we've added ourselves as
// delegate to gets clicked.
- (void)myImageView:(MyNSImageView *)view mouseDown:(NSEvent *)event {
if (view == imageView1) {
NSLog(#"imageView1 clicked");
} else if (view == imageView2) {
NSLog(#"imageView2 clicked");
}
}
You should read about the responder chain. For MyCallingClass's -mouseDown: method to be called, an instance of that class has to be in the current responder chain, and no other responder further down the chain should handle that event.