EXC_BAD_ACCESS(Code=1…. when using NSObject as a delegate - iphone

I have this code in the .h file :
#import <UIKit/UIKit.h>
#interface NFModalPickerView : NSObject
#end
#protocol NFModalPickerViewDelegate<NSObject>
#optional
- (void)titleSelected:(NFModalPickerView *) modalPickerView title:(NSString *) title;
#required
- (void)done:(NFModalPickerView *) modalPickerView;
#end
#interface NFModalPickerView()
{
id <NFModalPickerViewDelegate> delegate;
}
#property (nonatomic, strong) NSMutableArray * objectArray;
#property (nonatomic, strong) id <NFModalPickerViewDelegate> delegate;
- (void) show;
#end
and this code in the .m file :
#import "NFModalPickerView.h"
#interface NFModalPickerView()<UIPickerViewDelegate,UIPickerViewDataSource>
#end
#implementation NFModalPickerView
#synthesize objectArray;
#synthesize delegate;
UIActionSheet *actionSheet;
UIPickerView *pickerView ;
UISegmentedControl *closeButton;
- (void) show{
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil
delegate:nil
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
[actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect pickerFrame = CGRectMake(0, 40, 0, 0);
pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
pickerView.showsSelectionIndicator = YES;
pickerView.dataSource = self;
pickerView.delegate = self;
[actionSheet addSubview:pickerView];
pickerView = nil;
closeButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:#"Done"]];
closeButton.momentary = YES;
closeButton.frame = CGRectMake(260, 7.0f, 50.0f, 30.0f);
closeButton.segmentedControlStyle = UISegmentedControlStyleBar;
closeButton.tintColor = [UIColor blackColor];
[closeButton addTarget:self action:#selector(dismissActionSheet:) forControlEvents:UIControlEventValueChanged];
[actionSheet addSubview:closeButton];
closeButton = nil;
[actionSheet showInView:[[UIApplication sharedApplication] keyWindow]];
[actionSheet setBounds:CGRectMake(0, 0, 320, 485)];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return [objectArray count];
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
return [objectArray objectAtIndex:row];
}
-(void) dismissActionSheet:(id)sender {
UIActionSheet *actionSheet = (UIActionSheet *)[(UIView *)sender superview];
[actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
[[self delegate] titleSelected:self title:[objectArray objectAtIndex:row]];
}
#end
and finally this code in my ViewController
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
pickerView = [[NFModalPickerView alloc] init];
pickerView.objectArray = [[NSMutableArray alloc] init];
[pickerView.objectArray addObject:#"Don personnel"];
[pickerView.objectArray addObject:#"Don d'entreprise"];
[pickerView setDelegate:self];
[pickerView show];
return NO;
}
I'm always getting a bad access error when using NFModalPickerView as the delegate of the pickerview. If i put all the code in the view controller using the view controller as the delegate of the picker view it works fine. I need to have a separate class to reuse the modalpickerview and not always put all the code in each of my view controllers. Anyone can help me with this?

If you are using ARC, UIPickerView 's delegate might be auto-released. Either use the UIViewController as the dataSource and the delegate for the UIPickerView, or if you are using a separate object to manage the UIPickerView, keep it as a property so that it is not released.

Related

Making UIPicker pop up when textfield is tapped

I made a application with the templet of a Single View Application. Then I added a label and connected it to the .h file of my ViewController. Then I made a picker, filled it, then set it (and a toolBar I made) to the textfield. But when I tap the textfield, the picker is just all black. If this made no sense, the code will explain it all.
.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
}
#property (weak, nonatomic) IBOutlet UITextField *habitField;
#property (weak, nonatomic) NSArray *PickerData;
#end
.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSArray *array = [[NSArray alloc] initWithObjects:#"1",#"2",#"3", nil];
self.PickerData = array;
UIToolbar *toolBar = [[UIToolbar alloc] init];
toolBar.barStyle = UIBarStyleBlackOpaque;
[toolBar sizeToFit];
[toolBar setBackgroundImage:[UIImage imageNamed:#"red_navigation_bar.png"] forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:self
action:nil];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:#selector(releasePicker)];
UIPickerView *Picker = [[UIPickerView alloc] init];
doneButton.image = [UIImage imageNamed:#"button.png"];
[toolBar setItems:#[flexSpace, doneButton] animated:YES];
self.habitField.inputAccessoryView = toolBar;
[self.habitField setInputView:Picker];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return [self.PickerData count];
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [self.PickerData objectAtIndex:row];
}
#end
The simulator looks like this
As i see you forgot to set delegate for picker ( UIPickerViewDelegate )
Picker.delegate = self;
Remember to add :)
#interface ViewController : UIViewController<UIPickerViewDelegate> {
}
Cheers

Odd behavior UIActionSheet + UITableView: rows disappear

I've a UITableView with some static cells in it. One of them shows a UIActionSheet when touched. Here goes the code for it:
viewDidLoad: initialize controls.
- (void)viewDidLoad
{
[super viewDidLoad];
[self initializeControls];
}
initializeControls: add gesture recognizer to the label within the cell in order to show the UIActionSheet.
- (void)initializeControls {
[...]
// Places Label
self.placeNamesLabel.userInteractionEnabled = YES;
tapGesture = \
[[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(didPlaceNamesLabelWithGesture:)];
[self.placeNamesLabel addGestureRecognizer:tapGesture];
tapGesture = nil;
[...]
}
didPlaceNamesLabelWithGesture: initialize UIActionSheet, add a UITableView from StoryBoard and a Close button.
- (void)didPlaceNamesLabelWithGesture:(UITapGestureRecognizer *)tapGesture
{
// Show UITableView in UIActionView for selecting Place objects.
placesActionSheet = [[UIActionSheet alloc] initWithTitle:nil
delegate:nil
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
[placesActionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect tableFrame = CGRectMake(0, 40, 0, 0);
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
AddArticlesPlacesViewController *placesView = [storyBoard instantiateViewControllerWithIdentifier:#"PlacesForArticle"];
placesView.managedObjectContext = self.managedObjectContext;
placesView.view.frame = tableFrame;
[placesActionSheet addSubview:placesView.view];
placesView = nil;
UISegmentedControl *closeButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:#"Close"]];
closeButton.momentary = YES;
closeButton.frame = CGRectMake(260, 7.0f, 50.0f, 30.0f);
closeButton.segmentedControlStyle = UISegmentedControlStyleBar;
closeButton.tintColor = [UIColor blackColor];
[closeButton addTarget:self action:#selector(dismissPlacesActionSheet:) forControlEvents:UIControlEventValueChanged];
[placesActionSheet addSubview:closeButton];
closeButton = nil;
[placesActionSheet showInView:[[UIApplication sharedApplication] keyWindow]];
[placesActionSheet setBounds:CGRectMake(0, 0, 320, 485)];
}
dismissPlacesActionSheet: close UIActionSheet.
-(void)dismissPlacesActionSheet:(id)sender {
[placesActionSheet dismissWithClickedButtonIndex:0 animated:YES]; }
Everything works and the UITableView populates fine from Core Data. So where is the problem? The point is that when any row is tapped, the entire table gets empty (I can't post images yet, sorry).
I've tried to add a new custom row with a button that fires a push segue to the AddArticlesPlacesViewController; this works fine and the behavior is as expected. So the problem is between UIActionSheet and UITableView.
Here are the interfaces for both view controllers:
Main.
#interface AddArticleViewController : UITableViewController <NSFetchedResultsControllerDelegate, [...]>
[...]
#property (weak, nonatomic) IBOutlet UILabel *placeNamesLabel;
#property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
[...]
#end
Secondary.
#interface AddArticlesPlacesViewController : UITableViewController <NSFetchedResultsControllerDelegate>
#property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;
#property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#end
I'm stuck. What am I doing wrong?
Regards.
Pedro Ventura.
you can use tableview's delegate method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
NSLog(#"indexpath-->%d",indexPath.row);
if (indexPath.row==0 || indexPath.row == 2 )
{
NSLog(#"row %d",indexPath.row);
}
if (indexPath.row==1)
{
actionsheet=[[UIActionSheet alloc]initWithTitle:#"Sample" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:nil, nil];
[actionsheet showInView:self.view];
}
}
And you can use UIActionsheetDelegate's method for Selected Button:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSLog(#"index==>%d",buttonIndex);
NSLog(#"cancel");
}

How to display images when selecting data from a UIPickerview in Apple's iPhone SDK

I have a multicomponent picker with two separate wheels showing relative information. I want to display an image depending on which component is selected. For example: if "AA" is selected from both wheels, image AA will be displayed. If the right wheel is changed to "B", image AB will be displayed.
Thanks for your help in advance.
Regards,
You can do something like this:
#import <UIKit/UIKit.h>
#interface PickerController: UIViewController <UIPickerViewDelegate, UIPickerViewDataSource> {
NSArray *titleStrings;
UIPickerView *picker;
UIImage *imageView;
}
#end
#implementation PickerController
- (id) init {
if (self = [super init]) {
titleStrings = [[NSArray alloc] initWithObjects:#"A", #"B", NULL];
picker = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 100, 320, 100)];
picker.showsSelectionIndicator = YES;
picker.delegate = self;
picker.dataSource = self;
[self.view addSubview:picker];
imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"empty.png"]];
imageView.frame = CGRectMake(0, 200, imageView.frame.size.width, imageView.frame.size.height);
[self.view addSubview:imageView];
[imageView release];
[picker release];
}
return self;
}
- (void) dealloc {
[titleStrings release];
[super dealloc];
}
/* UIPickerViewDataSource */
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 2;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return 2;
}
/* UIPickerViewDelegate */
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [titleStrings objectAtIndex:row];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSString *first = [titleStrings objectAtIndex:[pickerView selectedRowInComponent:0]];
NSString *second = [titleStrings objectAtIndex:[pickerView selectedRowInComponent:1]];
NSString *imageName = [[NSString alloc] initWithFormat:#"%#%#", first, second];
imageView.image = [UIImage imageNamed:imageName];
[imageName release];
[imageView sizeToFit];
}
#end

Edit 2 uitextfield by turn with a select in uipickerview

I have 2 instances of UITextField and 1 instance of UIPickerView. UIPickerView is able to update data into
UITextField in didSelectRow:(NSInteger)row inComponent:(NSInteger)component. But how do I update 2 UITextField from UIPickerView when the user touch the UITextView?
Thanks. :)
you will need to make the UIPickerView the inputView of the textfields, i have made an example.
.h file:
#interface aViewController : UIViewController <UIPickerViewDelegate,UIPickerViewDataSource> {
UITextField * textField0;
UITextField * textField1;
UIPickerView * pickerView;
UIToolbar * toolBar;
NSArray * items0;
NSArray * items1;
}
-(void)cancel;
-(void)close;
#end
.m need something like the following:
- (void)viewDidLoad
{
[super viewDidLoad];
textField0 = [[UITextField alloc] initWithFrame:CGRectMake(10.f, 20.0f, 100.f, 30.f)];
textField1 = [[UITextField alloc] initWithFrame:CGRectMake(130.f, 20.0f, 100.f, 30.f)];
textField0.backgroundColor = [UIColor grayColor];
textField1.backgroundColor = [UIColor grayColor];
pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 0, 320.f, 200.f)];
// Do any additional setup after loading the view from its nib.
[self.view addSubview:textField0];
[self.view addSubview:textField1];
toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320.f, 44.f)];
UIBarButtonItem * cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancel)];
UIBarButtonItem * doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(close)];
toolBar.items = [NSArray arrayWithObjects:doneButton,cancelButton, nil];
items0 = [[NSArray alloc] initWithObjects:#"dogs",#"cats",#"llamas",#"emus", nil];
items1 = [[NSArray alloc] initWithObjects:#"bone",#"catnip",#"hay", nil];
[doneButton release];
[cancelButton release];
pickerView.showsSelectionIndicator = YES;
pickerView.delegate = self;
pickerView.dataSource = self;
textField1.inputView = pickerView;
textField0.inputView = pickerView;
textField1.inputAccessoryView = toolBar;
textField0.inputAccessoryView = toolBar;
}
#pragma mark - actions
-(void)cancel
{
//reset the values to the original values on cancel...
//do that here.
[textField0 resignFirstResponder];
[textField1 resignFirstResponder];
}
-(void)close
{
textField0.text = [items0 objectAtIndex:[pickerView selectedRowInComponent:0]] ;
textField1.text = [items1 objectAtIndex:[pickerView selectedRowInComponent:1]] ;
[textField0 resignFirstResponder];
[textField1 resignFirstResponder];
}
#pragma mark - pickerview handling
-(float)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component{
return 130.f;
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
if (component==0) {
return [items0 objectAtIndex:row];
}
return [items1 objectAtIndex:row];
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if (component==0) {
textField0.text = [items0 objectAtIndex:row];
return;
}
textField1.text = [items1 objectAtIndex:row];
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if (component ==0) {
return [items0 count];
}
return [items1 count];
}
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 2;
}
I haven't included any clean-up code.

problem in changing size of uialertview

Hello
I am having a alertview and i want to change the size by cgrectmake property but it does not happen .
It just take the by default size.
i tried following code.
- (void)viewDidLoad {
[super viewDidLoad];
UIAlertView* find = [[[UIAlertView alloc] init]initWithFrame:CGRectMake(0,0,300,200)];
[find setDelegate:self];
[find setTitle:#"Sample Alert"];
[find setNeedsLayout];
[find show];
[find release];
}
Thanks in advance .
To achieve what you want, in your code, after:
[find show];
add:
find.frame = CGRectMake(0,0,300,200);
It's not pretty though, I suggest you use ActionSheets.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Confirmation" message:#" Submit the answer " delegate:self cancelButtonTitle:#"NO" otherButtonTitles:#"YES", nil];
[alert show];
[alert release];
UILabel *theTitle = [alert valueForKey:#"_titleLabel"];
[theTitle setTextColor:[UIColor blackColor]];
UILabel *theBody = [alert valueForKey:#"_bodyTextLabel"];
[theBody setTextColor:[UIColor blackColor]];
UIImage *theImage = [UIImage imageNamed:#"blue-white-abstract-background.jpg"];
theImage = [theImage stretchableImageWithLeftCapWidth:10 topCapHeight:10];
CGSize theSize = [alert frame].size;
UIGraphicsBeginImageContext(theSize);
[theImage drawInRect:CGRectMake(0, 0, theSize.width, theSize.height)];
theImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//[[alert layer] setContents:[theImage CGImage]];
[[alert layer] setContents:[UIColor clearColor]];
This code does a lot of things to alertview and modify it to increase the size of the alert view.
This does the job pretty well, and does not look weird when the alert appear (ahmet emrah solution has a pretty bad side effect).
CGAffineTransform myTransform = CGAffineTransformMakeScale(1.0, 0.5f);
[alert setTransform:myTransform];
You can subclass the UIAlertView. I have done something like this, change it for your need.
Header file,
#import <Foundation/Foundation.h>
/* An alert view with a textfield to input text. */
#interface AlertPrompt : UIAlertView
{
UITextField *textField;
}
#property (nonatomic, retain) UITextField *textField;
#property (readonly) NSString *enteredText;
- (id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle okButtonTitle:(NSString *)okButtonTitle;
#end
Source code,
#import "AlertPrompt.h"
#implementation AlertPrompt
static const float kTextFieldHeight = 25.0;
static const float kTextFieldWidth = 100.0;
#synthesize textField;
#synthesize enteredText;
- (void) drawRect:(CGRect)rect {
[super drawRect:rect];
CGRect labelFrame;
NSArray *views = [self subviews];
for (UIView *view in views){
if ([view isKindOfClass:[UILabel class]]) {
labelFrame = view.frame;
} else {
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y + kTextFieldHeight , view.frame.size.width, view.frame.size.height);
}
}
CGRect myFrame = self.frame;
self.textField.frame = CGRectMake(95, labelFrame.origin.y+labelFrame.size.height + 5.0, kTextFieldWidth, kTextFieldHeight);
self.frame = CGRectMake(myFrame.origin.x, myFrame.origin.y, myFrame.size.width, myFrame.size.height + kTextFieldHeight);
}
- (id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle okButtonTitle:(NSString *)okayButtonTitle
{
if (self = [super initWithTitle:title message:message delegate:delegate cancelButtonTitle:cancelButtonTitle otherButtonTitles:okayButtonTitle, nil])
{
// add the text field here, so that customizable from outside. But set the frame in drawRect.
self.textField = [[UITextField alloc] init];
[self.textField setBackgroundColor:[UIColor whiteColor]];
[self addSubview: self.textField];
// CGAffineTransform translate = CGAffineTransformMakeTranslation(0.0, 20.0);
// [self setTransform:translate];
}
return self;
}
- (void)show
{
[textField becomeFirstResponder];
[super show];
}
- (NSString *)enteredText
{
return textField.text;
}
- (void)dealloc
{
[textField release];
[super dealloc];
}
#end