I am completely new to iPhone development and basically any C language at all. I understand the concept of variables and so forth, so I'm trying to use them in basic way to get a better grasp on the concept. Unfortunately, I'm getting compiler warnings when I try to do something very simple: I just want to assign my 5 variables values.
ViewController.h code:
#interface MyApplicationViewController : UIViewController {
IBOutlet UITextView *variable1;
IBOutlet UITextView *variable2;
IBOutlet UITextView *variable3;
IBOutlet UITextView *variable4;
IBOutlet UITextView *variable5;
}
[I know that theoretically I could connect those variables to text views in IB, but I'm not]
#property (nonatomic, retain) IBOutlet UITextView *variable1;
#property (nonatomic, retain) IBOutlet UITextView *variable2;
#property (nonatomic, retain) IBOutlet UITextView *variable3;
#property (nonatomic, retain) IBOutlet UITextView *variable4;
#property (nonatomic, retain) IBOutlet UITextView *variable5;
#end
ViewController.m code:
#implementation MyApplicationViewController
#synthesize variable1;
#synthesize variable2;
#synthesize variable3;
#synthesize variable4;
#synthesize variable5;
- (void)viewDidLoad {
variable1 = "memory text1"; [Warning]
variable2 = "memory text2"; [Warning]
variable3 = "memory text3"; [Warning]
variable4 = "memory text4"; [Warning]
variable5 = "memory text5"; [Warning]
}
I do not deallocate my variables because I want to keep them in memory until the application is completely terminated. Why am I getting these warnings? Am I doing anything wrong? All I'm intending to do here is save the variables' values (memorytext1, memory text 2, etc.) in the memory. I've looked at the other conversation about this warning on Stack Overflow, but their problem didn't seem to match mine, although the warning was the same. Please don't say anything too complicated, because I am still new to this. Thanks!
There're 2 problems:
1st problem is that you're trying to assign string to your text fields variables - if you want to set field's text then you should use its text property
2nd problem (that actually gives you compiler warning) is that "string" means c-string literal - you should use #"string" instead
So correct code to set textfield's text should be
variable1.text = #"text1";
You are missing the # at the beginning of the text!
variable1.text = #"memory text1";
variable2.text = #"memory text2";
variable3.text = #"memory text3";
variable4.text = #"memory text4";
variable5.text = #"memory text5";
Vladimir is correct, assuming you are using a NIB file to assign the UITextView properties. If you are not using a NIB your variables will be nil and your strings will not be assigned anywhere.
Related
I'm working on a project for iOS5 using ARC and storyboard.
I have a mapview with annotations with a disclosure button going to my DetailView (which is a TableViewController) but when it's supposed to be loaded, I get the following error:
2012-07-18 14:09:43.328 Zone-It-new[1966:707] Loadded the view for MapViewController
2012-07-18 14:11:40.467 Zone-It-new[1966:707] -[UILabel copyWithZone:]: unrecognized selector sent to instance 0x138470
2012-07-18 14:11:40.470 Zone-It-new[1966:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UILabel copyWithZone:]: unrecognized selector sent to instance 0x138470'
*** First throw call stack:
(0x3748488f 0x35189259 0x37487a9b 0x37486915 0x373e1650 0x311997ef 0x31195059 0x31194711 0x3119466b 0x311945e7 0x31284f63 0x311979bb 0x311973ad 0x31191b8b 0x311917d5 0x9386d 0x3120a93d 0x31284627 0x37cf5933 0x37458a33 0x37458699 0x3745726f 0x373da4a5 0x373da36d 0x33b99439 0x31186cd5 0x924b3 0x92458)
terminate called throwing an exception(lldb)
This is my detailviewcontroller.h:
#import <UIKit/UIKit.h>
#import "Event.h"
#interface DetailViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource>{
IBOutlet UILabel *title;
IBOutlet UILabel *description;
IBOutlet UILabel *zone;
IBOutlet UILabel *gemeente;
IBOutlet UILabel *plaats;
IBOutlet UILabel *deelnemers;
IBOutlet UILabel *start;
IBOutlet UILabel *einde;
IBOutlet UILabel *id_nr;
}
#property (nonatomic) Event *event;
#property (nonatomic) IBOutlet UILabel *title, *zone, *description, *gemeente, *deelnemers, *start, *einde, *plaats, *id_nr;
#end
part of the DetailViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[[self navigationController] setNavigationBarHidden:NO animated:YES];
/*title.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin;*/
[title lineBreakMode];
[title setText:[event title]];
[title sizeToFit];
gemeente.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin;
[title lineBreakMode];
[gemeente setText:[event gemeente]];
}
And this is where the view gets created in via the ListView:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"detail"];
SingletonManager *sharedManager = [SingletonManager sharedManager];
[detail setEvent:[sharedManager.eventsManager objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:detail animated:YES];
}
Event.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface Event : NSObject <MKAnnotation>
// required property from mkanotation
#property (nonatomic) CLLocationCoordinate2D coordinate;
// Optional
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *description;
#property (nonatomic, copy) NSString *zone;
#property (nonatomic, assign) NSString *gemeente;
#property (nonatomic, copy) NSString *straat;
#property (nonatomic, assign) int deelnemers;
#property (nonatomic, copy) NSDate *start;
#property (nonatomic, copy) NSDate *einde;
#property (nonatomic, copy) NSString *plaats;
#property (nonatomic, readonly) int id_nr;
#property (nonatomic, assign) int huisnummer;
#end
----- Some more debugging information -------
While using the exception breakpoints it stopped here:
[self.navigationController pushViewController:detail animated:YES];
console:
2012-07-18 15:53:46.691 Zone-It-new[179:707] Loadded the view for MapViewController
2012-07-18 15:54:01.940 Zone-It-new[179:707] -[UILabel copyWithZone:]: unrecognized selector sent to instance 0x170bb0
(lldb)
It appears that somewhere in your code you're trying to copy a UILabel. UIView subclasses don't adhere to the NSCopying protocol, so trying to copy any UIView will result in an exception (unless it's a subclass that does implements the protocol). I'd search through your code base to check where the copy is occurring. If you can't find any place that explicitly copies the UILabel, check collection classes. Some collections classes will copy values in (NSDictionary does this with keys, so if you're trying to use a UILabel as a key for a NSDictionary, you'll get the error). Also check your properties. What you show in your displayed code is fine, but if you specify a copy in a protocol for a UILabel, that'll also give the error.
You should also try standard debugging techniques like setting a breakpoint for all exceptions. (go to the breakpoints nav pane, at the bottom click the plus sign). This should help you find the problem by breaking on your offending line of code. Just be aware that if the copying is occurring in Apple's code (like setting a NSDictionary key) the breakpoint might not break on your code.
Update
Given your new code, I would suggest trying the following:
Try to find any place in your code where "anything" is copied. Obviously your not explicitly copying UILabel but maybe you're accidentally copying it by passing the wrong argument somewhere. For example: Remove all copy keywords from your Event properties and test it again. You probably don't need to specify copy for NSString anyway, but what we're doing here is making sure you're not accidentally setting a UILabel to one of those properties. If the code doesn't break, you didn't fix it but now you know what the problem is (trying to assign a UILabel to the wrong property).
Start commenting out various blocks of code, one at a time, to find the problem. For example, comment out your entire viewDidLoad method and test your code. If it works, you know the problem is in there. So uncomment part of the method and test again. Keep repeating until you've narrowed down the problem. If it still breaks with viewDidLoad, uncomment that and try a different block of code. In essence, you're playing detective to try to find the offending line of code.
The fix for this is to rename the title property in the UIViewController. This is due to the fact that UIViewController already defines an NSString * property with a name of title.
This can often mean you're trying to assign an object to a method that can't handle it, rather than a property of that object. For example, trying to set a UILabel to an object rather than a string property on that object.
My guess is it's this line: [gemeente setText:[event gemeente]];
There could also be an issue here:
#property (nonatomic) Event *event;
You haven't set Event *event as an instance variable but are referencing it as one. Try self.event for accessing event as you have it above.
I am new to iOS 5. From Apple's documentation I know what ARC is and "Owner of an object should using strong notation." After read "Hello World" , I noticed a strange thing.(I mean that was confusing me)
HelloWorldAppDelegate:
#interface HelloWorldAppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
HelloWorldViewController:
#import <UIKit/UIKit.h>
#interface HelloWorldViewController : UIViewController <UITextFieldDelegate>
#property (weak, nonatomic) IBOutlet UITextField *textField;
#property (weak, nonatomic) IBOutlet UILabel *label;
- (IBAction)changeGreeting:(id)sender;
#property (copy, nonatomic) NSString *userName;
#end
Here:
#property (weak, nonatomic) IBOutlet UITextField *textField;
#property (weak, nonatomic) IBOutlet UILabel *label;
UI elements have weak notation and none of file have a strong references to them. So I am confusing what/who hold them?
In my opinion you can consider the NIB/XIB as the owner of those objects. None of your classes own them. See "Managing the Lifetimes of Objects from Nib Files" in Resource Programming Guide:
From a practical perspective, in iOS and OS X outlets should be defined as declared properties. Outlets should generally be weak, except for those from File's Owner to top-level objects in a nib file (or, in iOS, a storyboard scene) which should be strong. Outlets that you create should will therefore typically be weak by default, because:
Outlets that you create to, for example, subviews of a view controller's view or a window controller's window, are arbitrary references between objects that do not imply ownership.
The strong outlets are frequently specified by framework classes (for example, UIViewController's view outlet, or NSWindowController's window outlet).
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Prefixing property names with an underscore in Objective C
iPhone App Developer Beginner here:
in .h
#property (nonatomic, retain) IBOutlet UILabel *detailDescriptionLabel;
in .m
#synthesize detailDescriptionLabel = _detailDescriptionLabel;
I'm used to seeing
#synthesize detailDescriptionLabel;
the = _ is throwing me off, what is this doing?
Each property is backed by an instance variable. The language allows for them to be named differently. By doing #synthesize detailDescriptionLabel = _detailDescriptionLabel;, you're basically saying that use _detailDescriptionLabel as the backing instance variable for the property detailDescriptionLabel. If you just do #synthesize detailDescriptionLabel;, it implicitly understands that the instance variable has the same name.
n .h
UILabel *_detailDescriptionLabel;
}
#property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
in .m
#synthesize detailDescriptionLabel = _detailDescriptionLabel;
This line means that the property "detailDescriptionLabel" will have a setter and getter for the class attribute named "_detailDescriptionLabel"
If the name was the same, you will have
#synthesize detailDescriptionLabel;
I've noticed that some generated classes only declare class properties/variables via #property, and don't include them within the #interface, as such:
#interface AddItemViewController : UITableViewController {
}
#property (nonatomic, retain) UITextField *itemName;
I was just curious if that's an acceptable way to do it, or if that is done for different reasons?
I normally do this:
#interface AddItemViewController : UITableViewController {
UITextField *itemName;
}
#property (nonatomic, retain) UITextField *itemName;
I declare it first in the #interface and then add the #property for it...
* Update *
I just wanted to update this a bit, because it's still not 100% clear to me.
I always thought that to declare a #property, you first needed to declare it within the #interface first, and then I saw this:
#interface mInventoryAppDelegate : NSObject <UIApplicationDelegate> {
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
#property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#end
All of those #property declarations are declared only as #properties, and not within the #interface.
For example, if I had say NSString *myString - I can declare that in the #interface and not as a #property and still have access to it no problem, but the getters and setters won't be created. I could also declare it in both. But what if I just declare it as #property, as such:
#interface AddItemViewController : UITableViewController {
}
#property (nonatomic, retain) NSString *myString;
Notice how I didn't add it between the #interface { } - how does it differ.
Sorry for repeating, but I'm just trying to reword this so that I can get an answer that makes more sense to me.
With the "modern" runtime, which the iPhone uses, the compilers can create the instance variable for you. Just use:
#synthesize itemName;
or if you prefer...
#synthesize itemName=_itemName;
...in your implementation. The compilers will then create ivar 'itemName' or '_itemName'.
This is of course for the case that the property is a simple getter/setter for one particular instance variable.
EDIT: NVM, per #bbum, what I thought of in my mind as the "32-bit" sim is actually the older simulator that didn't behave like the new runtime. The newer simulator is still 32-bit, and supports this behavior. See his comment below.
update
In response to your updated question:
The "interface" for a class is everything up to the #end. I think what you are calling "interface" is actually just the instance variables within the {}. What is between the {} are the instance variables for your class. The whole #interface includes those instance variables PLUS the method and #property declarations between the {} and the #end.
So I think what you are really asking is if you have a #property in your #interface, and that #property is just a simple getter/setter pair, then do you need to declare a "backing" instance variable also in your #interface, within the {}.
The answer for iPhone is NO. The compilers (both) can create that instance variable for you.
I hope that answers the question?
It is perfectly acceptable to do it this way. You would however need to implement the setter/getter methods yourself. These can not be created using the #synthesize syntax.
One reason to use this approach could be to have the properties based on something more complex than just setting and getting a value. It doesn't however make much sense for simple Nib connections as in your example.
I am trying to add a record to the database using core data. The appDelegate has the managed object model, context, and store coordinator setup in it. When the app is launched and I query the fetchResultsController method in one of my views the database is created matching the scheme with the correct table names and columns in it. However the problem comes when I try to add a record to the table.
The BurpListNavController.h file has the following contents (I am just learning):
#import <UIKit/UIKit.h>
#class BurpRecordController;
#interface BurpListNavController : UINavigationController <NSFetchedResultsControllerDelegate> {
BurpRecordController *burpRecordController;
NSFetchedResultsController *fetchedResultsController;
NSManagedObjectContext *managedObjectContext;
}
#property (nonatomic, retain) IBOutlet BurpRecordController *burpRecordController;
#property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
#property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
- (void)saveBurpLocal:(id)sender;
#end
I then have a view that records the burp, yes another one of the thousands of burp applications. haha. The following code is as follows:
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudioTypes.h>
#class BurpLocal;
#class BurpListNavController;
#interface BurpRecordController : UIViewController <AVAudioRecorderDelegate, UIActionSheetDelegate> {
/*** Outlets to talk to the view ***/
IBOutlet UITextField *burpName;
IBOutlet UIButton *_recordButton;
/*** Standard Variables ***/
NSURL *recordedTmpFile;
//AVAudioRecorder *recorder;
NSError *error;
BurpLocal *burpLocal;
BurpListNavController *burpListNavController;
}
/*** Properties ***/
#property (nonatomic, retain) IBOutlet UITextField *burpName;
#property (nonatomic, retain) IBOutlet UIButton *recordButton;
#property (nonatomic, assign) IBOutlet BurpListNavController *burpListNavController;
#property(nonatomic, retain) BurpLocal *burpLocal;
/*** Method ***/
-(IBAction)saveRecording:(id)sender;
-(void)applicationWillTerminate:(NSNotification *)notification;
#end
When the end-user pushes the "save" button it calls the "saveRecording" method which I can step into and is great. Then I try to call the following line of code within the "saveRecording" method: [burpListNavController saveBurpLocal:sender]; thinking this will call the "saveBurpLocal" method in the nav controller and it just steps over it, does not stop at the break point in the nav controller method and then just goes to the end of the current "saveRecording" function. Does not write a record to the database or anything.
Please help! This is driving me crazy.
It's difficult to tell without more code; but it sounds like burpListNavController has not been set. When you step through the saveRecording: method, is the value of burpListNavController 0x0? If it is then you have forgotten to set that iVar somewhere.
If you have come from another language this might sound a little strange, as usually calling a method on a null pointer you cause you to crash. This isn't the case in Objective-C though, it is perfectly legal to send a message to nil; but don't expect anything to actually happen.