IPhone application view transition becomes jerky - iphone

I have a view containing a UITableView using prototype cells. It contains a few labels I have connected to a subclassed UITableViewCell in interface builder.
When I click a row, I have created a segue in a storyboard to a detail view. This view can also be accessed via a segue from another class.
My table and detail views use a navigation controller.
My problem is that when I transition from the table view to the detail view and back again multiple times, I've noticed that after a while the transition from the detail view back to the table view starts getting jerky. The table scrolling begins to be slightly jerky too.
I'm using ARC.
If anyone can give me tips on what is likely to cause this, or tools I should use to investigate it would be really appreciated.
I'll put down some of my source code in case that helps. Please let me know if there's anything else I should provide.
The table view is populated from a remote service, however the problem occurs after the table is already populated and I'm not calling the service again.
Table view header:
#import <UIKit/UIKit.h>
#import "SearchManager.h"
#interface SearchViewController : UIViewController <UISearchBarDelegate, UITableViewDelegate, UITableViewDataSource, FreeTextSearchClient>
#property (nonatomic, retain) IBOutlet UITableView *TableView;
#end
Table view code:
#import "SearchViewController.h"
#import "SearchManager.h"
#import "LocationTableViewCell.h"
#import "StarRatingDisplay.h"
#import "LocationViewController.h"
#interface SearchViewController ()
#end
#implementation SearchViewController
#synthesize TableView;
SearchManager *searchManager;
NSArray *locations;
bool isSearching = false;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewWillAppear:(BOOL)animated {
//hide nav bar
[self.navigationController setNavigationBarHidden:true];
//deselect cell
NSIndexPath *selectedPath = [self.TableView indexPathForSelectedRow];
[self.TableView deselectRowAtIndexPath:selectedPath animated:false];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
searchManager = [[SearchManager alloc] initWithFreeTextClient:self];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"LocationDetails"])
{
// Get reference to the destination view controller
LocationViewController *vc = [segue destinationViewController];
NSIndexPath *indexPath = [self.TableView indexPathForSelectedRow];
vc.location = [locations objectAtIndex:indexPath.row];
}
}
- (void)showStarRating:(LocationTableViewCell*) cell: (float) score {
int x = cell.titleLabel.frame.origin.x;
int y = cell.ratingLabel.frame.origin.y + 2;
//add rating
NSArray *stars = [StarRatingDisplay GetTinyStarsForScore:score];
NSEnumerator *enumerator = [stars objectEnumerator];
UIImage *thisStar;
int i = 0;
//create image views for stars and place them on the callout
while(thisStar = [enumerator nextObject]) {
UIImageView *view = [[UIImageView alloc] initWithImage:thisStar];
view.frame = CGRectMake(x+(thisStar.size.width + 2)*i, y, thisStar.size.width, thisStar.size.height);
[cell.contentView addSubview:view];
i++;
}
}
#pragma mark - UITableView
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if([locations count] == 0 && isSearching) {
return 1;
}
else {
return [locations count];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([locations count] == 0) {
return 53;
} else {
return 77;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([locations count] > 0) {
LocationTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"LocationCell"];
Location *location = [locations objectAtIndex:indexPath.row];
cell.titleLabel.text = location.Name;
cell.addressLabel.text = location.Address.description;
cell.ratingLabel.text = [NSString stringWithFormat:#"%d rating%#", location.Ratings, (location.Ratings != 1 ? #"s" : #"")];
[self showStarRating:cell :location.Score];
return cell;
}
else {
//if there are no locations, show the no results cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"NoResults"];
return cell;
}
}
#pragma mark - UISearchBarDelegate
- (void) searchBarSearchButtonClicked:(UISearchBar *)searchBar {
if(searchBar.text.length > 0) {
[searchManager FreeTextSearch:searchBar.text];
[searchBar resignFirstResponder];
isSearching = true;
}
}
- (void) searchBarCancelButtonClicked:(UISearchBar *)searchBar {
//clear search and remove keyboard
searchBar.text = #"";
[searchBar resignFirstResponder];
isSearching = false;
}
#pragma mark - SearchClient delegate
- (void) ReceiveTextSearchResponse:(NSArray *) response {
NSLog(#"Response received");
locations = response;
[self.TableView reloadData];
}
#end
Table cell header:
#import <UIKit/UIKit.h>
#protocol RatingTableViewDelegate <NSObject>
#required
- (void) changeCommentCellHeight:(int) height;
- (void) setEditingOffset;
- (void) removeEditingOffset;
#end
Table cell:
#interface RatingTableCellViewController : UITableViewCell <UITextViewDelegate>
#property (nonatomic, unsafe_unretained) id <RatingTableViewDelegate> tableViewDelegate;
#property (nonatomic, assign) bool hasRating;
#property (nonatomic, assign) float rating;
#property (nonatomic, retain) IBOutlet UILabel *label;
#property (nonatomic, retain) IBOutlet UILabel *yourRatingLabel;
#property (nonatomic, retain) IBOutlet UITextView *textView;
#property (nonatomic, retain) IBOutlet UIImageView *star1;
#property (nonatomic, retain) IBOutlet UIImageView *star2;
#property (nonatomic, retain) IBOutlet UIImageView *star3;
#property (nonatomic, retain) IBOutlet UIImageView *star4;
#property (nonatomic, retain) IBOutlet UIImageView *star5;
- (IBAction) submitClicked:(id)sender;
- (IBAction) cancelClicked:(id)sender;
- (void) openCell;
- (void) closeCell;
- (void) cancelRating;
#end
Detail view header:
#import <UIKit/UIKit.h>
#import "Location.h"
#import "RatingTableCellViewController.h"
#interface LocationViewController : UITableViewController <RatingTableViewDelegate>
#property (retain, nonatomic) Location *location;
#property (retain, nonatomic) IBOutlet UITableViewCell *averageRatingCell;
#property (retain, nonatomic) IBOutlet RatingTableCellViewController *yourRatingCell;
#property (retain, nonatomic) IBOutlet UILabel *ratingLabel;
#property (retain, nonatomic) IBOutlet UILabel *address;
#end
Detail View:
#import "LocationViewController.h"
#import "StarRatingDisplay.h"
#import "RatingViewController.h"
#import "RatingTableCellViewController.h"
#interface LocationViewController ()
#end
#implementation LocationViewController
#synthesize location;
#synthesize averageRatingCell, yourRatingCell;
#synthesize ratingLabel;
#synthesize address;
int commentCellHeight = 45;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewWillAppear:(BOOL)animated {
[self showStarRating:averageRatingCell];
ratingLabel.Text = [NSString stringWithFormat: #"%d Rating%#:", location.Ratings, location.Ratings != 1 ? #"s" : #""];
self.navigationItem.title = location.Name;
address.text = location.Address.description;
address.lineBreakMode = UILineBreakModeWordWrap;
address.numberOfLines = 5;
yourRatingCell.tableViewDelegate = self;
// Show the nav bar. It might be hidden if coming from search view.
[self.navigationController setNavigationBarHidden:false];
}
- (void) setEditingOffset {
[self.tableView setContentOffset:CGPointMake(0, 60)];
}
- (void) removeEditingOffset {
[self.tableView setContentOffset:CGPointMake(0, 0)];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0 && indexPath.row == 1) {
return commentCellHeight;
}
else if(indexPath.section == 1 && indexPath.row == 0) {
return 70;
}
return 45;
}
- (void) changeCommentCellHeight:(int) height {
commentCellHeight = height;
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
- (void)showStarRating:(UITableViewCell*) cell {
int x = 132;
int y = 12;
//add rating
NSArray *stars = [StarRatingDisplay GetStarsForScore:location.Score];
NSEnumerator *enumerator = [stars objectEnumerator];
UIImage *thisStar;
int i = 0;
//create image views for stars and place them on the callout
while(thisStar = [enumerator nextObject]) {
UIImageView *view = [[UIImageView alloc] initWithImage:thisStar];
view.frame = CGRectMake(x+(thisStar.size.width + 2)*i, y, thisStar.size.width, thisStar.size.height);
[cell.contentView addSubview:view];
i++;
}
}
- (void) viewWillDisappear:(BOOL)animated {
//reset the comment/rating cell height
NSIndexPath *commentPath = [NSIndexPath indexPathForRow:1 inSection: 0];
RatingTableCellViewController *ratingCell = (RatingTableCellViewController*)[self.tableView cellForRowAtIndexPath:commentPath];
[ratingCell cancelRating];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end

Related

Custom Cell can't display in Table view in ios 6

#import "MasterViewController.h"
#import "DetailViewController.h"
#interface MasterViewController ()
#end
#implementation MasterViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Master", #"Master");
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
self.clearsSelectionOnViewWillAppear = NO;
self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
}
}
return self;
}
- (void)dealloc
{
[_detailViewController release];
[super dealloc];
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 100.0;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier: CellIdentifier];
if (cell == nil)
{
cell = [[[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.cellDate.text=#"date";
cell.cellDescription.text =#"Description";
cell.cellImageview.image = [UIImage imageNamed:#"facebook.png"];
cell.cellTitle.text = #"Title";
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
if (!self.detailViewController) {
self.detailViewController = [[[DetailViewController alloc] initWithNibName:#"DetailViewController_iPhone" bundle:nil] autorelease];
}
[self.navigationController pushViewController:self.detailViewController animated:YES];
}
else
{
}
}
#end
.h file
#import <UIKit/UIKit.h>
#import "CustomCell.h"
#import "XMLStringFile.h"
#class DetailViewController;
#interface MasterViewController : UITableViewController{
}
#property (strong, nonatomic) DetailViewController *detailViewController;
#property(strong,nonatomic)CustomCell *customCell;
#end
CustomCell.h
#import <UIKit/UIKit.h>
#interface CustomCell : UITableViewCell{
IBOutlet UIImageView *cellImageview;
IBOutlet UILabel *cellTitle;
IBOutlet UILabel *cellDescription;
IBOutlet UILabel *cellDate;
}
#property (retain, nonatomic) IBOutlet UIImageView *cellImageview;
#property (retain, nonatomic) IBOutlet UILabel *cellTitle;
#property (retain, nonatomic) IBOutlet UILabel *cellDescription;
#property (retain, nonatomic) IBOutlet UILabel *cellDate;
#end
CustomCell.m
#import "CustomCell.h"
#implementation CustomCell
#synthesize cellDate;
#synthesize cellDescription;
#synthesize cellImageview;
#synthesize cellTitle;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)dealloc {
[super dealloc];
}
#end
This is my both class
here Problem is in tableview data of the customcell cant Display onlt white screen.
Here i work in ios with masterdetails view template..
here i have also added m file in compile source
Customcell.xib size is 300X100
Here my output
My xib file as below
please help me to solve problem
if(cell == nil)
{
NSArray *outlets = [NSArray arrayWithArray:[[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil]];
for(id obj in outlets)
{
if([obj isKindOfClass:[UITableViewCell class]])
{
cell = (CustomCell *)obj;
}
}
}
If your CustomCell is made via XIB then Write this Code where your cell is nil.
EDIT:-
This may be the cause - I think you haven't changed your CustomCell's class name. Follow these steps -
Take a XIB with name CustomCell.xib then delete its view.
Take a UITableViewCell and set its height and structure according to you.
Select File's Owner and change its class name to CustomCell, Same thing do with UITableViewCell... select it and change its class name to CustomCell.
Now connect all subView's IBOutLets.
Note:- Select IBOutLets by right clicking on UITableViewCell not from File's Owner.
Do the following in viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
UINib *nib = [UINib nibWithNibName:#"Customcell" bundle:nil];
[[self tableView] registerNib:nib forCellReuseIdentifier:#"CustomCell"];
}
If the cell is designed in a nib then you need to load the cell from the nib.
This actually has support in UIKit since iOS 5
What you need to do is register your nib with the UITableView.
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:#"Customcell" bundle:nil]
forCellReuseIdentifier:#"CustomCell"];
//...
}
Now your tableView:cellForRowAtIndexPath: just needs to look like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CustomCell";
CustomCell *cell = (id)[tableView dequeueReusableCellWithIdentifier: CellIdentifier];
cell.cellDate.text = #"date";
cell.cellDescription.text = #"Description";
cell.cellImageview.image = [UIImage imageNamed:#"facebook.png"];
cell.cellTitle.text = #"Title";
return cell;
}
NB
Make sure to remember to set CustomCell as the reuseIdentifier in the xib
Some other observations
Really you should be using ARC for a new project.
#synthesize is implicit so not required in most cases
It's probably a bad idea to #import "CustomCell.h" in MasterViewController.h.
You should move this to the .m and use a forward declaration in the .h instead - #class CustomCell;
You also do not need to declare the backing ivars for properties as these will also be generated by the compiler e.g. you don't need to declare the following
#interface CustomCell : UITableViewCell {
IBOutlet UIImageView *cellImageview;
IBOutlet UILabel *cellTitle;
IBOutlet UILabel *cellDescription;
IBOutlet UILabel *cellDate;
}

Master-Detail - Different cells to different UiTablevIewControllers

Im having a problem connecting the different tableViewCells to different UiTableViewControllers. The first cellrow gets connected to the right TableViewController but after that cant get any further because I really dont know how to set the "else if" statement here.
Thanks in advance!
Please see the .m(master):
#import "GuideTableViewController.h"
#import "GuideDetailTableViewController.h"
#import "GuideDetailTableViewController2.h"
#import "GuideDetailTableViewController3.h"
#import <QuartzCore/QuartzCore.h>
#interface GuideTableViewController (){
NSArray *guide;
NSMutableData *weatherResponseData;
}
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (weak, nonatomic) IBOutlet UIImageView *imgHeader;
#property (weak, nonatomic) IBOutlet UIImageView *ImgTitle;
#property (weak, nonatomic) IBOutlet UIImageView *ImgWeather;
#property (weak, nonatomic) IBOutlet UIButton *btnMap;
#property (weak, nonatomic) IBOutlet UILabel *LabelWeather;
#end
#implementation GuideTableViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
//JSON method
- (void) loadJSON{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//code
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"https://dl.dropbox.com/u/100670549/test.json"]];
NSError *error;
if (data)
{
guide = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
for (NSDictionary *dictionary in guide){
//NSLog([dictionary description]);
}
}else
{
NSLog(#"Could not load data");
}
dispatch_sync(dispatch_get_main_queue(), ^{
// code
[self.tableView reloadData];
});
});
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//Call json
[self loadJSON];
[self loadWeather];
//set background
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"background.jpg"]];
//rounded corners
[self.tableView.layer setCornerRadius:9.0];
[self.ImgWeather.layer setCornerRadius:9.0];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//TableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 3;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
NSDictionary *dict = [guide objectAtIndex:indexPath.row];
cell.textLabel.text = [dict valueForKey:#"title"];
return cell;
}
//To detailView
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"showStay"]){
GuideDetailTableViewController *tvc = [segue destinationViewController];
NSIndexPath *index = sender;
NSDictionary *dict = [guide objectAtIndex:index.row];
tvc.stay = dict;
}
else if([segue.identifier isEqualToString:#"showEat"]){
GuideDetailTableViewController2 *tvc = [segue destinationViewController];
NSIndexPath *index = sender;
NSDictionary *dict = [guide objectAtIndex:index.row];
tvc.eat = dict;
}
else if([segue.identifier isEqualToString:#"showDo"]){
GuideDetailTableViewController3 *tvc = [segue destinationViewController];
NSIndexPath *index = sender;
NSDictionary *dict = [guide objectAtIndex:index.row];
tvc.todo = dict;
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self performSegueWithIdentifier:#"showStay" sender:indexPath];
}
- (void) viewWillAppear:(BOOL)animated{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.tableView.indexPathForSelectedRow];
//ta bort markeringen när man går tillbaka till master från detailView.
[cell setSelected:NO];
//Hide navbar
[self.navigationController setNavigationBarHidden:YES];
}
//Show navbar in detailView
-(void)viewWillDisappear:(BOOL)animated{
[self.navigationController setNavigationBarHidden:NO];
}
#end

Delegation in iOS

I have 2 ViewControllers, in 1st - TableView and in 2nd - button with label on it. When I click on the button in 2nd ViewController I need to go back on TableView and set in
cell.detailTextLabel.text
text from label on the button.
Here is my code, but it does not work:
ViewController.h:
#import <UIKit/UIKit.h>
#import "TestControl.h"
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, myTestProtocol>
{
TestControl *myProtocol;
}
#property (strong, nonatomic) IBOutlet UITableView * tableTest;
#end
ViewController.m:
#import "ViewController.h"
#import "TestControl.h"
#implementation ViewController
#synthesize tableTest;
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBarHidden = YES;
myProtocol = [[TestControl alloc]init];
myProtocol.delegate = self;
// Do any additional setup after loading the view, typically from a nib.
}
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
TestControl * test = [[TestControl alloc] initWithNibName:#"TestControl" bundle:nil];
[self.navigationController pushViewController:test animated:YES];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
switch (indexPath.row) {
case 0:
cell.textLabel.text = #"Firs Cell";
cell.detailTextLabel.text = myProtocol.myLabel.text;
break;
case 1:
cell.textLabel.text = #"Second Cell";
break;
case 2:
cell.textLabel.text = #"Third Cell";
break;
default:
break;
}
return cell;
}
#end
TestControl.h:
#import <UIKit/UIKit.h>
#protocol myTestProtocol <NSObject>
#end
#interface TestControl : UIViewController
{
UILabel *myLabel;
}
#property (nonatomic, assign) id <myTestProtocol> delegate;
#property (strong, nonatomic) IBOutlet UILabel *myLabel;
- (IBAction)testButton:(id)sender;
#end
TestControl.m:
#implementation TestControl
#synthesize myLabel;
#synthesize delegate;
- (IBAction)testButton:(id)sender
{
myLabel.text = #"TEXT LABEL";
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:0] animated:YES];
}
What is the problem in this???
A couple of things....
You are creating two different TestControl objects, setting the delegate for one of them and pushing the other one, so the one handling the button tap has no delegate.
The delegate logic would work better the other way around. That is, TestControl should have the code that communicates with its delegate rather than the delegate "pulling" from TestControl.

Access UITableView cell and swipe between them from DetailView using XCode 4

I'm making my first app and I’m using XCode 4 with a Storyboard. Thanks to this place, lots of tutorials, Apple’s archives databases and a bit of me, I’m slowly getting the basics together. It’s an app populated from a plist. The plist is an array with dictionaries, the dictionarires containing stings with info about different red wines in Norway. First, the plist populates a TableView. I’m using NSSortDescritor to sort the TableView and added a button to the navigation bar for resorting if I want it displayed by another value. It looks like this:
RootTableViewController.h:
#import <UIKit/UIKit.h>
#interface RootTableViewController : UITableViewController <UIActionSheetDelegate> {
NSMutableArray *sortedObjects;
}
-(IBAction)sortButtonPressed:(id)sender;
#end
RootTableViewController.m:
#import "RootTableViewController.h"
#import "ObjectCell.h"
#import "DetailViewController.h"
#interface RootTableViewController ()
#end
#implementation RootTableViewController
- (IBAction)sortButtonPressed:(id)sender;
{
UIActionSheet *sort = [[UIActionSheet alloc]
//InitWithStyle etc for sheet
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSSortDescriptor *sortDesc;
if (buttonIndex == 0) {
sortDesc = [[NSSortDescriptor alloc] initWithKey:#"Name" ascending:YES];
[sortedWines sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];
}
if (buttonIndex == 1) {
sortDesc = [[NSSortDescriptor alloc] initWithKey:#"Country" ascending:YES];
[sortedWines sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];
}
[self.tableView reloadData];
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *myfile = [[NSBundle mainBundle]
pathForResource:#"Objects" ofType:#"plist"];
sortedObjects = [[NSMutableArray alloc]initWithContentsOfFile:myfile];
NSSortDescriptor * sortDesc = [[NSSortDescriptor alloc] initWithKey:#"Popularity" ascending:YES];
[sortedObjects sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (void)viewWillAppear:(BOOL)animated {
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [sortedObjects count];
}
//(I’m using a Custom Cell for the TableView)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"objectCell";
ObjectCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[ObjectCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.nameLabel.text = [[sortedObjects objectAtIndex:indexPath.row] valueForKey:#"Name"];
cell.countryLabel.text = [[sortedObjects objectAtIndex:indexPath.row] valueForKey:#"Country"];
return cell;
}
#pragma mark - Table view delegate
//Then the selected object is sent to the DetailViewController in this segue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"DetailSegue"]) {
NSIndexPath *selectedRowIndex = [self.tableView indexPathForSelectedRow];
DetailViewController *detailViewController = [segue destinationViewController];
detailViewController.selectedObject = [sortedObjects objectAtIndex:selectedRowIndex.row];
}
}
#end
Then the DetailViewController recieves the selected object to populate the Labels and ImageViews with the data from it.
DetailViewController.h:
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController
#property (nonatomic, strong) IBOutlet UILabel *districtLabel;
#property (nonatomic, strong) IBOutlet UILabel *countryLabel;
#property (nonatomic, strong) IBOutlet UIImageView *bottleImageView;
#property (nonatomic, strong) NSString *selectedObject;
#end
DetailViewController.m:
#import "WinesDetailViewController.h"
#interface WinesDetailViewController ()
#end
#implementation WinesDetailViewController
#synthesize districtLabel,countryLabel,bottleImageView;
#synthesize selectedObject;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidAppear:(BOOL)animated
{
self.title = [selectedObject valueForKey:#"Name"];
[super viewDidAppear:animated];
}
- (void)viewDidLoad
{
[super viewDidLoad];
districtLabel.text = [selectedObject valueForKey:#"District"];
countryLabel.text = [selectedObject valueForKey:#"Country"];
bottleImageView.image = [UIImage imageNamed:[selectedObject valueForKey:#"Image"]];
self.navigationController.navigationBar.translucent = YES;
self.wantsFullScreenLayout = YES;
//Then I’ve added recognizers for left and right swiping:
UISwipeGestureRecognizer *leftGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeDetectedLeft:)];
leftGesture.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:leftGesture];
UISwipeGestureRecognizer *rightGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeDetectedRight:)];
rightGesture.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:rightGesture];
}
//And the voids to handle the swipes:
- (void)swipeDetectedRight:(UISwipeGestureRecognizer *)sender
{
//Access previous cell in TableView
}
- (void)swipeDetectedLeft:(UISwipeGestureRecognizer *)sender
{
//Access next cell in TableView
}
//Some more besic code for the view..
#end
As you can see, I’ve added UISwipeGestureRecognizers in the DetailViewController, because I want to reload it with data from the previous cell to when swiped to the right, and next cell when swiped to the left. Now I have no idea how to handle the voids for swipe detected, how can I reach selectedRowIndex from DetailView and swipe through cells? I’m new to programming, have been trying to figure this out for a long time now, so code examples would be great so the answer don't lead to 100 new questions if you know what I mean. Thank you so much if you can help me.
One way to go about this is to pass the "sorted" datasource array to the DetailViewController and the indexpath through the "prepareForSegue" method.
RootTableViewController.h:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"DetailSegue"]) {
NSIndexPath *selectedRowIndex = [self.tableView indexPathForSelectedRow];
DetailViewController *detailViewController = [segue destinationViewController];
detailViewController.selectedObject = [sortedObjects objectAtIndex:selectedRowIndex.row];
//added code
detailViewController.detailsDataSource = [[NSArray alloc]initWithArray:sortedObjects];
detailViewController.detailIndex = selectedRowIndex.row;
}
}
Then you could reload the UI elements of the DetailViewController.
Here is the declaration of the new properties.
DetailViewController.h:
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController
#property (nonatomic, strong) IBOutlet UILabel *districtLabel;
#property (nonatomic, strong) IBOutlet UILabel *countryLabel;
#property (nonatomic, strong) IBOutlet UIImageView *bottleImageView;
#property (nonatomic, strong) NSString *selectedObject;
// added code
#property (strong, nonatomic) NSArray *detailsDataSource;
#property int detailIndex;
#end
Don't forget to synthesize the new properties
#synthesize detailsDataSource,detailIndex;
//And the voids to handle the swipes:
- (void)swipeDetectedRight:(UISwipeGestureRecognizer *)sender
{
//Access previous cell in TableView
if (detailIndex != 0) // This way it will not go negative
detailIndex--;
districtLabel.text = [[detailsDataSource objectAtIndex: detailIndex] valueForKey:#"District"]];
countryLabel.text = [[detailsDataSource objectAtIndex: detailIndex] valueForKey:#"Country"];
bottleImageView.image = [UIImage imageNamed:[[detailsDataSource objectAtIndex: detailIndex] valueForKey:#"Image"]];
}
- (void)swipeDetectedLeft:(UISwipeGestureRecognizer *)sender
{
//Access next cell in TableView
if (detailIndex != [detailsDataSource count]) // make sure that it does not go over the number of objects in the array.
detailIndex++; // you'll need to check bounds
districtLabel.text = [[detailsDataSource objectAtIndex: detailIndex] valueForKey:#"District"]];
countryLabel.text = [[detailsDataSource objectAtIndex: detailIndex] valueForKey:#"Country"];
bottleImageView.image = [UIImage imageNamed:[[detailsDataSource objectAtIndex: detailIndex] valueForKey:#"Image"]];
}
//Some more besic code for the view..
#end
Give this a try it might work for you. Otherwise, I think you might want to take a look at Scrollview and "paging." iPhone/iPad users are used to this UI design, and you might be able to modify it to fit what you are doing.

How to access a mutable array that is a property of an instance of an Object and fill that array up with values

I have a Card Object, which have 4 instance variables namely name(NSString), pin(NSString), points(NSNumber), pointsToDeduct(NSMutableArray).
Card.h
#interface Card : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *pin;
#property (nonatomic, strong) NSNumber *points;
#property (nonatomic, strong) NSMutableArray *pointsToDeduct;
#end
This pointsToDeduct array is always present for every new instance of Card I make. What I want is to fill it's values with another array's values which are static through a button click. But before that, in my code below, I cast those static values into an NSNumber so that the pointsToDeduct's values will be of type NSNumber. I'm thinking of delegation to do this though not sure if it's best. For now I want to access that pointsToDeduct array so I can add values in it.
*this is part of PerksDetailsViewController.m
- (IBAction)redeemPressed:(id)sender {
NSNumber *pointsRequired;
NSNumberFormatter * formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
pointsRequired = [formatter numberFromString: (self.pointsLabel.text)];
NSLog(#"points required by the perk %#", pointsRequired);
// now insert pointsRequired's value to pointsToDeduct array instance variable of a Card
Below are the other codes that I have.
Main View
CardWalletViewController.h
#import <UIKit/UIKit.h>
#interface CardWalletViewController : UITableViewController
#property (nonatomic, strong) NSMutableArray *myWallet;
-(void) printArrayContents;
CardWalletViewController.m
#import "CardWalletViewController.h"
#import "AddCardViewController.h"
#import "Card.h"
#import "CardDetailsViewController.h"
#interface CardWalletViewController () <AddCardDelegate>
#end
#implementation CardWalletViewController
#synthesize myWallet = _myWallet;
- (NSMutableArray *) myWallet
{
if (_myWallet == nil) _myWallet = [[NSMutableArray alloc] init];
return _myWallet;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showAddCardVC"]) {
AddCardViewController *addCardVC = (AddCardViewController *)segue.destinationViewController;
addCardVC.delegate = self;
}
}
- (void)printArrayContents
{
// I want to show the name of each instance
for ( int i = 0; i < self.myWallet.count; i++) {
Card *cardDummy = [self.myWallet objectAtIndex:i];
NSLog(#"Element %i is %#", i,cardDummy.name );
}
}
- (void)addCardViewController:(AddCardViewController *)sender didCreateCard:(Card *)newCard
{
// insert a new card to the array
[self.myWallet addObject:newCard];
[self printArrayContents];
[self.tableView reloadData];
}
- (void)saveMyWallet: (NSMutableArray *)myWallet
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:self.myWallet forKey:#"myWalletArray"];
[defaults synchronize];
NSLog(#"I am saved");
}
- (NSMutableArray *)loadWallet
{
NSMutableArray *boom;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
boom = [defaults objectForKey: #"myWalletArray"];
if (!boom) {
boom = [[NSMutableArray alloc] init];
}
return boom;
}
- (void)viewDidLoad
{
[self loadWallet];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//this method will return the number of rows to be shown
return self.myWallet.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
Card *cardDummy = [self.myWallet objectAtIndex:indexPath.row];
cell.textLabel.text = cardDummy.name;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", cardDummy.points];
return cell;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//this method is responsible for showing the details of a selected card
//make another view controller - DetailVC perhaps
CardDetailsViewController *details = [self.storyboard instantiateViewControllerWithIdentifier:#"cardDetails"];
Card *cardDummy = [self.myWallet objectAtIndex:indexPath.row];
details.myPoints = [NSString stringWithFormat:#"%#", cardDummy.points];
[self.navigationController pushViewController:details animated:YES];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
The way I create a new Card
AddCardViewController.m
#import "AddCardViewController.h"
#import "Card.h"
#import "CardWalletViewController.h"
#interface AddCardViewController ()
#end
#implementation AddCardViewController
#synthesize cardNameTextField = _cardNameTextField;
#synthesize pinTextField = _pinTextField;
#synthesize pointsTextField = _pointsTextField;
#synthesize delegate = _delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.cardNameTextField becomeFirstResponder];
}
- (BOOL) textFieldShouldReturn:(UITextField *)textField{
if ([textField.text length]) {
[self.cardNameTextField resignFirstResponder];
[self.pinTextField resignFirstResponder];
[self.pointsTextField resignFirstResponder];
return YES;
}
else {
return NO;
}
}
- (void)viewDidLoad
{
self.cardNameTextField.delegate = self;
self.pinTextField.delegate = self;
self.pointsTextField.delegate = self;
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setCardNameTextField:nil];
[self setPinTextField:nil];
[self setPointsTextField:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (IBAction)addCard:(id)sender
{
Card *myNewCard = [[Card alloc] init];
myNewCard.name = self.cardNameTextField.text;
myNewCard.pin = self.pinTextField.text;
NSNumber *myPoints;
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
myPoints = [f numberFromString: (self.pointsTextField.text)];
myNewCard.points = myPoints;
//method here that will dismiss the modal view
// if condition forces the user to fill up all the text field
if ([self.cardNameTextField.text length] && [self.pinTextField.text length] && [self.pointsTextField.text length])
{
//method here that will dismiss the modal view
[[self presentingViewController] dismissModalViewControllerAnimated:YES];
//checking...
NSLog(#"name saved %#", myNewCard.name);
NSLog(#"pin saved %#", myNewCard.pin);
NSLog(#"points saved %#", myNewCard.points);
[self.delegate addCardViewController:self didCreateCard:myNewCard];
// to check if there is a delegate
/*
if (self.delegate){
NSLog(#"delegate is not nil");
}
*/
}
}
#end
AddCardViewController.h
#import <UIKit/UIKit.h>
#import "Card.h"
#class AddCardViewController;
#protocol AddCardDelegate <NSObject>
- (void)addCardViewController:(AddCardViewController *)sender
didCreateCard:(Card *) newCard;
#end
#interface AddCardViewController : UIViewController <UITextFieldDelegate>
#property (strong, nonatomic) IBOutlet UITextField *cardNameTextField;
#property (strong, nonatomic) IBOutlet UITextField *pinTextField;
#property (strong, nonatomic) IBOutlet UITextField *pointsTextField;
#property (nonatomic, strong) id <AddCardDelegate> delegate;
#end
CardDetailsViewController.m
#import "CardDetailsViewController.h"
#import "PerksDetailsViewController.h"
#import "Card.h"
#interface CardDetailsViewController ()
#end
#implementation CardDetailsViewController
#synthesize pointsLabel = _pointsLabel;
#synthesize myPoints = _myPoints;
#synthesize perks = _perks;
#synthesize datasource = _datasource;
#synthesize datasourcePoints = _datasourcePoints;
-(void)setupArray
{
self.perks = [[NSMutableDictionary alloc] init];
[self.perks setObject:#"200" forKey:#"10% Discount"];
[self.perks setObject:#"100" forKey:#"250Php Off"];
self.datasource = [self.perks allKeys]; //contains perk's description
self.datasourcePoints = [self.perks allValues]; //contains perk's required points
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 2;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [self.datasource objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [self.datasourcePoints objectAtIndex:indexPath.row];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
PerksDetailsViewController *perksDetails = [self.storyboard instantiateViewControllerWithIdentifier:#"detailsOfMyPerks"];
[self.navigationController pushViewController:perksDetails animated:YES];
perksDetails.perkDetailsLabel.text = [self.datasource objectAtIndex:indexPath.row];
perksDetails.pointsLabel.text = [self.perks objectForKey:perksDetails.perkDetailsLabel.text];
}
- (void)viewDidLoad
{
//show the number of points of the selected Card
self.pointsLabel.text = self.myPoints;
self.navigationItem.title = #"Your Points";
[self setupArray];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setPointsLabel:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
#end
CardDetailsViewController.h
#import <UIKit/UIKit.h>
#interface CardDetailsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
}
#property (nonatomic, retain) NSMutableDictionary *perks;
#property (nonatomic, retain) NSArray *datasource;
#property (nonatomic, retain) NSArray *datasourcePoints;
-(void)setupArray;
#property (strong, nonatomic) IBOutlet UILabel *pointsLabel;
#property (nonatomic, weak) NSString *myPoints;
#end
PerksDetailsViewController.m
#import "PerksDetailsViewController.h"
#import "Card.h"
#import "CardWalletViewController.h"
#interface PerksDetailsViewController ()
#end
#implementation PerksDetailsViewController
#synthesize pointsLabel = _pointsLabel;
#synthesize perkDetailsLabel = _perkDetailsLabel;
#synthesize perkDetailText = _perkDetailText;
#synthesize pointsText = _pointsText;
- (IBAction)redeemPressed:(id)sender {
// get required points of a perk selected
// cast the NSString value to an int/NSInteger
NSNumber *pointsRequired;
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
pointsRequired = [f numberFromString: (self.pointsLabel.text)];
NSLog(#"points required by the perk %#", pointsRequired);
// now insert this value to points array instance variable of a Card
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
//self.perkDetailsLabel.text = self.perkDetailText;
//self.pointsLabel.text = self.pointsText;
NSLog(#"perk detail:%#", self.perkDetailText);
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setPerkDetailsLabel:nil];
[self setPointsLabel:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
PerksDetailsViewController.h
#import <UIKit/UIKit.h>
#interface PerksDetailsViewController : UIViewController
{
NSString *perkDetailText;
NSString *pointsText;
IBOutlet UILabel *perkDetailsLabel;
IBOutlet UILabel *pointsLabel;
}
#property (nonatomic, retain) IBOutlet UILabel *perkDetailsLabel, *pointsLabel;
#property (nonatomic, retain) NSString *perkDetailText, *pointsText;
#end
Your PerksDetailViewController needs to have a property of the current Card object. Then, it's simply a matter of
[self.card.pointsToDeduct addObject:pointsRequired];
I can't see in all your sample code where you are actually using any Card objects.
in current class
NSMutable Array from One Class to Another Class in iPhone
#import "SecondViewController"
SecondViewController *NextViewController = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
NextViewController.nextClasssArray = thisClassarray;
in second class .h
#property(nonatomic,retain) NSMutableArray *nextClasssArray;
in second class .m
#synthesize nextClasssArray;