I'm new to objective-c, so please forgive me if the words are not precise.
I'm trying to transfer data between class files, my code:
in HomeViewController.h file:
#import <Cocoa/Cocoa.h>
#import "TimeInputFormatWrongPromptViewController.h"
#interface HomeViewController : NSViewController
#property NSTextField *wrongMessageBox;
#end
in HomeViewController.m file:
#import "HomeViewController.h"
#implementation HomeViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_wrongMessageBox = ((TimeInputFormatWrongPromptViewController*)NSApp.windows[0].contentViewController).wrongMessagesBox; //error here
}
#end
in TimeInputFormatWrongPromptViewController.h file:
#import <Cocoa/Cocoa.h>
#interface TimeInputFormatWrongPromptViewController : NSViewController
#property (weak) IBOutlet NSTextField *wrongMessagesBox;
#end
When I write the wrong code, the main window has nothing. When I removed the error code, the main window showed the controls I put in.
And when I write the error code, an error will be reported when the main window is displayed:
2022-10-25 19:46:34.947503+0800 xxxx[8622:607549] -[HomeViewController wrongMessagesBox]: unrecognized selector sent to instance 0x6000014b4000
2022-10-25 19:46:34.947847+0800 xxxx[8622:607549] Failed to set (contentViewController) user defined inspected property on (NSWindow): -[HomeViewController wrongMessagesBox]: unrecognized selector sent to instance 0x6000014b4000
Can anyone tell me how to fix it?
Thanks in advance
Related
The original question remains below this update:
So further research indicates that my
"...missing setter or instance variable"
log messages are due to an unhinged .xib.
I originally thought that might be the case which is why I went through the process of re-connecting the outlets and properties in the graphic interface builder, but that seems to have been insufficient to repair the connections.
I restored the outlets as properties rather than iVars and reconnected again, still to no avail. So I'm in the process of remaking the .xib's from scratch. Stay tuned for the results.
Original question follows:
Having declared and synthesized properties in parent and sheet classes, and attempted therein to access the properties by their respective class.property names, Xcode rejects the code.
I posted a similar question recently and deleted it after being told there was not enough info to make a response, so I include here below a mini-app which shows how the relevant setup was in the real app of over 2000 lines of Objective-C, which built and ran properly before I attempted to add the Parent / Sheet properties feature.
I've indicated the compiler error messages with a prefix of ////. When I comment out the erroneous lines, the app with its .xib's builds and runs, dysfunctionally of course.
ParentClass.h
// ParentClass stuff belongs in the original main window controller
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#interface ParentClass : NSObject
{
IBOutlet NSTextField * messageTextField;
IBOutlet NSButton * proceedButton;
}
#property (assign) IBOutlet NSWindow * window;
#property (strong) NSMutableString * parentPropInfo;
- (IBAction) awakeFromNib;
- (IBAction) doCreate:(id)sender;
#end
ParentClass.m
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import "ParentDelegate.h"
#import "ParentClass.h"
#import "SheetClass.h"
#implementation ParentClass
ParentDelegate * MyDelegate; // only confirms termination requests
NSWindowController * SheetController;
#synthesize parentPropInfo;
- (IBAction)awakeFromNib {
MyDelegate = [NSApplication sharedApplication].delegate;
MyDelegate.ParentController = self; // BTW, this property assignment works!
SheetController = [[SheetClass alloc] initWithWindowNibName: #"SheetClass"];
messageTextField.stringValue = #"Click Proceed button";
}
- (IBAction)doProceed*emphasized text*:(id)sender {
parentPropInfo = #"Hello!".mutableCopy; // to be read by the sheet
[NSApp runModalForWindow:SheetController.window];
// Sheet is active now until it issues stopModal, then:
messageTextField.stringValue = SheetController.sheetPropInfo; // set by the sheet
////above gets ERROR "Property sheetPropInfo not found on object of type 'NSWindowController *'"
messageTextField.stringValue = SheetController.window.sheetPropInfo;
////above gets ERROR "Property sheetPropInfo not found on object of type 'NSWindow *'"
[NSApp endSheet: SheetController.window];
[SheetController.window orderOut:self];
}
#end
SheetClass.h
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import "ParentClass.h"
#interface SheetClass : NSWindowController
{
IBOutlet NSTextField * propTextField;
IBOutlet NSButton * cancelButton;
}
#property (assign) IBOutlet NSWindow * window;
#property NSMutableString * sheetPropInfo;
- (IBAction)awakeFromNib;
- (IBAction)doCancel:(id)sender;
#end
SheetClass.m
#import "SheetClass.h"
#import "ParentClass.h"
#implementation SheetClass
#synthesize sheetPropInfo;
- (IBAction)awakeFromNib {
propTextField.stringValue = self.window.sheetParent.parentPropInfo; // set by the parent
////above gets ERROR "Property parentPropInfo not found on object of type 'NSWindow *'"
sheetPropInfo = #"Goodbye!".mutableCopy; // to be read by the parent
}
- (IBAction)doCancel:(id)sender {
[NSApp stopModal];
}
#end
I can find nothing in Apple documentation or extensive (three weeks now!) online search to offer any insight as to my abysmal ignorance. I apologize for the overwhelming batch of code needed to illustrate my problem! Where shall I obtain the information I need?
The error messages are perfectly clear. Just read them and think about them. Let's just take the first one. You are saying:
messageTextField.stringValue = SheetController.sheetPropInfo;
...and getting this response from the compiler:
// Property sheetPropInfo not found on object of type 'NSWindowController *'
Well, think about the expression SheetController.sheetPropInfo and why the compiler cannot make sense of it. You have declared SheetController as follows:
NSWindowController * SheetController;
So that is all the compiler knows: SheetController is an NSWindowController. Well, sure enough, just as the compiler says, sheetPropInfo is not a property of NSWindowController. It is a property of SheetClass (which is not the same as NSWindowController; it is a subclass of NSWindowController).
If you know that SheetController is in fact a SheetClass instance, you need to tell the compiler that fact. You must either declare SheetController as a SheetClass or cast it down from an NSWindowController to a SheetClass.
There are many questions about accessing 'private' (I hear technically there is no such thing as a private method in Obj-C) messages in Obj-C. And there are many questions addressing No visible #interface for SomeClass declares the the selector 'SomeMethod'. However, there is not one that addressed both.
So here is some code.
Example.h
#import <Cocoa/Cocoa.h>
#interface Example : NSView
#end
Example.mm
#import "Example.h"
#interface Example()
- (void) printWordOne:(NSString*) firstWorld wordTwo:(NSString*) secondWord;
#end
#implementation Example
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// Drawing code here.
}
- (void) printWordOne:(NSString*) firstWorld wordTwo:(NSString*) secondWord{
NSLog(#"The two words are %# %#", firstWorld, secondWord);
}
#end
ViewController.h
#import <Cocoa/Cocoa.h>
#import "Example.h"
#interface ViewController : NSViewController{
IBOutlet Example *example;
}
#end
The IBOutlet has been connected in storyboard.
ViewController.mm
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[example printWordOne:#"Hello" wordTwo: #"World"];
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
// Update the view, if already loaded.
}
#end
The issue I am having is with this method call.
[example printWordOne:#"Hello" wordTwo: #"World"];
The error is No visible #interface for 'Example' declares the selector 'printWordOne:wordTwo'
I need a way to call that function without declaring it in the Example.h file. If I #import Example.mm in my ViewController.mm file I get the following:
duplicate symbol _OBJC_CLASS_$_Example in:
/path/Example.o
/path/ViewController.o
duplicate symbol _OBJC_METACLASS_$_Example in:
/path/Example.o
/path/ViewController.o
ld: 2 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I know using class_copyMethodList I can get the method list and list that method from ViewController.mm. But again is there anyway to execute the method.
Any help would be greatly appreciated.
You can simply declare category to Example class with private method declaration inside your ViewController.mm:
#import "ViewController.h"
#interface Example()
- (void) printWordOne:(NSString*) firstWorld wordTwo:(NSString*) secondWord;
#end
#implementation ViewController
// ...
#end
I'm having trouble calling an external method from a NSTextField Subclass. I have a NSTextField subclass that I'm monitoring text with and when textDidChange I'm calling an external method that is of a NSObject class. For some reason my method doesn't get called. I'm hoping someone could explain why. My code is below. Thanks.
EDIT: Fixed code to what drewag suggested.
MyTextField.h
#import <Cocoa/Cocoa.h>
#class ObjectController;
#interface MyTextField : NSTextField <NSTextFieldDelegate> {
ObjectController *objectController;
}
#property (strong, nonatomic) ObjectController *objectController;
#end
MyTextField.m
#import "MyTextField.h"
#import "ObjectController.h"
#implementation MyTextField
#synthesize objectController;
- (void)textDidChange:(NSNotification *)notification{
[objectController methodFromOtherClass];
}
#end
ObjectController.h
#import <Foundation/Foundation.h>
#interface ObjectController : NSObject {
}
- (void)methodFromOtherClass;
#end
ObjectController.m
#import "ObjectController.h"
#implementation ObjectController
- (void) methodFromOtherClass {
NSLog(#"Testing");
}
There are two likely scenarios causing this issue:
objectController is nil when textDidChange: is called
textDidChange: is not actually being called because you didn't connect it up correctly.
I don't think anyone can help you beyond that since you did not post your connection code nor where you are setting objectController.
Probably forgot to assign the delegate to self or whatever object that implements the textDidChange? Happens to me a lot.
I fixed the issue by creating an instance of ObjectController instead of the above process.
ObjectController *objectController = [ObjectController new];
[objectController methodFromOtherClass];
Hi I have searched and search and then I have decided to post it here - this question may be silly to you but it costs me already one day:(
So I am trying to use the XYPieChart to draw some pie charts, here some some codes from XYPieChart:
XYPieChart.h
#class XYPieChart;
#protocol XYPieChartDataSource <NSObject>
#required
- (NSUInteger)numberOfSlicesInPieChart:(XYPieChart *)pieChart;
- (CGFloat)pieChart:(XYPieChart *)pieChart valueForSliceAtIndex:(NSUInteger)index;
#optional
- (UIColor *)pieChart:(XYPieChart *)pieChart colorForSliceAtIndex:(NSUInteger)index;
- (NSString *)pieChart:(XYPieChart *)pieChart textForSliceAtIndex:(NSUInteger)index;
#end
#protocol XYPieChartDelegate <NSObject>
#optional
- (void)pieChart:(XYPieChart *)pieChart willSelectSliceAtIndex:(NSUInteger)index;
- (void)pieChart:(XYPieChart *)pieChart didSelectSliceAtIndex:(NSUInteger)index;
- (void)pieChart:(XYPieChart *)pieChart willDeselectSliceAtIndex:(NSUInteger)index;
- (void)pieChart:(XYPieChart *)pieChart didDeselectSliceAtIndex:(NSUInteger)index;
#end
XYPieChart.m
#synthesize dataSource = _dataSource;
#synthesize delegate = _delegate;
And then in my own view controller XYPieChartViewTestViewController.h
#import <UIKit/UIKit.h>
#import "XYPieChart.h"
#interface XYPieChartViewTestViewController : UIViewController <XYPieChartDelegate, XYPieChartDataSource>
#property (weak, nonatomic) IBOutlet XYPieChart *MyPieCharts;
#end
And XYPieChartViewTestViewController.m
#import "XYPieChartViewTestViewController.h"
#interface XYPieChartViewTestViewController ()
#end
#implementation XYPieChartViewTestViewController
#synthesize MyPieCharts = _MyPieCharts;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[_MyPieCharts setDelegate:self];
}
But when executing [_MyPieCharts setDelegate:self];, there is a dump:
2012-10-16 10:33:53.100 XYPieChartViewTest[3859:11303] -[UIView setDelegate:]: unrecognized selector sent to instance 0x9040680
* First throw call stack:
libc++abi.dylib: terminate called throwing an exception
If I put a breakpoint at the line "[_MyPieCharts setDelegate:self];", and PO self._MyPieCharts.delegate, it says:
po self.MyPieCharts.delegate
error: Execution was interrupted, reason: Attempted to dereference an invalid ObjC Object or send it an unrecognized selector.
The process has been returned to the state before execution.
I have uploaded the project here since I cannot post screen shots.
Does this mean that self.MyPieCharts.delegate is not initialized? Do you have any idea what should I do?
Thanks a lot!
It seems like MyPieCharts isn't connected in Interface Builder.
Try to set the delegate to :
[_MyPieCharts setDelegate:XYPieChartDelegate];
i have two views with view1 calling view2. i need to pass data from view2 back to view1. so i am attempting to set up a delegate. here's what i got in view controller 2:
.h file
#protocol addEventDelegate <NSObject>
-(void) setAddedEventFlag:(BOOL) hasAddedEvent;
#end
#interface AddEventViewController : UIViewController <UITextFieldDelegate, UITextViewDelegate, UIPickerViewDelegate, UIPickerViewDelegate>
#property (weak, nonatomic) id delegate; //changed from strong to weak
i then #synthesize delegate in the .m file
when try to include the addEventDelegate for the first view controller, xcode can not find it:
.h file
#import "AddEventViewController.h"
#interface FieldReportViewController : UIViewController <UITextFieldDelegate,
UITextViewDelegate, UIPickerViewDelegate, UIPickerViewDelegate, addEventDelegate>
i get the error: "Cannot find protocol declaration for 'addEventDelegate'".
what is wrong?
EDIT:
//code
ERRORS:
Make sure your spelling is correct.
Make sure that AddEventViewController.h/.m are added to the project.
Other than that, what you have is fine.
Edit
Something else I would suggest is to rename your delegate, perhaps there is a naming conflict. Although I haven't seen any issues with 'add' and 'set', but I've seen issues in the past when prefixing with, say, 'new'.
Also, clean your project, and rebuild and see if that helps.
There could be a situation if you have multiple targets in your project, and possibly only added AddEventViewController.h/m to one of them, and you are building/debugging a different target.
Here's the correct way to define a protocol
#protocol addEventDelegate; // forward declaration for delegate property
#interface AddEventViewController : UIViewController <UITextFieldDelegate, UITextViewDelegate, UIPickerViewDelegate, UIPickerViewDelegate>
{
id <addEventDelegate> *delegate
}
#property (weak, nonatomic) id <addEventDelegate> *delegate;
#end // interface
#protocol addEventDelegate <NSObject>
// #optional // if you want to make it optional
-(void) setAddedEventFlag:(BOOL) hasAddedEvent;
#end // protocol
Solved the issue. i had an #import loop. I was #importing all my classes in my .h files. i changed to #Class in .h file and moved the #import's to the .m files and works like a charm now.
You can import addEventDelegate in FieldReportViewController.m file
#interface FieldReportViewController ()<AddEventDelegate>
#end
This one is working in my app