I'm new to xCode and objective-c, and trying to use different classes to familiarize myself with the language.
I was trying to use an NSMutableArray to show several pictures and a corresponding textsnippet to tell about the picture. I have a segmentedControl to switch between several choices. Using an UIImageView to show a picture, and a UITextView the corresponding text.
But for some reason they will not load properly? The picture and the text isn't shown. What am I doing wrong?
#interface TestingViewController : UIViewController{
UIImageView *pic;
UITextView *description;
UISegmentedControl *choice;
NSMutableArray *infoDescription;
}
#property (nonatomic, retain) IBOutlet UIImageView *pic;
#property (nonatomic, retain) IBOutlet UITextView *description;
#property (nonatomic, retain) NSMutableArray *infoDescription;
#property (nonatomic, retain) IBOutlet UISegmentedControl *choice;
- (IBAction) segmentedControllIndexChanged;
#end
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
infoDescription = [[NSMutableArray alloc] init];
}
UIImage *miko = [UIImage imageNamed:#"miko.jpg"];
NSString *mikoString = #"Info about Miko";
UIImage *alex = [UIImage imageNamed:#"alex.jpg"];
NSString *alexString = #"Info about Alex";
[infoDescription addObject:miko];
[infoDescription addObject:mikoString];
[infoDescription addObject:alex];
[infoDescription addObject:alexString];
- (IBAction)segmentedControllIndexChanged{
switch (choice.selectedSegmentIndex) {
case 0:
[pic setImage: miko];
[pic setImage: [infoDescription objectAtIndex:0]];
[description setText: [[infoDescription objectAtIndex:1] stringValue]];
break;
case 1:
[pic setImage: [infoDescription objectAtIndex:2]];
[description setText: [[infoDescription objectAtIndex:3] stringValue]];
break;
default:
break;
}
}
Thanks for any help out there.
NSMutableArray should not be an IBOutlet ..
Change this
#property (nonatomic, retain) IBOutlet NSMutableArray *infoDescription;
to
#property (nonatomic, retain) NSMutableArray *infoDescription;
and make sure you synthesize it..
and also the program isn't working since your array is not initialized and is not adding objects to it.
put this in ViewDidLoad
infoDescription = [[NSMutableArray alloc] init];
Your infoDescription array is probably nil. Put this before you add items to it:
infoDescription = [[NSMutableArray alloc] init];
Also, infoDescription doesn't need to be declared as an IBOutlet. IBOutlets are only for properties that you bind in Interface Builder (usually views).
Related
I am trying to pass data from a table view controller to a detail view controller. Every entry of my table works just as it should, except for one.
Here is the prepareForSegue method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"showDetails"]) {
NSIndexPath *indexPath = [[self tableView] indexPathForSelectedRow];
NSDictionary *notification = [[self notifications] objectAtIndex:[indexPath row]];
NRDetailViewController *destViewController = [segue destinationViewController];
[destViewController setDate:[notification objectForKey:#"date"]];
[destViewController setFrom:[notification objectForKey:#"from"]];
[destViewController setIden:[notification objectForKey:#"identifier"]];
[destViewController setPriority:[notification objectForKey:#"priority"]];
[destViewController setSubject:[notification objectForKey:#"subject"]];
[destViewController setMessage:[notification objectForKey:#"text"]];
}
}
Here is my interface for the detail view:
#import <UIKit/UIKit.h>
#interface NRDetailViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *dateField;
#property (weak, nonatomic) IBOutlet UITextField *fromField;
#property (weak, nonatomic) IBOutlet UITextField *idenField;
#property (weak, nonatomic) IBOutlet UITextField *prioField;
#property (weak, nonatomic) IBOutlet UITextField *subjectField;
#property (weak, nonatomic) IBOutlet UITextView *messageView;
#property (copy, nonatomic) NSString *date;
#property (copy, nonatomic) NSString *from;
#property (copy, nonatomic) NSString *iden;
#property (copy, nonatomic) NSString *priority;
#property (copy, nonatomic) NSString *subject;
#property (copy, nonatomic) NSString *message;
#end
Here is the detail view's implementation file:
#import "NRDetailViewController.h"
#interface NRDetailViewController ()
#end
#implementation NRDetailViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[self dateField] setText:[self date]];
[[self fromField] setText:[self from]];
[[self idenField] setText:[self iden]];
[[self prioField] setText:[self priority]];
[[self subjectField] setText:[self subject]];
[[self messageView] setText:[self message]];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I have problem setting the text of idenField to the text of iden. I have added an exception breakpoint, and got that the exception indeed occurs at this line:
[[self idenField] setText:[self iden]];
At this point, I have printed the value of [self iden] and it even contains the content I want to pass, so I have absolutely no idea what the problem is, since as I said, all the other fields are working as they should.
The exception being thrown is:
2013-08-07 22:28:20.539 NotificationReader[1214:11303] -[__NSCFNumber length]: unrecognized selector sent to instance 0x7587a00
Any help would be appreciated greatly.
It looks like:
[destViewController setIden:[notification objectForKey:#"identifier"]];
is returning an NSNumber and not an NSString. You could try replacing that line with:
[destViewController setIden:[(NSNumber*)[notification objectForKey:#"identifier"] stringValue]];
Somewhere you are passing an NSNumber instead of a NSString.
To set the text, iden needs to be a NSString. When you are getting the object from the NSDictionary, it is a NSNumber.
Try this:
[destViewController setIden:(NSString *)[notification objectForKey:#"identifier"]];
or change the iden property to be a NSNumber and then
[[self idenField] setText:[NSString stringWithFormat:#"%d", [self iden]]];
I am pushing a detail view from the master of a Master-Detail Application template.
I want to load a single view with different information depending on which row was clicked. I plan to load the data from a plist file.
Here is the code I used in the MasterViewController, when I added didSelectRowAtIndexPath:
DetailViewController *dvc = [[DetailViewController alloc]init];
dvc.rowItem = [_objects objectAtIndex:indexPath.row];;
NSLog(#"row is %i", indexPath.row);
NSLog(#"master %#", dvc.rowItem);
where rowItem is an NSString belonging to the DetailViewController. Inside the viewDidLoad of the DetailViewController I put:
[super viewDidLoad];
NSLog(#" thingy %#", rowItem);
[self setup:rowItem];
and setup looks like this:
-(void) setup: (NSString *)eval {
filePath = [NSString stringWithFormat:#"%#.plist",eval];
NSLog(#"%#", filePath);
NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
NSString *subName;
NSString *yesNo;
NSString *theseChanges;
subName = [plistDict objectForKey:#"subContractAddress"];
yesNo = [plistDict objectForKey:#"yesOrno"];
theseChanges = [plistDict objectForKey:#"Changes"];
}
Here is my interface:
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController
#property (strong, nonatomic) id detailItem;
#property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
#property (strong, nonatomic) IBOutlet UIButton *finishedButton;
#property (strong, nonatomic) IBOutlet UITextView *changes;
#property (strong, nonatomic) IBOutlet UIButton *saveButton;
#property (strong, nonatomic) IBOutlet UISwitch *test;
#property (strong, nonatomic) IBOutlet UILabel *finishedLabel;
#property (strong, nonatomic) IBOutlet UITextField *subContractName;
#property BOOL needsChanges;
#property (strong, nonatomic) NSString *rowItem;
-(IBAction)change:(id)sender;
-(IBAction)save:(id)sender;
#end
when I build and run I get the console output of:
thingy (null)
(null).plist
row is 0
master Excavations
when I press the first row, and
thingy (null)
(null).plist
row is 1
master Flooring
so somehow, rowItem is getting set to null in the crossover.
Can someone see what I am doing wrong here?
Try changing your two log statements as follows:
NSLog(#"master %#, detail %#", dvc.rowItem, dvc);
NSLog(#" thingy %# in detail %#", rowItem, self);
I suspect that the detail you create as dvc is not the same object that is in the view controller hierarchy. Showing the object addresses should verify whether that's the answer.
Do your setup in "viewWillAppear" and I'll bet it starts working.
Please check with this,
dvc.rowItem = [[NString alloc]initWithString:#"%#",[_objects objectAtIndex:indexPath.row]];
I'm having some difficulty figure out what I'm doing wrong when trying to assign my a delegate for my UIPopoverView. I tried to work around not even using one, but having it would be much more straightforward and clean. Here is the code that I think should cover it:
//.h of View where I call popover, this would be the delegate.
#import <UIKit/UIKit.h>
#import "ACTypePopoverViewController.h"
#interface NewRouteViewController : UIViewController<ACTypePickerDelegate>{
ACTypePopoverViewController *_acTypePicker;
UIPopoverController *_acTypePickerPopover;
}
#property (nonatomic, retain) ACTypePopoverViewController *acTypePicker;
#property (nonatomic, retain) UIPopoverController *acTypePickerPopover;
#end
//.m file for where I would like to use the popover, is the .m for the .h above
if (_acTypePickerPopover == nil)
{
ACTypePopoverViewController* content = [[ACTypePopoverViewController alloc] init];
UIPopoverController* aPopover = [[UIPopoverController alloc]
initWithContentViewController:content];
aPopover.delegate = self;
[content release];
// Store the popover in a custom property for later use.
self.acTypePickerPopover = aPopover;
}
[self.acTypePickerPopover presentPopoverFromRect:self.selectACTypeButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
//.h file for the actual popover, what I would be setting the delegate of
#protocol ACTypePickerDelegate
- (void)acTypeSelected:(NSString *)acType;
#end
#interface ACTypePopoverViewController : UITableViewController {
NSMutableArray *_acTypes;
NSString *selectedACType;
id<ACTypePickerDelegate> _delegate;
}
#property (nonatomic, retain) NSMutableArray *acTypes;
#property (nonatomic, retain) NSString *selectedACType;
#property (nonatomic, assign) id<ACTypePickerDelegate> delegate;
#end
I think thats all I need, but let me know if more code is needed!
Thanks!
I understood you correctly... what you need is:
content.delegate = self;
Right after this line you have:
ACTypePopoverViewController* content = [[ACTypePopoverViewController alloc] init];
Are you synthesizing your properties? Also you are assigning your delegate before initiating the popover...
#synthesize acTypePickerPopover;
self.acTypePickerPopover = [[[UIPopoverController alloc]
initWithContentViewController:_acTypePickerPopover] autorelease];
self.acTypePickerPopover.delegate = self;
`
I have two buttons that are not performing the IBAction that they are programmed to do. I have them correctly connected in Interface Builder, but when I click them in the simulator or on a phone, they do not perform their task. No crashes, nothing. Here is my code
MapDetailInfo.h:
#interface MapDetailInfo : UIViewController {
IBOutlet UILabel *name;
IBOutlet UITextView *address;
NSString * nameText;
NSString * addressText;
NSString * stringOne;
NSString * stringTwo;
IBOutlet UILabel *phoneNumber;
}
#property (retain, nonatomic) IBOutlet UILabel *name;
#property (retain, nonatomic) IBOutlet UITextView *address;
#property (nonatomic, copy) NSString * nameText;
#property (nonatomic, copy) NSString * addressText;
#property (retain, nonatomic) NSString * stringOne;
#property (retain, nonatomic) NSString * stringTwo;
#property (retain, nonatomic) IBOutlet UILabel *phoneNumber;
- (IBAction)callPhone:(id)sender;
- (IBAction)getDirections:(id)sender;
#end
MapDetailInfo.m:
#implementation MapDetailInfo
#synthesize name, address, nameText, addressText, phoneNumber, stringTwo, stringOne;
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *myWords = [addressText componentsSeparatedByCharactersInSet:
[NSCharacterSet characterSetWithCharactersInString:#"("]
];
stringOne = [myWords objectAtIndex:1];
stringTwo = #"(";
stringTwo = [stringTwo stringByAppendingString:stringOne];
self.name.text = nameText;
self.address.text = [myWords objectAtIndex:0];
self.phoneNumber.text = stringTwo;
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(callPhone:)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"Call Shop" forState:UIControlStateNormal];
button.frame = CGRectMake(104.0, 332.0, 160.0, 40.0);
[self.view addSubview:button];
}
- (IBAction)callPhone:(id)sender {
NSString *URLString = [#"tel://" stringByAppendingString:stringTwo];
NSURL *URL = [NSURL URLWithString:URLString];
[[UIApplication sharedApplication] openURL:URL];
}
- (IBAction)getDirections:(id)sender {
[[UIApplication sharedApplication] openURL:
[NSURL URLWithString:[NSString stringWithFormat:#"http://maps.google.com/maps?saddr=Current Location&daddr=%#",self.address.text]]];
}
I am pulling this view from an annotation in a map. Everything works perfect accept for these two buttons not performing their task. Any help would be much appreciated. Thanks!
The reason the buttons were not working is because the URL's were incorrect. If you run into the same problem, make sure your telephone number URL's are:
#"tel://5555555"
I had the parenthesis and dash inside of mine and that is why it would not pull up. Also there was an error in my google URL.
Thanks!
I dont see any UIButton in your code. Did you use them ?
Edit:
I had suggested that you use buttons for that is the specific purpose. And yes, you can still use labels and follow the same procedure to call the methods.
There has to be some issue with the way you are connecting the outlets.
I would suggest that you follow tutorials - 4, 5, and 6 of this Youtube link.
http://www.youtube.com/watch?v=B7jB0D3Y7Ws&feature=relmfu
I have a method tied to four buttons. I want to create an array containing each button, and later retrieve and interact w/ a button from the array. The code I was tinkering with below. When I try to get a button from the array and send it a message, it goes kablooie.
Any thoughts on what I'm doing wrong?
Hack_DumpViewController.h
#import <UIKit/UIKit.h>
#interface Hack_DumpViewController : UIViewController {
IBOutlet UIButton *redButton;
IBOutlet UIButton *greenButton;
IBOutlet UIButton *blueButton;
IBOutlet UIButton *yellowButton;
NSArray *buttonMapping;
}
- (IBAction) changeToYo:(id)sender;
#property (nonatomic, retain) UIButton *redButton;
#property (nonatomic, retain) UIButton *greenButton;
#property (nonatomic, retain) UIButton *blueButton;
#property (nonatomic, retain) UIButton *yellowButton;
#property (nonatomic, retain) NSArray *buttonMapping;
#end
Hack_DumpViewController.m
#import "Hack_DumpViewController.h"
#implementation Hack_DumpViewController
#synthesize redButton;
#synthesize greenButton;
#synthesize yellowButton;
#synthesize blueButton;
#synthesize buttonMapping;
- (IBAction) changeToYo:(id)sender {
NSLog(#"changing numbers!");
for (UIButton *b in buttonMapping) {
[b setTitle:#"yo!"];
}
NSLog(#"changed to numbers!");
}
- (void)viewDidLoad {
buttonMapping = [[NSArray alloc] initWithObjects:greenButton, redButton, yellowButton, blueButton, nil];
}
[NSArray arrayWithObjects:...] returns an autoreleased array, so by the time you use it, it no longer exists and you end up messaging an invalid pointer. What you want is [[NSArray alloc] initWithObjects:...] (remembering to release it in your dealloc).
Why not tag the views in interface builder and then treat them like an array, much easier