I need to pass back an NSMutableArray of photos between a CameraSessionView; how store the photos taken from camera on an NSMutableArray, and a TableViewController how uploads this photos to DropBox. I'm using delegates and protocols, but all the ways I tried... fail.
Anyone can help me. I think Im doing some little thing wrong.
I show you some code:
CameraSessionView.h
#class CameraSessionView;
#protocol CameraSessionViewDelegate <NSObject>
#optional
-(void)uploadPhotosFromCamera:(NSMutableArray*)photos;
#end
#property (nonatomic, weak) id <CameraSessionViewDelegate> delegado;
CameraSessionView.m
#property (nonatomic, strong) NSMutableArray* images;
- (void)onTapOkButton{
NSLog(#"Save photos");
if([self.delegado respondsToSelector:#selector(uploadPhotosFromCamera:)])
[self.delegado uploadPhotosFromCamera:_images];
[self onTapDismissButton];
}
PhotosTableViewController.h
#interface PhotosTableViewController : UITableViewController <CameraSessionViewDelegate>
PhotosTableViewController.m
#property (nonatomic, strong) CameraSessionView *camera;
- (void)viewDidLoad
{
_camera = [CameraSessionView new];
[_camera setDelegado:self];
}
-(void)uploadPhotosFromCamera:(NSMutableArray*)photos
{
NSLog(#"UPFC");
for(int x=0; x < [photos count];x++)
{
NSLog(#"UPFC...");
UIImage *foto = [photos objectAtIndex:x];
if (foto.size.height > 1000 || foto.size.width > 1000)
foto = [self imageWithImage:foto scaledToScale:0.15f];
DBMetadata* datos = [TablaSubidas addFile:pathElemento];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSData *data = UIImageJPEGRepresentation(foto, 1.0);
[fileManager createFileAtPath:[self photoPath:datos] contents:data attributes:nil];
[elementosTabla insertObject:datos atIndex:0];
}
[self sincFotos];
[self.tableView reloadData];
}
Only wants that when I press OK button the photos send back to PhotosTableViewController where it would be uploaded to dropbox.
self.delegado on onTapOKButton is always nil.
Looks easy but I cant run it.
I'm so grateful if anyone could help me or recommend me any tutorial...
Thanks!!
Your CameraSessionView instance will be released from memory as soon as viewDidLoad ends. You need to store it in a property in PhotosTableViewController so that it is retained.
Your delegate should also be defined as weak, e.g.
#property (nonatomic,weak) id< CameraSessionViewDelegate >delegado;
Then in your implementation of PhotosTableViewController, you'll need to implement the -(void)uploadPhotosFromCamera:(NSMutableArray*)photos; method.
Also as this method is defined as #optional, you should check if the delegate responds to it before calling it.
if([self.delegado respondsToSelector:#selector(uploadPhotosFromCamera:]){
[self.delegado uploadPhotosFromCamera:_images];
}
This will prevent the app from crashing if the delegate method isn't implemented.
This is working for me. So, you can implement this Directly. Hope, you will get success. Oh! first check without camera activity. Just pass simple array of string to test the delegate
/............*****************
CameraSessionView.h file
/............*****************
#import <UIKit/UIKit.h>
#class CameraSessionView;
#protocol CameraSessionViewDelegate <NSObject>
#optional
-(void)uploadPhotosFromCamera:(NSMutableArray*)photos;
#end
#interface CameraSessionView : UIViewController
#property (nonatomic,weak) id< CameraSessionViewDelegate >delegado;
#end
/............*****************
CameraSessionView.m file
/............*****************
#import "CameraSessionView.h"
#interface CameraSessionView ()
#property (nonatomic, strong) NSMutableArray* images;
#end
#implementation CameraSessionView
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(onTapOkButton)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"OK" forState:UIControlStateNormal];
button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[self.view addSubview:button];
}
- (void)onTapOkButton{
NSLog(#"Save photos");
_images = [[NSMutableArray alloc]init];
[_images addObject:#"_images1"];
[_images addObject:#"_images2"];
//NSLog(#"from del:%#",_images);
if([self.delegado respondsToSelector:#selector(uploadPhotosFromCamera:)])
[self.delegado uploadPhotosFromCamera:_images];
[self onTapDismissButton];
}
-(void)onTapDismissButton{
[self.view removeFromSuperview];
}
#end
/............*****************
DetailViewController.m file
/.........********
#import "DetailViewController.h"
#import "CameraSessionView.h"
#interface DetailViewController ()<CameraSessionViewDelegate>
#end
#implementation DetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
CameraSessionView *Camara= [[CameraSessionView alloc]initWithNibName:#"CameraSessionView" bundle:nil];
[Camara setDelegado:self];
[self.navigationController pushViewController:Camara animated:YES];
}
-(void)uploadPhotosFromCamera:(NSMutableArray*)photos{
NSLog(#"success:%#",photos);
}
#end
If you have to pass data from B View Controller To A view Controller
Create protocol in B View Controller as
#protocol BViewControllerDelegate <NSObject>
-(void)didclickonSubmit:(NSArray*)selected_array;
#end
Create an id, so that you can assign any class as its delegate class.
#property (weak,nonatomic) id<BViewControllerDelegate> delegate;
Call this method in B View Controller on submit button or wherever required.
if (self.delegate && [self.delegate respondsToSelector:#selector(didclickonSubmit:)])
{
[self.delegate didclickonSubmit:myarray];
}
Create an object of B View Controller in View Controller A and assign A as delegate of B
BViewController *b = [[BViewController alloc]init];
b.delegate=self;
Implement required protocol methods of B in A and access the array
-(void)didclickonSubmit:(NSArray*)array
{
NSArray *myarray =[[NSMutableArray alloc]initWithArray:array];
}
now you can use myarray,as u like it..
hit link for sample project
https://www.dropbox.com/s/002om8efpy6fout/passDataToPreviousContoller.zip
Hope it helps..
****EDITED****
u can for sure assign tableViewController as delegate of UIView class.
#protocol BView <NSObject>
-(void) didclickonSubmit:(NSArray*) selected_array;
#end
#interface BView : UIView
#property (weak,nonatomic) id<BView> delegate;
#end
in A i.e. your tableViewController create an object of B and assign your tableview controller as delegate of B .
BView *b=[[BView alloc]init];
b.delegate=self;
Happy Coding..:)
Related
hi i am working on an app and all was going good till now.... i am stuck at this point..
here is my storyboard snapshot..
in the DemoTableViewController when i clock on "filters" button .. Brands TableViewController is opened modally .
after user select multiple rows in Brands TableViewController ,, he then clicks on done button and view controller is dismissed by this code:
-(IBAction)DonePressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
I am storing the user selections in NSMutableSet and it is to be Used in DemoTableViewController so that i can reload the table rows according to the selection but i dont know how to send NSMutableSet to DemoTableViewController and then reload the table according to selection..
what is the right way to dismiss modal view and reload the parent DemoTableViewController
i know i am not doing it correctly but can anyone help me in doing it...
here is some code ---
DemoTVC.h
#import <UIKit/UIKit.h>
#import "MyModelClass.h"
#import "brandsTableViewController.h"
#interface demoTableViewController : UITableViewController<UITableViewDataSource,UITableViewDelegate,MyModelProtocol,FilterProtocol>
#property (strong, nonatomic) IBOutlet UITableView *demoTable;
- (IBAction)FilterPressed:(id)sender;
#end
DemoTVC.m--
the method which performs segue--
- (IBAction)FilterPressed:(id)sender {
[self performSegueWithIdentifier:#"FilterPressed" sender:self];
}
the delegate method which is called to get the values from BrandsTVC--
-(void)GetTheSet:(NSMutableSet *)MySet{
[self dismissViewControllerAnimated:YES completion:nil];
}
viewdidLoad--
- (void)viewDidLoad
{
[super viewDidLoad];
productArray = [[NSMutableArray alloc] init];
homeModel = [[MyModelClass alloc] init];
// Set this view controller object as the delegate for the home model object
homeModel.delegate = self;
// Call the download items method of the home model object
[homeModel downloadItemswithurl:#"url is written here"];
}
BrandsTVC.h---
#import <UIKit/UIKit.h>
#import "MyModelClass.h"
#protocol FilterProtocol <NSObject>
-(void)GetTheSet:(NSMutableSet *) MySet;
#end
#interface brandsTableViewController : UITableViewController<UITableViewDataSource,UITableViewDelegate,MyModelProtocol>
#property (strong, nonatomic) IBOutlet UITableView *RetailerList;
#property (strong,nonatomic) NSMutableSet *selectStates;
#property (nonatomic, weak) id<FilterProtocol> delegate;
- (IBAction) DonePressed:(id)sender;
#end
BrandsTVC.m---
#interface brandsTableViewController ()
{
MyModelClass *myModelClass;
NSMutableArray *BrandsArray;
brandsTableViewController *Delegate;
}
#end
viewDidLoad----
- (void)viewDidLoad
{
[super viewDidLoad];
BrandsArray = [[NSMutableArray alloc] init];
self.selectStates=[NSMutableSet new];
myModelClass = [[MyModelClass alloc] init];
// Set this view controller object as the delegate for the home model object
myModelClass.delegate = self;
// Call the download items method of the home model object
[myModelClass downloadItemswithurl:#"url to get json"];
self.tableView.allowsMultipleSelection = YES;
}
Done Button is called ---
- (IBAction)DonePressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
id<FilterProtocol> strongDelegate = self.delegate;
if ([strongDelegate respondsToSelector:#selector(GetTheSet:)]) {
[strongDelegate GetTheSet:self.selectStates];
}
}
#end
You can keep those elements in NSUserDefaults, and whenever DemoTableViewController appears, you send [tableView reloadData]. Do this in the viewDidAppear: method.
You can also use Core Data, but there are a lot of details to explain how to do that.
After a lot of trial and error i come to know that in BrandsTVC--
- (IBAction)DonePressed:(id)sender {
NSLog(#"done pressed %#",self.delegate);
[delegate GetTheSet:self.selectStates];
}
self.delegate is giving me NULL.
delegate is not setup and i cant figure out how to do that.. someone help me..
this answer solved my problem :D
custom viewcontroller delegate not working
I saw a lot of this kind of questions and answers here, but couldn't find solution to my problem. I'm trying to send data from one view controller to another and use delegate. But don't know why my postDelegate doesn't responds to selector. Is something wrong with this code or what is the problem?
PostViewController.h file
#protocol GetDataDelegate <NSObject>
-(void)getPassedInfo:(NSString*)info;
#end
#interface PostViewController : UIViewController
#property (nonatomic, weak) id <GetDataDelegate> postDelegate;
#end;
PostViewController.m file
#import "PostViewController.h"
- (IBAction)postData:(id)sender {
if ([_postDelegate respondsToSelector:#selector(getPassedInfo:)]) {
[self.postDelegate getPassedInfo:#"data"];
NSLog(#"responds");
}
[self dismissViewControllerAnimated:YES completion:nil];
}
in second view controllers .h file
#import "PostViewController.h"
#interface MainViewController : UITableViewController <GetDataDelegate>
and in .m file
#implementation MainWindowTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
PostViewController * postController = [[PostViewController alloc]init];
postController.postDelegate = self;
}
and here is delegate method:
-(void)getPassedInfo:(NSString *)info{
NSLog(#"info is %#", info);
}
You need to make postController a property or an ivar. Currently it is a local variable in the viewDidLoad method which will be deallocated after viewDidLoad completes as #CodaFi said above.
#import "PostViewController.h"
#interface MainViewController : UITableViewController <GetDataDelegate>
#property (nonatomic, strong) PostViewController *postController;
#end
Then:
- (void)viewDidLoad
{
[super viewDidLoad];
self.postController = [[PostViewController alloc]init];
self.postController.postDelegate = self;
}
I'm really having a tough time figuring out why one of my delegate methods performs perfectly, but another won't. Here is the relevant code for the delegate that isn't working:
SideBarController.h
#import <UIKit/UIKit.h>
#import "Report.h"
#protocol ReportSelectViewControllerDelegate <NSObject>
#optional
- (void) viewSelectMonitoredArea:(Report *)report;
#end
#interface SidebarController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, weak) id <ReportSelectViewControllerDelegate> delegate;
#property (nonatomic, weak) IBOutlet UITableView *tableView;
#property (nonatomic, weak) Report *selectedReport;
#end
SideBarController.m
#import "SidebarController.h"
#interface SidebarController ()
#end
#implementation SidebarController
#synthesize tableView = _tableView;
#synthesize delegate;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableArray *sectionArray = [self.tableViewItems objectAtIndex:indexPath.section];
NSDictionary* item = sectionArray[indexPath.row];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:item[#"title"] forKey:#"CurrentReportTitle"];
self.selectedReport = [Report where:#{#"reportTitle": item[#"title"]}].lastObject;
[self.delegate viewSelectMonitoredArea:self.selectedReport];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
DetailReportViewController.h
#import <UIKit/UIKit.h>
#import "BDBSplitViewController.h"
#import "SidebarController.h"
#interface DetailReportViewController : BDBDetailViewController <UISplitViewControllerDelegate, ReportSelectViewControllerDelegate >
#end
DetailReportViewController.m
#import "DetailReportViewController.h"
#interface DetailReportViewController ()
#end
#implementation DetailReportViewController
- (void)viewDidLoad
{
[super viewDidLoad];
SidebarController *sideBarController = [[SidebarController alloc] init];
sideBarController.delegate = self;
}
- (void) viewSelectMonitoredArea:(Report *)report {
NSLog(#"viewSelectMonitoredArea was called");
}
Another delegate written exactly the same way from another controller to the DetailReportViewController works just fine. When I put a breakpoint right after the delegate is called, I notice that the delegate has a nil value. Any help would be greatly appreciated.
EDIT:
Sorry, I forgot to put in sideBarController.delegate = self in the DetailReportViewController.h example. It is in the original code.
The DetailReportViewController class needs to get a reference to the "SideBarController" instance and then set itself as the delegate. In DetailReportViewController:
// This needs to be in the DetailReportViewController class
// Assume we have a reference to the SideBarController in the DetailReportViewController class called sideBarControllerInstance
sideBarControllerInstance.delegate = self;
The solution spurred on by Michael Dautermann was to put
DetailReportViewController *detailReport = [[DetailReportViewController alloc] init];
self.delegate = detailReport;
right before
[self.delegate createSelectMonitoredArea:self.selectedReport];
Thanks!
I have a UIButton in MainViewController.
MainViewController has a childViewContoller.
I need to access the UIButton (tcButton) property in MainViewController FROM the childViewController and set it to setSelected:YES in viewDidLoad. I have the following code in my ChildViewController.m file and it's not working.
#import "ChildViewController.h"
#import "MainViewController.h"
#import "CoreData.h"
#interface ChildViewContoller ()
#property (nonatomic, strong) CoreData *coreData;
#property (nonatomic, strong) MainViewController *mainViewController;
#end
#implementation ChildViewController
#synthesize coreData, mainViewController;
-(void)viewDidLoad
{
[super viewDidLoad];
self.managedObjectContext = [(STAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
[[(mainViewController *)self.parentViewController tcButton] setSelected:YES];
}
Your code is kind of a mess. Why are you creating a new instance of yourself in viewDidLoad? This makes no sense. If ChildViewController is truly a child view controller, then you can access the parent with self.parentViewController. You only need one line in the viewDidLoad:
-(void)viewDidLoad // Line 4
{
[[(MainViewController *)self.parentViewController tcButton] setSelected:YES]; // Line 8
}
There are several issues in your code but the main idea to perform what you want is getting a pointer to the mainViewController. There are many ways to do that but here a simple example how you can implement such thing. For instance in the initializer of the ChildViewContoller you can pass a pointer to the mainViewController:
#interface ChildViewContoller ()
#property (nonatomic, strong) MainViewController *mainViewController;
#end
#implementation ChildViewContoller
- (id)initWithMainViewController:(MainViewController *)mainViewController
{
self = [super init];
if (self)
{
_mainViewController = mainViewController;
}
return self;
}
- (void)viewDidLoad
{
[_mainViewController.tcButton setSelected:YES];
}
#end
Please not that I have not tested the code above but you can get the idea.
I have application where i have two view controllers my first view and second view controller is in uipopovercontroller. i want value of second view controller in first view for that i have created protocol. here is my code.
#import
#import "SearchPopoverController.h"
#import "AppDelegate.h"
#interface ViewController : UIViewController<PassSearchValueDelegate>{
AppDelegate *appDelegate;
SearchPopoverController *popSearch;
IBOutlet UILabel *lblAdd;
}
-(IBAction)showpop:(id)sender;
#end
#import "ViewController.h"
// my ViewController.m file code
-(void) getLocationList:(NSString *)strSearch{
lblAdd.text = strSearch;
}
-(IBAction)showpop:(id)sender{
if(![appDelegate.delObjSearchPopoverCon isPopoverVisible]){
SearchPopoverController *popser = [[SearchPopoverController alloc] init];
popSearch = popser;
[popSearch setDelegate:self];
appDelegate.delObjSearchPopoverCon = [[UIPopoverController alloc] initWithContentViewController:popSearch] ;
[appDelegate.delObjSearchPopoverCon setPopoverContentSize:CGSizeMake(400 , 150)];
[appDelegate.delObjSearchPopoverCon presentPopoverFromRect:CGRectMake(0, 0, 1, 1) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#protocol PassSearchValueDelegate
#required
-(void) getLocationList:(NSString *)strSearch;
#end
#interface SearchPopoverController : UIViewController <UITextFieldDelegate>{
AppDelegate *appDelegate;
IBOutlet UITextField *txtSearchAdd;
IBOutlet UILabel *lblSearchAdd;
id<PassSearchValueDelegate> _delegate;
}
#property (retain) id _delegate;
#end
// my SearchPopoverController.m file code
-(IBAction)btnDoneSearch_clicked:(id)sender{
NSString *strAdd = [txtSearchAdd.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
strAdd = [strAdd stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[appDelegate.delObjSearchPopoverCon dismissPopoverAnimated:YES];
if (strAdd != nil || strAdd.length != 0) {
[_delegate getLocationList:strAdd];
}
}
i am getting warning at this line.
[popSearch setDelegate:self];
and app getting crashed very next line.
Please help me for this. Any help will be appreciated.
id<PassSearchValueDelegate> _delegate;
// ...
#property (retain) id _delegate;
Your property should be named just delegate and maybe synthesized to use the _delegate instance variable. You should also specify the protocol on the property type.
Additionally, delegates should be assign (or weak under ARC) properties.
rename _delegate to delegate
You will need to change
#property (retain) id delegate;
to
#property (assign) id<PassSearchValueDelegate> delegate;
Also in PassSearchValueDelegate.m add
#implementation PassSearchValueDelegate //After this
#synthesize delegate; //add this