Here is a case where I am passing some parameters to a method, and then assigning the parameter values to local ivars and properties:
- (void) assignOwnerView:(UIView*)oView andPosition:(menuPosition)position withTopView:(UIView*)topView {
self.topView = topView;
self.ownerView = oView;
self.position = position;
<< --- other code --- >>
}
The interface for these properties is this (UPDATED with SYNTHESIS)
#interface MenuVC (){
UIView *ownerView_;
UIView *topView_;
menuPosition position_;
}
#property (nonatomic, retain) UIView *ownerView;
#property (nonatomic, retain) UIView *topView;
#property (assign) menuPosition position;
#end
#implementation MenuVC
#synthesize list, menuDelegate;
#synthesize ownerView = ownerView_;
#synthesize topView = topView_;
#synthesize position = position_;
- (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)style
{...
The enum is defined here:
typedef enum {
above,
below,
centered
} menuPosition;
After executing the three assignments, at a breakpoint in the debugger, the values are as shown below:
The received parameter values look okay, but the assigned values of the ivars ownerView_ and position_ are not right. On the other hand, topView is okay.
The same thing happened when I assigned directly to ivars rather than properties.
I started seeing this problem when I upgraded to Lion (10.7.3) and XCode 4.3.1. It was working okay before then. I see this at other spots in my app, and I don't see any pattern to it yet.
ARC is not being used.
I reported this problem before, but didn't get an answer. In this case, the problem description is a simpler. That might make it easier to see what the problem is.
UPDATE -- header file added
#import <UIKit/UIKit.h>
#class MenuVC;
#protocol menuDelegateProtocol
typedef enum {
above,
below,
centered
} menuPosition;
- (void) didSelectItemFromMenu:(MenuVC *)menu atIndex:(NSUInteger) index;
#end
#interface MenuVC : UITableViewController {
NSArray *list;
float extendedHeight;
id<menuDelegateProtocol> menuDelegate;
}
#property (nonatomic, retain) NSArray *list;
#property (nonatomic, assign) id<menuDelegateProtocol> menuDelegate;
- (id) initWithFrame:(CGRect)frame style:(UITableViewStyle)style;
- (void) hide;
- (void) unhide;
- (void) assignOwnerView:(UIView*)oView andPosition:(menuPosition)position withTopView:(UIView*)topView;
#end
You didn't synthesized the properties.
Put:
#synthetize ownerView = ownerView_;
#synthetize topView = topView_;
#synthetize position = position_;
After "#implementation MenuVC".
I changed the debugger to GDB from LLDB. This seems to be a problem with LLDB. I'm not seeing this now.
Related
I have a window with a large NSTextFeildCell, where text can be modified. Upon clicking a button another window appears where the text from the original window can be used some how. The issue I am having is when I attempt to retrieve that text the log spits out...
" -[NSTextView stringValue]: unrecognized selector sent to instance 0x100151860"
Fallowed by a long trace...
I have tried to solve this several different ways but with no luck.
currently,
First window controller
.h
#import <Cocoa/Cocoa.h>
#class NextWindowController;
#interface TextViewWindowController : NSWindowController
#property (nonatomic, weak) NextWindowController *NextWindow;
#property (nonatomic, weak) IBOutlet NSTextFieldCell *txtTextView;
- (IBAction)btnClicked:(id)sender;
- (NSString*)getText;
#end
.m
#import "TextViewWindowController.h"
#import "NextWindowController.h"
#implementation TextViewWindowController
#synthesize NextWindow;
- (IBAction)btnClicked:(id)sender{
[NextWindow setCallingWindow:self];
[NextWindow showWindow:self];
}
- (NSString*)getText{
return [_txtTextView stringValue];// there is a problem with the view...
}
#end
Next Window controller
.h
#import <Cocoa/Cocoa.h>
#class TextViewWindowController;
#interface NextWindowController : NSWindowController{
NSMutableString* str;
}
#property (nonatomic, weak) TextViewWindowController *callingWindow;
#end
.m
#import "NextWindowController.h"
#import "TextViewWindowController.h"
#implementation NextWindowController
#synthesize callingWindow;
- (IBAction)btnEnterClicked:(id)sender{
[str setString:callingWindow.txtTextView.stringValue];
}
- (id)initWithWindow:(NSWindow *)window{
self = [super initWithWindow:window];
if (self) {
str = [[NSMutableString alloc] init];
}
return self;
}
#end
I have also tried str = [callingWindow getText] with the same result.
Any help would be very appreciated!
It's not super intuitive to figure out from Apple's documentation, but to get the raw string value of a NSTextView (which inherits from NSText), just use:
[_txtTextView string];
And since you're using properties, it might be smarter to use the accessor in your function, like this:
- (NSString*)getText{
return [self.txtTextView string];
}
So long story short, I have some odd bugs in some code I'm messing with and it turns out that it comes from an object being identified as the wrong class.
Here is my code, with the NSLog statement I put before anything touches the object... I can't figure out why it's showing as the wrong class.
Photo.h
#interface Photo : NSObject
{
}
#property (nonatomic, retain) UIImage *image;
#property (nonatomic, retain) IBOutlet NSString *descr;
#end
Photo.m
#implementation Photo
#synthesize image;
#synthesize descr;
#end
CameraViewController.h
#include "Photo.h"
#interface CameraViewController : UIViewController <UIImagePickerControllerDelegate>
{
IBOutlet UIImageView *imageView;
}
#property (nonatomic, retain) Photo *photo;
-(void)takePhoto;
-(void)resetImage;
#end
and finally...
CameraViewController.m
#import "Photo.h"
....
#implementation CameraViewController
#synthesize photo;
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"%#", NSStringFromClass([_photo class]));
// Do any additional setup after loading the view.
}
This prints out:
UIImageView
I would expect it to print out
Photo
or at the very least
NSObject
Am I missing something???
Sending an object the class message retrieves that object's dynamic type. The object must be assigned prior to querying it for its class. In other words, declaring a property as Photo* is not sufficient for its class to return Photo: you must also assign it an instance of Photo or one of its subclasses. In the later case, the result of sending class message will be different (i.e. the Class of the subclass will be returned).
I am interested in setting a property as a subclass, say Person, of NSManagedObject in a view controller that will specify an instance of person so that I will be able to update with methods in the controller. can I do it like this?
// Viewcontroller.h
#implementation
#property (nonatomic, retain) Person* currentPerson;
#end
// ViewController.m
#implementation
#dynamic currentPerson;
-(void) doSomethingToCurrentPerson {
currentPerson.SomeAtrribute=somevalue;
}
#end
It seems like if this were not a valid way to go, it would also be possible to set a unique identifier and then store CurrentPersonUniqueID as a property and use KVC. Is there a way to get something along the lines of what I posted to work, or am I better off with something closer to the KVC approach, or something totally different?
This code won't work until you replace #dynamic by #synthesize. #dynamic tells the compiler that -setCurrentPerson: and -currentPerson are implemented somewhere else, which is not the case.
So #synthesize currentPerson will create the currentPerson's getter/setter automatically. It won't have anything to do with the fact that Person is a NSManagedObject.
Also, either you can't access to currentPerson directly with this name, you have to use its getter:
self.currentPerson.attribute = something;
// or
[self currentPerson].attribute = something;
Correct code:
// Viewcontroller.h
#implementation
#property (nonatomic, retain) Person* currentPerson;
#end
// ViewController.m
#implementation
#synthesize currentPerson;
-(void) doSomethingToCurrentPerson {
self.currentPerson.SomeAtrribute = somevalue;
}
#end
Right before my model class sends the variable stringToDisplay, NSLog shows me that it has a value. But when I try to use it in my ViewController, I just get (null). Any thoughts about what I'm doing wrong?
(The good news is that, while working on this, I had sort of a breakthrough in understanding how models and controllers relate to each other. I'm still a complete newbie, but I don't feel quite as lost as I did.)
Here's what I think is the relevant code:
CalculatorBrain.h
#import <Foundation/Foundation.h>
#interface CalculatorBrain : NSObject
#property (nonatomic) NSMutableString *stringToAdd;
#property (nonatomic,strong) NSString *stringForDisplay;
- (double)performOperation:(NSString *)operation withArray:(NSMutableArray *)particularStackYouNeedToPopOff;
CalculatorBrain.m
#implementation CalculatorBrain
#synthesize stringToAdd = _stringToAdd;
#synthesize stringForDisplay = _stringForDisplay;
#synthesize whatHappenedSinceLastClear = _whatHappenedSinceLastClear;
- (double)performOperation:(NSString *)operation withArray:(NSMutableArray *)particularStackYouNeedToPopOff
{
<long code that I think doesn't matter because this NSLog produces exactly what I want it to:>
NSLog(#"%#",stringForDisplay);
return result;
}
CalculatorViewController.h
#import <UIKit/UIKit.h>
#interface CalculatorViewController : UIViewController
#property (nonatomic) NSArray *arrayOfDictionaries;
#property (nonatomic) NSDictionary *dictionary;
#property (weak, nonatomic) IBOutlet UILabel *variablesUsed;
#property (nonatomic, strong) NSString *operation;
#end
CalculatorViewController.m
#import "CalculatorViewController.h"
#import "CalculatorBrain.h"
#interface CalculatorViewController ()
#property (nonatomic,strong) CalculatorBrain *brain;
#end
#implementation CalculatorViewController
#synthesize display = _display;
#synthesize history = _history;
#synthesize brain = _brain;
#synthesize operation = _operation;
- (IBAction)operationPressed:(UIButton *)sender
{
NSString *otherString=[self.brain stringForDisplay];
if (self.userIsEnteringNumber) [self enterPressed];
NSString *operation = sender.currentTitle;
double result = [self.brain performOperation:operation withArray:[self.brain whatHappenedSinceLastClear]];
self.display.text = [NSString stringWithFormat:#"%g",result];
self.history.text = otherString;
NSLog(#"%#",otherString);
}
And the NSLog in that last line of code give me (null).
Any thoughts?
Maybe I'm missing something but your property is declared in the class extension of CalculatorBrain so nobody outside CalculatorBrain.m knows about this property.
So if you want to expose this property to other objects, you will have to declare it in CalculatorBrain.h instead.
Oh - your declaration of the property whatHappenedSinceLastClear isn't exposed to other classes that import CalculatorBrain.h because you put the property declaration in an interface extension in the .m file, which other classes will not see.
To make it publicly accessible move the #property line for whatHappenedSinceLastClear to CalculatorBrain.h, not the .m file.
I can guess that problem lies in the way you assign your stringForDisplay, eg.:
if you use something like
stringForDisplay_ = anotherString;
setter for property doesn't fire, so you have to retain your variable yourself otherwise it'll live just until your method finishes;
If so - use property setters, eg.:
self.stringForDisplay = anotherString;
that way ARC will do all the memory management.
It really depends how you set stringForDisplay inside the performOperation:withArray: method.
for a blind guess, try using
NSString *otherString = self.brain.stringForDisplay;
after this line
double result = [self.brain performOperation:operation withArray:[self.brain whatHappenedSinceLastClear]];
I am unsure why this code will not work. When I click a button (action: buttonclick) it should change the two text boxes' (MyTextLabel and MyTextLabel2) text increment value "r" by one. Here is the code:
MainView.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#interface MainView : UIView {
IBOutlet UIButton *MyButton;
IBOutlet UILabel *MyTextLabel;
IBOutlet UILabel *MyTextLabel2;
}
#property (nonatomic, retain) UIButton *MyButton;
#property (nonatomic, retain) UILabel *MyTextLabel;
#property (nonatomic, retain) UILabel *MyTextLabel2;
- (IBAction)buttonclick;
#end
MainView.m:
#import "MainView.h"
#include <stdlib.h>
#include <libc.h>
#implementation MainView
#synthesize MyButton, MyTextLabel, MyTextLabel2;
int r;
- (IBAction)buttonclick {
r++
if(r < 50) {
MyTextLabel.text = #"< 50";
}
else {
MyTextLabel2.text = #"=> 50";
}
}
#end
I have a feeling something's wrong with the way you're using int r. Try putting static int r; at the top of the #interface line in MainView.h and also add, under the - (IBAction)buttonclick; line:
+(void) initialize;
Then remove int r; from MainView.m. Then in MainView.m add:
+(void) initialize {
count = 0;
}
I see two issues:
You can't declare int r where you have it. You should declare it in your interface's variable block (where you declare your button and labels or outside a method) or in the method definition.
The line with r++ isn't ended with a semi-colon.
You don't say in your question what, exactly, isn't working the way you expect it. My guess is going to be that your outlets aren't actually connected properly. You might want to add a log statement to buttonClick like this:
NSLog(#"button click called! MyTextLabel is %#", MyTextLabel);
The point being, mostly, to be sure it isn't nil.
In Objective-C the names of variables and properties must start with a lowercase letter to conform to the Key-Value Coding (KVC) protocol (always myButton, never MyButton). The #synthesize directive relies on this to generate the setters and getters. Thus, for myButton #synthesize will generate -(void)setMyButton:(UIButton *)button and -(UIButton *)myButton.
So, do make MyButton and its colleagues lowercase and see if it helps.
Action methods always have a sender argument, so your -buttonClick: method should be declared like this:
-(IBAction) buttonClick: (id)sender {
}