When I try to compile this I get this error. What do I need to add for the property declaration in the interface? If textBox is an instance variable, why does it need to be declared as a property?
ViewController.h
#import <UIKit/UIKit.h>
#interface TNRViewController : UIViewController {
IBOutlet UITextField *textBox;
IBOutlet UILabel *label;
}
- (IBAction)button:(id)sender;
#end
ViewController.m
#import "TNRViewController.h"
#implementation TNRViewController
#synthesize textBox;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)dealloc {
[textBox release];
[label release];
[super dealloc];
}
- (IBAction)button:(id)sender {
NSString *Name = textBox.text;
NSString *Output = Nil;
Output = [[NSString alloc] initWithFormat:#"%# says: Hello World!", Name];
label.text = Output;
[Output release];
}
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
[textBox resignFirstResponder];
return YES;
}
#end
textBox needs to be declared as a property because you are #synthesizing it in your implementation.
You need to either:
Add the #property declaration for textBox in your interface.
OR, You could remove the #sythesize line from your implementation if you don't plan on needing the setter/getter methods.
by writing #synthesize textBox in your implementation the compiler generates 2 methods for you automatically.
-(UITextField*)textBox
-(void)setTextBox:(UITextField *)textBox
To be accessed these need to be defined in the class' interface. Objective-C for the iPhone has a nifty shortcut for declaring these two methods, the #property directive. You can also include information about how the variable should be stored in this directive.
#property (nonatomic, retain) IBOutlet UITextField * textBox
Would give you your IBOutlet for a text field. It is also a stand in for the 2 methods above. It tells us that the textBox is retained by your class. By always using the setter and getter methods for a variable you can avoid releasing an object and referencing the instance variable later, when it may not be safe. It is best practise to do this. You would access the text field from within your class by doing
[self.textBox setText:#"aString"];
self.textBox.text = #"aString";
(the lines above are equivalent)
This error happened when I added a pod. I ended up deleting a updating my pod file and it fixed the error.
Related
This is my first day of Objective C so I apologise for the lack of knowledge.
I need to import an existing SKD into an App and I done it successfully. Now I need to create the delegate methods and I don't understand how can I do it.
This is the structure of the header file included from the SDK (SDKManager.h):
#protocol SDKManagerDelegate;
#interface SDKManager : NSObject
#property (nonatomic, weak) id<SDKDelegate> delegate;
+(void)initialize:(NSString*)appId withKEY:(NSString*)key;
+(void)setHandler:(id)delegate;
#end
#protocol SDKManagerDelegate <NSObject>
#required
-(void)appDidReceiveTokens:(NSDictionary*)items withResponse:(NSDictionary*)response;
#end
So, from my FirstViewController.m I was able to import the header and call two methods:
#import "FirstViewController.h"
#import "SDKManager.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[SDKManager setHandler:[UIApplication sharedApplication].delegate];
[SDKManager initialize:#"AppId"withKEY:#"1234"];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
but I have noticed that I am not able to call the other methods (i.e. appDidReceiveTokens).
Actually the instructions require to create those methods but I have no idea where.
Any help is really appreciated.
Thank you
You do not call delegate methods directly in the files in which you are implementing the delegate methods. Review Apples documentation on the concept of Delegation.
To implement this properly you would adopt the delegate in your class, then implement the delegate methods that are #required and/or #optional.
You've correctly created the delegate protocol and a property to store the SDKManager's delegate.
Your setHandler: and initialize:withKEY: methods are class methods, whereas the delegate property belongs to each instance of SDKManager. Without seeing your implementation file (.m) for SDKManager, it's hard to know why you've set it up this way. You may be attempting to follow a singleton pattern - if so, read up on it, e.g. here.
The reason for that is you have class methods which sets the calls setHandler method and the delegate is property, so where do you assign the delegate and when and how do you call the delegate. I hope you understand what a class and instance is. So, you cannot call the delegate until you create instance of your object.
You have two different class methods which is used to set some attributes to the class, would it make sense to have them as property.
More generic and better way to do this would be like this,
#protocol SDKManagerDelegate <NSObject>
#required
-(void)appDidReceiveTokens:(NSDictionary*)items
withResponse:(NSDictionary*)response;
#end
#protocol SDKManagerDelegate;
#interface SDKManager : NSObject
- (instancetype)initWithAppId:(NSString *)appId
key:(NSString *)key
delegate:(id<SDKManagerDelegate>)delegate;
#end
#interface SDKManager ()
#property (nonatomic, copy, readonly) NSString *appId;
#property (nonatomic, copy, readonly) NSString *key;
#property (nonatomic, weak, readonly) id<SDKManagerDelegate> delegate;
#end
#implementation SDKManager
- (instancetype)initWithAppId:(NSString *)appId
key:(NSString *)key
delegate:(id<SDKManagerDelegate>)delegate
{
if (self = [super init]) {
_appId = [appId copy];
_key = [key copy];
_delegate = delegate;
}
return self;
}
- (void)doSomeNetworkRequestHere
{
[self fetchTokenFromServer:^(NSDictionary *tokens, NSDictionary *response){
[self.delegate appDidReceiveTokens:tokens
withResponse:response];
}];
}
- (void)fetchTokenFromServer:(void(^)(NSDictionary *tokens, NSDictionary *response))completion
{
}
#end
i am in initial phase of development and i want to make sure i am in right direction with regards to memory management.
i have a view controller named LayoutViewController with xib.I have a custom ui-subclass with its xib named LayoutContainerView which basically contains a scrollview. I am using LayoutContainerView in LayoutViewController xib by IBOutlet.
I have an another UIView subclassed, which contains a view with background image, some labels and a transparent button with same frame as of viw.I am adding this custom controll in LayoutContainerView's scrollview.
my view controller .h looks like this:
#import <UIKit/UIKit.h>
#protocol LayoutVcRemovedProtocol;
extern const char* MyConstantKey;
#interface LayoutViewController : UIViewController
// public properties
#property (nonatomic, copy) NSString *databasePath;
#property (nonatomic, weak) id<LayoutVcRemovedProtocol> layoutVcRemovedProtocolDelegate;
#end
#protocol LayoutVcRemovedProtocol<NSObject>
-(void) layoutVcRemovedProtocolMethod;
#end
=========================
**some of relevant code of **implementation** file looks like this:**
//private stuffs goes here
const char* MyConstantKey = "MyConstantKey";
#interface LayoutViewController () <UIActionSheetDelegate, UIAlertViewDelegate>
#property(nonatomic, weak) IBOutlet LayoutContainerView *layoutContainerView;
#property(nonatomic, weak) IBOutlet UIButton *backbutton;
#property(nonatomic, weak) IBOutlet UILabel *layoutNameLabel;
#property (nonatomic, strong) UIView *baseView;
#property (nonatomic, strong) NSMutableArray *layoutModelArray;
-(IBAction)backButtonPressed;
#end
#implementation LayoutViewController
//my viewDidLoad and viewWillAppear look like this:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self adjustLayoutContainerFrameAndSetDataBasePath];
}
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.layoutNameLabel.text = [Utils getLayoutName];
[self getLatestData];
}
-(void) getLatestData
{
[self setUpDataSource];
[self setUpComponentsOnLayoutScreen];
}
#pragma mark - datasource method
-(void)setUpDataSource
{`
self.layoutModelArray = (NSMutableArray *)[LAYOUTMODULE getAllLayoutData];
}`
-(void)setUpComponentsOnLayoutScreen
{`
for (int i = 0; i < self.layoutModelArray.count; i++)
{
Layout *layout = [self.layoutModelArray objectAtIndex:i];
[self drawViewWithLayoutObject:layout];
}
[self.layoutContainerView.scrollView adjustContentSize];
}
this is what i am trying to manage memory:
-(void) cleanLayoutModelArray
{
if (self.layoutModelArray != nil && self.layoutModelArray.count >0)
{
[self.layoutModelArray removeAllObjects];
}
}
-(void) cleanComponents
{
[self.layoutContainerView.scrollView.subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
}
//user events
-(void) placeOrderForLayout:(Layout *)layout
{
[DELEGATE showLandscapeLoading];
//web service COMMUNICATION HERE here
OrderModule *oModule = [OrderModule sharedModule];
NSDictionary *requestDictionary = [NSDictionary dictionaryWithObjectsAndKeys:oModule.currentOrder.mOrderId,#"order_id",oModule.currentOrder.mPosId,#"pos_id",[Utils currentDate],#"book_date", layout.componentId, #"component_id", nil];
BOOL status = [LAYOUTMODULE placeComponentOrderThroughAPI:requestDictionary];
if (status == TRUE)
{
[self performCleanUp];
[self getLatestData];
}
[DELEGATE stopLandscapeLoading];
}
help me or any suggestion for:
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
what ever i try in memoryWarningDelegate view controller becomes black screen.
You've got a lot of #properties marked 'weak' in your code - when you mark things as weak, that means that something else is keeping track of whether it should still exist. Here you're doing it with IBOutlet items, which your controller should be keeping track, so they should be marked 'strong,' not weak. I'd review all your usage of 'weak' in this. Also refer to Apple's excellent doc on memory management. ARC will be handling most of your memory management for you. Usually, the only thing you need to do in didReceiveMemoryWarning, is to set to nil anything that's a large object, say a video or webpage you can reload if the user needs it again. Often, there's not much that you can free up at this time in your typical view. Note also that iOS devices have a fairly substantial memory footprint these days, so you should not worry about small data structures remaining resident in memory as long as they have the potential to be needed again. If you're having out of memory issues, I'd run with instruments and check for leaks.
There are many questions concerning the category-properties problem.
I know some possibilities to address this:
use a singleton registry
objc_setAssociatedObject and objc_getAssociatedObject
From my point of view both is not clean since the memory allocated is never cleared when the object that created such properties is deallocated.
Categories are a good way to keep code clean and dynamically add functionality to already existing classes. They help to group functionality and to distributed implementation work among more developers.
The bad about categories is the missing storage.
I came across this problem several times now and I'm wondering whether the following would address this problem in an clean way that also takes care about the memory and if there are any problems that I can't see right now.
There is one restriction, that I can ignore since I'm working as a framework developer: I'm able to create my own root class that all my other classes can inherit from.
First of all declare the new root object:
#interface RootObject : NSObject
- (void)setRuntimeProperty:(id)runtimeProperty forKey:(id<NSCopying>)key;
- (id)runtimePropertyForKey:(id)key;
#end
With the corresponding implementation:
#import "RootObject.h"
#interface RootObject ()
#property (readwrite) NSMutableDictionary *runtimeProperties;
#end
#implementation RootObject
#synthesize runtimeProperties = _runtimeProperties;
- (id)init {
self = [super init];
if (self)
{
_runtimeProperties = [[NSMutableDictionary alloc] initWithCapacity:1];
}
return self;
}
- (void)dealloc {
[_runtimeProperties release];
_runtimeProperties = nil;
[super dealloc];
}
- (id)runtimePropertyForKey:(id)key {
return [self.runtimeProperties objectForKey:key];
}
- (void)setRuntimeProperty:(id)runtimeProperty forKey:(id<NSCopying>)key {
if (key)
{
if (runtimeProperty)
{
[self.runtimeProperties setObject:runtimeProperty forKey:key];
}
else
{
[self.runtimeProperties removeObjectForKey:key];
}
}
}
#end
By using this RootObject instead of NSObject it should be very easy to add a "property" to a category on a class. Consider having some class MyClass
#interface MyClass : RootObject
// some interface here
#end
When implementing a special behavior on top of this class you are now able to add a property like this:
#interface MyClass (specialBehavior)
#property (nonatomic, retain) NSString *name;
#property (nonatomic, copy) NSDate *birthday;
#end
With corresponding implementation:
#implementation MyClass (specialBehavior)
#dynamic name;
- (NSString *)name {
return [self runtimePropertyForKey:#"name"];
}
- (void)setName:(NSString *)name {
[self setRuntimeProperty:name forKey:#"name"];
}
#dynamic birthday;
- (NSDate *)birthday {
return [self runtimePropertyForKey:#"birthday"];
}
- (void)setBirthday:(NSDate *)birthday {
[self setRuntimeProperty:[birthday copy] forKey:#"birthday"];
}
#end
Such an implementation could KVO compatible as well by just adding the necessary calls in the setter method.
Very straight forward, but I'm wondering whether I missed something important? (E.g. very very bad runtime performance having many such declared properties or using many of these objects)
This is effectively the same as objc_setAssociatedObject and objc_getAssociatedObject, which do release memory when the object is deallocated (depending on the association type). I would guess they also have much lower overhead than your suggested code.
I am trying to create my first test app in IOs and everything I do gets me that error. I am using xcode 4.4.
The app is very simple. It has a button, and When I press it, a label and an imageview must appear.
My whole code is this:
ViewController.h
//
// ViewController.h
// helloWorld_04
//
//
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController{
IBOutlet UILabel *label;
IBOutlet UIImageView *Kant;
}
#property (nonatomic, retain) IBOutlet UILabel *label;
#property (nonatomic, retain) IBOutlet UIImageView *Kant;
- (IBAction)buttonGuess:(id)sender;
#end
and my implementation file:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize label,Kant;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)dealloc {
[label release];
[Kant release];
[super dealloc];
}
- (IBAction)buttonGuess:(id)sender {
label.text=#"Hello World i am back!";
UIImage *imageSource=[UIImage imageNamed:#"kantStair.png"];
Kant.image=imageSource;
}
#end
My error log is this:
2012-08-23 13:38:50.030 helloWorld_04[537:c07] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<ViewController 0x6a5e1f0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key image.'
*** First throw call stack:
(0x14b2022 0xeb2cd6 0x14b1ee1 0x9c3022 0x934f6b 0x934edb 0x94fd50 0x23771a 0x14b3dea 0x141d7f1 0x23626e 0xdc1fc 0xdc779 0xdc99b 0x3b401 0x3b670 0x3b836 0x4272a 0x2d1b 0x13386 0x14274 0x23183 0x23c38 0x17634 0x139cef5 0x1486195 0x13eaff2 0x13e98da 0x13e8d84 0x13e8c9b 0x13c65 0x15626 0x2a22 0x2995)
terminate called throwing an exception(lldb)
and it gets me that signal in that line:
//
// main.m
// helloWorld_04
//
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
I have read several answers here but not found sollution to my problem, that why I made it a new question. I thought that it may be a problem with the connection so what I did on my own was to "darg and drop" my label and my image to "file's owner" but still getting the error.
Looking at your error message, it looks like you have something defined as image in Interface Builder, but doesn't exist. E.g., maybe you have something like:
But you don't have a image property. Did you have one once upon a time, perhaps having renamed it to Kant? If you have something like this defined in Interface Builder, delete it (by tapping on the "x" next to the outlet that I've highlighted) and then link it up again to your new control.
Update:
You should definitely fix your bug above, and hopefully the above observation helps you find it. There is not a bug in your code, but rather the problem undoubtedly rests with your Interface Builder linkages.
But, having said that, if you're a new programmer, I hope you don't mind some unsolicited stylistic observations. Clearly, given that it is a matter of style, these can be debated, but I think these all represent either established or emerging iOS coding standards. Anyway, I might suggest that in the future:
Like David H suggested, you should use lower case variable names.
You probably should have #synthesize statements that either say #synthesize label = _label, or, if you're using Xcode 4.4 or later, just omit the #synthesize statement altogether. (I know that Interface Builder can generate a simple #synthesize statement for you, but it really is best practice to #synthesize with a unique instance variable name so you don't accidentally confuse instance variables with properties.)
You should reference your instance variables in init and dealloc methods (i.e. the variable name with the leading underscore) and elsewhere use the property (with the leading self.), as noted by Born Survivor.
You probably should omit the instance variables and let the #synthesize statement do these for you (so that if you make a typo, you don't accidentally end up with two instance variables).
Thus your code would then become:
// ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
// note, no braces with instance variables defined
// once upon a time that was recommended by Apple, but no longer
// just let the following #property statements and the subsequent
// #synthesize statement generate the instance variables for you.
#property (retain, nonatomic) IBOutlet UIImageView *kant; // note the lower case "k"
#property (retain, nonatomic) IBOutlet UILabel *label;
- (IBAction)buttonGuess:(id)sender;
#end
and
// ViewController.m
#import "ViewController.h"
#implementation ViewController
#synthesize label = _label; // note the #synthesize statement let's us define what the instance variable name should be, _label in this case
#synthesize kant = _kant;
- (void)viewDidUnload
{
[self setKant:nil];
[self setLabel:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)dealloc {
[_kant release]; // note I'm now using the instance variables that begin with the underscore
[_label release];
[super dealloc];
}
- (IBAction)buttonGuess:(id)sender
{
self.label.text = #"Hello World i am back!"; // note, I'm using the properties with the preceding "self."
UIImage *imageSource = [UIImage imageNamed:#"kantStair.png"];
self.kant.image = imageSource;
}
#end
Its important in ObjectiveC to always name your variables with a lower case letter - because when you synthesize a variable like "foo" you get "-(id)foo;// the getter" and "-(void)setFoo:(id)val;//the setter". See how the setter uses a capital letter. So first thing you should do is rename 'Kant' to 'kant'. [by convention only Classes have initial capital letters, so you help others like me read your code by following the conventions.]
So first thing you do is change 'Kant' to 'kant', and then go back to the Interface builder view and re-wire the newly named variable to the UIImageView.
If that does not fix the problem, you have iswired 'kant' or there is some other oddity going on - add this line of code right before you set the image:
NSLog(#"kant has class %#", NSStringFromClass([kant class]) );
and lets see what it really is.
I am new to iPhone development, I have a program that has 7 UITextFields visableenter code here. When the user picks a number on the UIPicker View (1-5) that many UITextFields become hidden and unusable. That program works well. I want to have the same number that was picked from that .m file and transfered to another .m file so that 1-5 UITextFields are hidden and unusable. If it matters, the first .m file is abc.m and the second one is bca.m
if it matters I use [textfield sethidden= YES]
Thanks
You need to keep references to all those objects in the class, and define properties to them so that you can refer to them in the second .m file.
So assuming you have a classes, abc.m
#interface abc {
UITextField *text1;
}
#property (nonatomic, retain) UITextField *text1;
#end
#implementation abc
#synthesize text1;
- (id) init {
if (self = [super init]) {
text1 = [[UITextField alloc] initWithFrame:CGRectMake(0,0,150,10)];
}
return self;
}
- (void)dealloc {
[text1 release];
[super dealloc];
}
Then you can use the text1 property to refer to that text field, given that you have instantiated the object in the second class, or hold a reference to it.
[[MyClass alloc] initWithFrame: CGRectZero andSomeString: #"Hello World!"];
MyClass
- (id)initWithFrame:(CGRect)frame andSomeString:(NSString*)aString
{
if (self = [super initWithFrame:frame])
{
someString = aString;
}
return self;
}
You could try making a BOOL or several BOOL variables and set it equal to YES or NO then put that into your text fields.
BOOL isVisible = YES;
[textfield setHidden:isVisible];
and then if you use a pushViewController you can set the isVisible from bca.m equal to the isVisible in abc.m
viewController.isVisible = isVisible;