In Obj-c (xCode) how do I display this string to the text field? - objective-c

I am trying to make a practice application that takes two entered words (word1, word2) and puts them together to make a compound word. I am very new to this and would like to know the correct way to display these two variables under the action "buttonPressed."
Here's the header file...
#import <UIKit/UIKit.h>
#interface Word_CombinerViewController : UIViewController {
UITextField *word1;
UITextField *word2;
UITextField *display;
UIButton *mashButton;
}
#property (nonatomic, retain) IBOutlet UITextField *word1;
#property (nonatomic, retain) IBOutlet UITextField *word2;
#property (nonatomic, retain) IBOutlet UITextField *display;
#property (nonatomic, retain) IBOutlet UIButton *mashButton;
-(IBAction)textFieldDoneEditing:(id)sender;
-(IBAction)backgroundTap:(id)sender;
-(IBAction)buttonPressed:(id)sender;
#end
And here's the implementation file (.m)...
#import "Word_CombinerViewController.h"
#implementation Word_CombinerViewController
#synthesize word1;
#synthesize word2;
#synthesize display;
#synthesize mashButton;
-(IBAction)textFieldDoneEditing:(id)sender {
[sender resignFirstResponder];
}
-(IBAction)backgroundTap:(id)sender {
[word1 resignFirstResponder];
[word2 resignFirstResponder];
}
-(IBAction)buttonPressed:(id)sender {
NSString *newText = [NSString: #word1, #word2]
display.text = newText;
[newText release]
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[word1 release];
[word2 release];
[display release];
[mashButton release];
[super dealloc];
}
#end
I know this code is probably full of errors, but everyone has gotta start somewhere, right?
Any feedback would be greatly appreciated, thank you!

NSString *newText = [NSString: #word1, #word2]
This code doesn't make any sense. The first part of a message is the receiver, and it won't have any colons in it. The second part is the message itself, i.e. the method name along with any necessary parameters. What you're looking for is:
NSString *newText = [NSString stringWithFormat:#"%#%#", word1, word2];
The -stringWithFormat: method uses a format string (very much like printf()) and a variable number of parameters to fill in the placeholders in the format string.
Also, when you create a string (or any object) using a "convenience method" like this, you shouldn't release it. You didn't retain or alloc or copy it, so it's not your responsibility to release it. You'll want to remove that line from your -buttonPressed method.

Try this:
-(IBAction)buttonPressed:(id)sender {
NSString *newText = [word1.text stringByAppendingString:word2.text]
display.text = newText;
}

Related

Issue adding to NSMutableArray

I have looked all over the place for anyone who has experienced this issue but have yet to find anything relevant, so I thought I'd ask it myself...
I have a custom object (HitterData) which I will use to populate cells in a UITableView, then two ViewControllers (one is hitterTableViewController, the other is a "detail" view controller labeled "AddPlayerViewController").
The problem is that I can add HitterData objects to the NSMutableArray in my Table VC, but only one, and then when I add another one using the detail view controller, the Mutable array is "reinitialized" and I can again only have one object at a time.
HitterObject:
#implementation HitterData.m
#synthesize hitterName = _hitterName;
#synthesize position = _position;
-(id)initWIthNameAndPosition:(NSString *)hitterName position:(NSString *)position {
if ((self = [super init])) {
self.hitterName = _hitterName;
self.position = _position;
}
return self;
}
HitterTableViewController.h
#import "HitterData.h"
#import "HitterDoc.h"
#import "AddPlayerViewController.h"
#interface HitterTableViewController : UITableViewController
#property (nonatomic, strong) NSMutableArray *hitters;
- (IBAction)backButton:(id)sender;
- (IBAction)addPlayerView:(id)sender;
-(void)addHitterObject:(HitterData *)hitter;
HitterTableViewController.m (only relevant to make this more readable)
#implementation HitterTableViewController
#synthesize hitters = _hitters;
- (void)viewDidLoad {
[super viewDidLoad];
self.hitters = [NSMutableArray array];
}
-(void)addHitterObject:(HitterData *)hitter {
if(_hitters != nil) {
[_hitters addObject:hitter];
} else {
_hitters = [NSMutableArray array];
[_hitters addObject:hitter];
NSLog(#"MutableArray is not valid");
}
}
AddPlayerViewController.h
#interface AddPlayerViewController : UIViewController <UITextFieldDelegate, UINavigationControllerDelegate>
#property (weak, nonatomic) IBOutlet UITextField *nameTextField;
#property (weak, nonatomic) IBOutlet UITextField *positionTextField;
#property (nonatomic) HitterTableViewController *hitterTable;
#property (nonatomic) NSString *hitterName;
#property (nonatomic) NSString *position;
//-(void)addNewHitterToHittersArray:(HitterData *)hitter;
- (IBAction)addPlayerToRoster:(id)sender;
AddPlayerViewController.m
#implementation AddPlayerViewController
#synthesize hitterTable;
- (void)viewDidLoad {
[super viewDidLoad];
hitterTable = [[HitterTableViewController alloc] init];
}
- (IBAction)addPlayerToRoster:(id)sender {
self.hitterName = [self.nameTextField text];
self.position = [self.positionTextField text];
HitterData *hitter = [[HitterData alloc] init];
hitter.hitterName = self.hitterName;
hitter.position = self.position;
[hitterTable addHitterObject:hitter];
ArraySingleton *arrayS = [[ArraySingleton alloc] init];
[arrayS initializeArray];
[arrayS addToHittersArray:hitter];
if (arrayS) {
NSLog(#"arrayS exists in AddPlayerVC");
} else {
NSLog(#"arrayS does not exist");
}
[self performSegueWithIdentifier:#"backToTeamTableViewController" sender:self];
}
Am I missing something here?
Guess based just on the code shown:
Every time you wish to add a player it looks like you create a new AddPlayerView/AddPlayerViewController. In turn that controller creates, in its viewDidLoad, a new HitterTableViewController - which of course has its own empty array. The code should instead be referencing the existing HitterTableViewController.
BTW: The common design pattern is MVC - model, view, controller - consider whether you are in your current situation because you've stored part of your model, the array, in your controller, and maybe both controllers should be referencing a common shared model object containing that array.
BTW: All those #synthesise statements are unneeded. In modern Obj-C synthesis is automatic and you rarely need these statements. Also it is generally recommended to not use the property backing variable directly, and certainly not when storing into the property as this breaks KVO. (There also appears to be a related typo in HitterData.m but as you don't report that as not working it is probably just a typo in your question and not code.)
HTH
AddPlayerViewController should know nothing about HitterTableViewController, return the new HitterData object with a delegate method.
- (IBAction)addPlayerToRoster:(id)sender
{
Hitter *hitter = [[Hitter alloc] init];
hitter.name = [self.nameTextField text];
hitter.position = [self.positionTextField text];
[self.delegate didAddHitter:hitter];
}
Then back in HitterTableViewController
- (void)didAddHitter:(Hitter *)hitter
{
[self.hitters addHitter:hitter];
[self dismissViewControllerAnimated:YES completion:nil];
}

Use of undeclared identifier errors

i'm getting "use of undeclared identifier" errors in my .m file with the code below and can't seem to work it out.
NSArray *imageViews = [NSArray arrayWithObjects:img1, img2, img3, img4, img5, img6, img7, img8, img9, img10, img11, img12, img13, img14, img15, img16, img17, img18, img19, img20, img21, img22, img23, img24, img25, img26, img27, img28, img29, img30, img31, img32, img33, img34, img35, img36, img37, img38, img39, img40, nil];
In my .h file i have 40 images, all with referencing outlets:
#property (weak, nonatomic) IBOutlet UIImageView *imgX;
where X is a number from 1-40. In my .m file, the NSArray *imagesViews works fine as long as it's inside a method, but i can't declare it outside the method so that it is available to all methods. As an Objective-C novice, I don't where to go from here. I'd appreciate any help.
You don't have to initialize the array outside of a method to make it accessible from all methods. What you should do instead is declare it as a property and initialize it inside the viewDidLoad method.
In the .h file:
#property (strong, nonatomic) NSArray *imageViews;
#property (weak, nonatomic) IBOutlet UIImageView *img1;
// ...
In the .m file:
#synthesize imageViews, img1, img2, ...
// ...
- (void)viewDidLoad
{
[super viewDidLoad];
// ...
self.imageViews = [NSArray arrayWithObjects:self.img1, self.img2, ... , nil];
}
Also, note that because you have 40 image views, you should probably avoid declaring a property for each one of them. You can assign tags to them, and then retrieve them using the method viewWithTag.
In the header:
#interface MyClass : NSObject {
NSArray *imageViews;
}
#end
In the implementation:
#implementation MyClass
- (id) init
{
self = [super init];
if (self != nil) {
imageViews = [[NSArray arrayWithObjects:img1, nil] retain];
}
return self;
}
// now you can use imageViews also from other methods
- (void) dealloc
{
[imageViews release];
[super dealloc];
}
#end

Getting exc_bad_access in UITableViewController while getting object from NSMutableArray

I have a subclass of UITableViewController, and I init the subclass with a NSMutableArray of another custom class:
#import <UIKit/UIKit.h>
#import "NUBCheckpointModel.h"
#interface NUBUserCheckpointModel : NSObject
#property (nonatomic,assign) NSString* objId;
#property (nonatomic,assign) NSString* userId;
#property (nonatomic,assign) NSString* checkpointId;
#property (nonatomic,assign) NSDate* dateAdded;
#property (nonatomic,assign) NUBCheckpointModel* checkpoint;
+ (NUBUserCheckpointModel*) fromJson: (NSString*)json;
#end
This array that is generated from another ViewController, gets passed into this subclassed TableViewController, of which contain this property
#property (nonatomic,retain) NSMutableArray* userCheckpointData;
This property is set like this:
- (id)initWithFrame: (CGRect)frame withType: (TableType)typeOfTable fromParent: (UIViewController*)parent data: (NSMutableArray*)ucpData
{
self = [self init];
if (self) {
self.tableView = [[UITableView alloc] initWithFrame:frame];
self.parentController = parent;
self.userCheckpointData = ucpData;
[self styleTable];
[self addPullToRefreshHeader];
typeCategory = typeOfTable;
}
return self;
}
All is fine up to this part, and any manipulation including trying to get an object from the array works fine. I tested it.
The code I used to test the array is:
NUBUserCheckpointModel* model = [self.userCheckpointData objectAtIndex:0];
NSLog(model.objId);
However, this very same code, when used here:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Gives me exc_bad_access. May I know why this happens? I can't seem to figure out why. I'm using ARC btw. Thank you.
While adding the property, you need to take care of the memory management. For string, it is not good practice to set assign property.
Instead , do as following,
#property (nonatomic,copy) NSString* objId;
#property (nonatomic,copy) NSString* userId;
#property (nonatomic,copy) NSString* checkpointId;
#property (nonatomic,retain) NSDate* dateAdded;
#property (nonatomic,retain) NUBCheckpointModel* checkpoint;

Getting name of the image which is on the image view

Is there any way to get the name of the image which is present on the image view which is there on my screen. Please tell me ways to do this. I already searched it a lot but still have not found anything useful. Please help.
You can subclass UIImageView and add a property name or identifier.
#interface MyImageView : UIImageView{
NSString *name;
}
#property (retain) NSString *name;
-(id)initWithImage:(UIImage *)image andName:(NSString *)name;
#end;
#implementation MyImageView
#synthesize name;
-(id)initWithImage:(UIImage *)image andName:(NSString *)name
{
if(self = [super initWithImage:image]){
self.name = name;
}
return self;
}
-(void)dealloc
{
self.name = nil;
[super dealloc;]
}
You should use the tag property of the view to distinguish between different imageViews.

After setting one NSManaged object to another it returns Null

I am trying to pass the selected object in my coredata from the rootviewcontroller to the edit view. The selected object is being passed but is then becoming null after the theObject=selectedObject is being called. Anyone know what im doing wrong?
This is in the edit.h
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#import "LearningAppDelegate.h"
#interface edit : UIViewController <UITextViewDelegate, UITableViewDelegate, UITableViewDataSource, UIActionSheetDelegate>{
UITableView *tableView;
NSManagedObject *theObject;
UITextView *messageView;
}
#property(nonatomic, retain) IBOutlet UITableView *tableView;
#property(nonatomic, retain) IBOutlet UITextView *messageView;
#property(nonatomic, retain) NSManagedObject *theObject;
-(id)initWithObject:(NSManagedObject *)selectedObject;
#end
This is in the edit.m:
-(id)initWithObject:(NSManagedObject *)selectedObject {
self = [super init];
if (nil == self) {
return nil;
}
NSLog(#"selectedObject: %#", selectedObject);
NSLog(#"selecetedObject.message: %#", [[selectedObject valueForKey:#"message"] description]);
theObject=selectedObject;
NSLog(#"theObject 1: %#", theObject);
NSLog(#"theObject.message 1: %#", [[theObject valueForKey:#"message"] description]);
return self;
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
NSLog(#"theObject 2: %#", theObject);
NSLog(#"theObject.message 2: %#", [[theObject valueForKey:#"message"] description]);
messageView.text=[[theObject valueForKey:#"message"] description];
[super viewDidLoad];
}
I am actually amazed that doesn't crash for you. You're assigning the variable selectedObject into the instance variable theObject without retaining it for your own use. By accessing the instance variable directly in the assignment 'theObject=selectedObject', you're bypassing the behavior granted by the #property declaration. This means that once selectedObject is finally dealloc'd, theObject will point to garbage memory.
The correct way to do this is to put theObject = [selectedObject retain]; in the -initWithObject: method and in -viewDidLoad to access it via self.theObject rather than just theObject.
In my own usage I prefer to give instance variables names different from the actual property name to avoid confusion. For example:
#interface SomeClass : NSObject
{
#private
NSManagedObject *_theObject;
}
#property (nonatomic, retain) NSManagedObject *theObject;
...
#end
#implementation SomeClass
#synthesize theObject = _theObject
...
- (void)dealloc
{
[_theObject release], _theObject = nil;
[super dealloc];
}
#end
I only have experience with Coredata on the desktop, but the problem looks like it would be with your initWithObject method. At no point do you actually insert the new object into the managed object context. You should be using this method to make new objects:
- (id)initWithEntity:(NSEntityDescription *)entity insertIntoManagedObjectContext:(NSManagedObjectContext *)context
As an example in pseudocode:
NSManagedObject *newObject = [[NSManagedObject alloc] initWithEntity:NSENTITYDESCRIPTION insertIntoManagedObjectContext:MANAGEDOBJECTCONTEXT];
[newObject setValue:#"VALUE_OF_SELECTED_OBJECT" forKey:#"APPROPRIATE_KEY"];
//REPEAT AS NECESSARY
[MANAGEDOBJECTCONTEXT save];
*Code not tested, naming conventions are ignored, etc.
The save is important. If you don't do this the object won't persist.