Xcode - How to call method from another class - ios

my first class .h :
#interface CollectionViewController : UICollectionViewController <..>
#property (strong, nonatomic) IBOutlet UICollectionView *collectionView;
-(void)refreshView;
#end
my first class .m
#implementation CollectionViewController
-(void)refreshView
{
[self.collectionView reloadData];
}
#end
i need to call this method from my second class
my second class .h
#interface CollectionViewCell : UICollectionViewCell
- (IBAction)buttonAction:(id)sender;
#end
my second class .m
#implementation CollectionViewCell
- (IBAction)myButtonAction:(id)sender {
//i need to call the method "refreshView" here
}
#end
I tried to edit the method refreshView from private to public but it's not compatible with "[self.collectionView reloadData];"
Thanks for help.

It's not a good idea to have your cell "know about" its collection view.
Use delegation instead...
CollectionViewCell.h
#protocol CollectionViewCellDelegate <NSObject>
- (void)refreshButtonPressedForCell:(CollectionViewCell *)cell;
#end
#interface CollectionViewCell : UICollectionViewCell
#property (nonatomic, weak) id<CollectionViewCellDelegate> delegate;
#end
CollectionViewController.m
#interface CollectionViewController : UICollectionViewController <CollectionViewCellDelegate>
#end
#implementation CollectionViewController
- (void)refreshButtonPressedForCell:(CollectionViewCell *)cell {
[self.collectionView reloadData];
}
#end
Don't forget to set the delegate property on each of your cells!

Related

delegate become nil iOS

I created a custom UIView with the buttons above , this view opens as a pop- up to a viewcontroller . I want the view controller intercepts the pressure of the buttons so I created a protocol methods but delegates in the view controller is never called.
The protocol:
#protocol InsertDelegate <NSObject>
-(void)addNode:(double)x pointY:(double)y radius:(double)r forw:(int)forw;
-(void)cancelView:(UIView*)view;
#end
In the AddNewNode.h
#interface AddNewNode : UIView
#property (assign, nonatomic)id <InsertDelegate> delegate;
- (IBAction)actionCancel:(id)sender;
- (IBAction)actionAdd:(id)sender;
#end
In the AddNewNode.m
- (IBAction)actionCancel:(id)sender { //this action is connect with storyboard
NSLog(#"%#", self.delegate);
//(null)
[self.delegate cancelView:self];
}
- (IBAction)actionAdd:(id)sender { //this action is connect with storyboard
NSLog(#"%#", self.delegate);
//(null)
[self.delegate addNode:x pointY:y radius:r forw:f];
}
In ViewController.h:
#interface ViewController : UIViewController <InsertDelegate>
In ViewController.m
(IBAction)addNewNode:(id)sender {
AddNewNode * addRowView =[[AddNewNode alloc]init];
addRowView.delegate=self;
[self.view addSubview: addRowView];
}
//delegate methods never called
-(void)addNode:(double)x pointY:(double)y radius:(double)r forw:(int)forw{
}
-(void)cancelView:(UIView*)view{
}
In UIView custom self.delegate become null and I don't understand why
What about making an IBOutlet for your
ViewController.h
#interface ViewController : UIViewController <InsertDelegate>
#property (strong, nonatomic) AddNewNode * addNewNode;
//or connect IBOutlet of your `addNewNode`
#property (strong, nonatomic) IBOutlet (addNewNode);
#end
ViewController.m
- (IBAction)addNewNode:(id)sender
{
// you dont need to allocate anymore
self.addRowView.delegate=self;
// and you need to trigger the delegate from `- (IBAction)actionAdd:(id)sender;`
[self.addRowView actionAdd:sender];
}
try the following
Create a private property to hold the instance
#implement AddNewNode()
#propery (nonatomic, strong) AddNewNode * addNewNode;
#end
from inside the button handler
(IBAction)addNewNode:(id)sender {
self.addNewNode =[[AddNewNode alloc]init];
self.addRowView.delegate=self;
}

Custom delegate method not called

I'm trying to adapt Apple's example of TableViewUpdates (expanding TableView Cells) to my own application, but I can't seem to get it to work.
I tried narrowing the problem down and I think I know where the problem lies now.
Apple uses a UITableViewController as the base controller for the view, but I have a UIViewController that has the UITableViewDelegate and DataSource as delegate methods. I added the HeaderViewDelegate to it like this:
#interface SearchViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, IngredientHeaderViewDelegate>
IngredientHeaderFooterView.h:
#import <Foundation/Foundation.h>
#include <UIKit/UIKit.h>
#protocol IngredientHeaderViewDelegate;
#interface IngredientHeaderFooterView : UITableViewHeaderFooterView
#property (nonatomic, weak) IBOutlet UILabel *lblTitle;
#property (nonatomic, weak) IBOutlet id <IngredientHeaderViewDelegate> delegate;
#property (nonatomic) NSInteger section;
- (void)toggleOpenWithUserAction:(BOOL)userAction;
#end
#protocol IngredientHeaderViewDelegate <NSObject>
#property (nonatomic) NSInteger hoi;
#optional
- (void)sectionHeaderView:(IngredientHeaderFooterView *)sectionHeaderView sectionOpened:(NSInteger)section;
- (void)sectionHeaderView:(IngredientHeaderFooterView *)sectionHeaderView sectionClosed:(NSInteger)section;
#end
In IngredientHeaderFooterView.m:
- (void)toggleOpenWithUserAction:(BOOL)userAction {
if ([self.delegate respondsToSelector:#selector(sectionHeaderView:sectionOpened:)]) {
NSLog(#"Test1");
[self.delegate sectionHeaderView:self sectionOpened:self.section];
}
if ([self.delegate respondsToSelector:#selector(sectionHeaderView:sectionClosed:)]) {
NSLog(#"Test2");
[self.delegate sectionHeaderView:self sectionClosed:self.section];
}
}
And in my UIViewController that implements the delegate:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
IngredientHeaderFooterView *ingredientHeaderView = [self.tableView dequeueReusableHeaderFooterViewWithIdentifier:SectionHeaderViewIdentifier];
IngredientDescriptionInfo *ingredientInfo = (self.sectionInfoArray)[section];
ingredientInfo.headerView = ingredientHeaderView;
ingredientHeaderView.lblTitle.text = ingredientInfo.play.name;
ingredientHeaderView.section = section;
ingredientHeaderView.delegate = self;
return ingredientHeaderView;
}
But respondsToSelector: always returns false. What could it be?
In your SearchViewController, you need to implement both methods from the protocol IngredientHeaderViewDelegate:
- (void)sectionHeaderView:(IngredientHeaderFooterView *)sectionHeaderView sectionOpened:(NSInteger)section
{
NSLog(#"section opened");
}
- (void)sectionHeaderView:(IngredientHeaderFooterView *)sectionHeaderView sectionClosed:(NSInteger)section
{
NSLog(#"section closed");
}
Also, don't forget to actually assign the delegate in IngredientHeaderFooterView. Make sure that it's not nil when toggleOpenWithUserAction: is called.
If you make sure that the methods are implemented and the delegate is actually assigned you should be good :)

iOS: how class notify something to UI view?

Starting point
I have a class, say A, used by an UI view.
A has a delegate that should notify UI view and this one should be write something on screen.
Question
What is the best approach to achieve this feature?
Seems something like observer-observable pattern
Code
---A.h
#interface A : NSObject
#end
---A.m
#implementation A
-(void)fooDelegate:(FooType *)sender {
/* Here I need to notify UI (that change notificationArea.text) */
}
---UIView.h
#interface UIView : UIViewController
#property(strong, nonatomic, retain) A* a;
#property(strong, nonatomic) IBOutlet UITextField *notificationArea;
#end
Based on the comments, I guess just code is what you're looking for...
Create your delegate protocol:
#protocol ADelegate;
#interface A : NSObject
#property (nonatomic, weak) id <ADelegate> delegate;
#end
#protocol ADelegate <NSObject>
#optional
-(void)fooDelegate:(A *)a;
#end
Notify your delegate:
#implementation A
-(void)fooDelegate:(FooType *)sender {
if ([[self delegate] respondsToSelector:#selector(fooDelegate:)]) {
[[self delegate] fooDelegate:self];
}
}
#end
Conform to the delegate protocol:
#import "A.h"
#import "MyView.h"
#interface MyView <ADelegate>
#end
#implementation MyView
-(void)fooDelegate:(A *)a {
// update text field here
}
#end
Finally, whenever you create an instance of A, set the delegate (where self in this example is an instance of MyView:
A *a = [[A alloc] init];
[a setDelegate:self];

iOS Protocol Issues

I have been staring at code too long and know i am doing something silly here with my Protocols if someone could enlighten me that would be great.
Trying to get my areaNameLabel to change to cell.nameLabel.text across viewcontrollers.
FirstTableViewController.h
#import <UIKit/UIKit.h>
#import "FirstTableCell.h"
#import "SecondViewController.h"
#interface FirstTableViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate, passNames>
#property (nonatomic, strong) NSString *passedNameString;
#property (strong, nonatomic) NSMutableArray *names;
FirstTableViewController.m
#import "FirstTableViewController.h"
#interface FirstTableViewController ()
#end
#implementation FirstTableViewController
#synthesize names;
#synthesize passedNameString;
- (void)viewDidLoad
{
[super viewDidLoad];
names = [NSMutableArray arrayWithObjects:#"Bondi", #"Miranda", nil];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
FirstTableCell *cell = (FirstTableCell *)[tableView cellForRowAtIndexPath:indexPath];
if ([cell.nameLabel.text isEqualToString:#"Bondi"]) {
SecondViewController *mapController = [[SecondViewController alloc] init];
NSString *passedName = cell.nameLabel.text;
mapController.passedNameString = passedName;
[mapController setDelegate:self];
self.tabBarController.selectedIndex = 1;
NSLog(#"Hola");
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - Protocol Methods
-(void)setAreaName:(NSString *)areaName {
passedNameString = areaName;
}
SecondViewController.h
#import <UIKit/UIKit.h>
#protocol passNames <NSObject>
-(void)setAreaName:(NSString *)areaName;
#end
#interface SecondViewController : UIViewController <RMMapViewDelegate>
#property (retain) id <passNames> delegate;
#property (nonatomic, strong) NSString *passedNameString;
#property (weak, nonatomic) IBOutlet RMMapView *mapView;
#property (weak, nonatomic) IBOutlet UILabel *areaNameLabel;
#end
SecondViewController.m
#import "SecondViewController.h"
#import "FirstTableViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController #synthesize areaNameLabel; #synthesize delegate, passedNameString;
- (void)viewDidLoad {
[super viewDidLoad];
passedNameString = areaNameLabel.text;
[[self delegate] setAreaName:passedNameString];
if ([areaNameLabel.text isEqualToString:#"Bondi"]) {
NSLog(#"You got it!");
}
}
Any other critiques feel free to throw in - I've had a look at some other Protocol questions and examples but i know it is something obvious i am missing.
The problem is that your SecondViewController has no relationship to the passNames protocol (being declared in the same header does not count).
Since protocol methods need to be implemented (or their implementation be inherited from the base) and your SecondViewController does not do that, you cannot call setAreaName: without triggering an error.
If you would like to use a common protocol in two view controllers, you need to do this:
Give passNames protocol a more conventional name that starts in a capital letter, and put it in a separate header file
Include that header in both view controllers (the #import "SecondViewController.h" in the FirstTableViewController.h does not look right)
Put implementations of setAreaName: in both view controllers.
Note that you cannot put the common functionality in a superclass, because your view controllers inherit from different bases (i.e. UIViewController and UITableViewController).

ios - respondsToSelector always false with custom delegate

I was playing around with MKMap and some custom delegate it's not working here and i really don't know why :/
Here's my code :
LocationViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#protocol LocationViewDelegate <NSObject>
#required
- (void)didReceiveLocation:(CLLocation *)location;
#end
#interface LocationViewController : UIViewController <CLLocationManagerDelegate>
#property (strong, nonatomic) IBOutlet UILabel *locationLabel;
#property (nonatomic, strong) id<LocationViewDelegate> delegate;
- (IBAction)sendLocation:(id)sender;
#end
LocationViewController.m
[...]
- (IBAction)sendLocation:(id)sender {
if ([_delegate respondsToSelector:#selector(didReceiveLocation:)]) {
[_delegate didReceiveLocation:_currentLocation];
} else {
NSLog(#"nope");
}
}
[...]
MapViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "LocationViewController.h"
#interface MapViewController : UIViewController <LocationViewDelegate>
#end
MapViewController.m
[...]
- (void)didReceiveLocation:(CLLocation *)location {
_mapView.centerCoordinate = location.coordinate;
}
[...]
I'm always getting the "nope" message means that respondsToSelector returns NO.
I did pretty the same example a few days ago and everything was fine.
Someone can see where's the problem here ?
Set your MapViewController as the delegate for the LocationViewController i.e. in your MapViewController.m:
self.locationViewController.delegate = self;
Just as an aside, I'm presuming your MapViewController owns a LocationViewController instance, if so it's better to set the delegate property in LocationViewController to 'weak' to avoid a circular reference. #property (nonatomic, weak) id delegate;

Resources