Access IBOutlet from other class (ObjC) - objective-c

I've googled around and found some answers but I didn't get any of them to work. I have one NSObject with the class "A" and a second class "B" without an NSObject. In class "A" are my IBOutlets defined and I can't seem to figure out how to access those outlets from class "B"...
I've found answered questions like http://forums.macrumors.com/archive/index.php/t-662717.html But they're confusing.
Any help would be greatly appreciated!
Simplified Version of the Code:
aClass.h:
#import <Cocoa/Cocoa.h>
#interface aClass : NSObject {
IBOutlet NSTextField *textField;
}
#end
aClass.m:
#import "aClass.h"
#implementation aClass
// Code doesn't matter
#end
bClass.h:
#import <Cocoa/Cocoa.h>
#interface bClass : NSObject {
}
#end
bClass.m:
#import "aClass.h"
#import "bClass.h"
#implementation bClass
[textField setStringValue: #"foo"];
#end

When you write:
I have one NSObject with the class
"A" and a second class "B" without an
NSObject.
It tells me that you don't have your head around the basic concepts.
Read through Apple's objective-C introduction, and the tutorial projects.

The solution is using NSNotificationCenter. Here's a thread telling you how to do it: Send and receive messages through NSNotificationCenter in Objective-C?
Then in the method reacting to the notification, you call a method accessing the Outlet
- (void) receiveTestNotification:(NSNotification *) notification
{
if ([[notification name] isEqualToString:#"TestNotification"])
//NSLog (#"Successfully received the test notification!");
[self performSelectorOnMainThread:#selector(doIt:) withObject:nil waitUntilDone:false];
}
- (void) doIt
{
//testLabel.text = #"muhaha";
}
This worked for me, I hope it does so for you as well.

Related

Delegate from Obj-C into Swift - method is never executed

Before I was using NSNotificationEvents, but as I know I should be using delegate because of 1:1 relations (it will be used only in one place in code).
Basically Im new to objective-C and swift (Im JavaScript guy) and the code that I created after a few hours of reading and checking - it just doesnt work, because self.delegate in not defined.
Im trying to delegate "an event" from objective-C code to swift code. NSNotificationEvents works like charm, but I want to make it with protocols / delegate.
I guess, I just missing how to exactly initialize the delegate protocol.
ProtocolDelegate.h
#import <Foundation/Foundation.h>
#protocol ProtocolDelegate <NSObject>
- (void) delegateMethod: (id)data;
#end
Event.h
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import "ProtocolDelegate.h"
#interface Event : NSObject <RCTBridgeModule, ProtocolDelegate>
#property(nonatomic, weak)id <ProtocolDelegate> delegate;
#end
Event.m
(someMethod is executed from JavaScript React-native code, but it shouldn't be any difference from what I know)
#import "Event.h"
#implementation Event
RCT_EXPORT_MODULE(Events);
RCT_EXPORT_METHOD(someMethod: (NSString*)parameter) {
NSDictionary* data = #{#"parameter": parameter};
NSLog(#"This I can see");
if ([self.delegate respondsToSelector:#selector(delegateMethod:)]) {
NSLog(#"This I can not see");
[self.delegate delegateMethod:data];
}
}
ViewController.swift
class ViewController: UIViewController, ProtocolDelegate {
// Xcode has automatically created this method
func delegateMethod(_ data: Any!) {
os_log("ON AUCTION");
}
}
I want delegateMethod inside ViewController to be executed.
Or maybe I get the whole idea wrong? Objective-C is a bit confising to me.

Call NSObject method from NSTextField Subclass?

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];

No access to global instance (build by factory) on iOS

this is a follow-up question to my last one here: iOS: Initialise object at start of application for all controllers to use .
I have set my application up as follows (ignore the DB Prefix):
DBFactoryClass // Built a DataManaging Object for later use in the app
DBDataModel // Is created by the factory, holds all data & access methods
DBViewControllerA // Will show some of the data that DBDataModel holds
moreViewControllers that will need access to the same DBDataModel Object
i will go step by step through the application, and then post the problem in the end
AppDelegate.h
#import "DBFactoryClass.h"
AppDelegate.m
- (BOOL)...didFinishLaunching...
{
DBFactoryClass *FACTORY = [[DBFactoryClass alloc ]init ];
return YES;
}
DBFactoryClass.h
#import <Foundation/Foundation.h>
#import "DBDataModel.h"
#interface DBFactoryClass : NSObject
#property (strong) DBDataModel *DATAMODEL;
#end
DBFactoryClass.m
#import "DBFactoryClass.h"
#implementation DBFactoryClass
#synthesize DATAMODEL;
-(id)init{
self = [super init];
[self setDATAMODEL:[[DBDataModel alloc]init ]];
return self;
}
#end
ViewControllerA.h
#import <UIKit/UIKit.h>
#import "DBDataModel.h"
#class DBDataModel;
#interface todayViewController : UIViewController
#property (strong)DBDataModel *DATAMODEL;
#property (weak, nonatomic) IBOutlet UILabel *testLabel;
#end
ViewControllerA.m
#import "todayViewController.h"
#implementation todayViewController
#synthesize testLabel;
#synthesize DATAMODEL;
- (void)viewDidLoad
{
todaySpentLabel.text = [[DATAMODEL test]stringValue]; // read testdata
}
#end
DBDataModel.h
#import <Foundation/Foundation.h>
#interface DBDataModel : NSObject
#property (nonatomic, retain) NSNumber* test;
#end
DBDataModel.m
#import "DBDataModel.h"
#implementation DBDataModel
#synthesize test;
-(id)init{
test = [[NSNumber alloc]initWithInt:4]; // only a testvalue
return self;
}
#end
the app builds fine, and starts up but the label stays blank. so either the object does not exist (but i guess this would result in an error message), or something else is wrong with my setup. any thoughts?
Two notes:
Your have a shotgun approach to asking questions: everytime you hit a stumbling block, you ask a question and if the answer does not work immediately, you ask another one. You have to spend some energy in between the questions debugging and poking into the code on your own, otherwise you will depend on the external help forever.
Use the common coding style please. CAPS are reserved for macros.
Now to the code:
- (BOOL) …didFinishLaunching…
{
DBFactoryClass *factory = [[DBFactoryClass alloc] init];
return YES;
}
This simply creates an instance of the DBFactoryClass and then throws it away. In other words, it’s essentially a no-op. Judging by the comments in the previous answer you create the controllers using the Storyboard feature. How are they supposed to receive the reference to the data model? The reference isn’t going to show up by magic, you have to assign it somewhere.
I’m not familiar with the Storyboard feature. The way I would do it is to create the view controllers using separate XIB files, then you can create the controller instances in the Factory class and pass them the needed reference to the model. In the end the application delegate would create the factory, ask it to assemble the main controller and then set it as the root view controller for the window. Just like in my sample project. It’s possible that there’s a way to make it work with storyboards, but as I said, I am not familiar with them.

Getting an error while trying to access property from an extern Controller in Xcode 4.2

In a first controller, I create an instance variable for my model, because I want to edit its content from a controller and then access the same object from another controller.
In the second controller, I get an error when trying to access the object:
Property 'levels' not found on object of type FirstController.
Model.h
#imports....
#property (readwrite,copy) NSMutableString *answersString;
FirstController.h
#import <UIKit/UIKit.h>
#import "Model.h"
#interface FirstController : UIViewController{
// some declarations
}
#property (nonatomic, retain) LevelsCompleted *levels;
#end
FirstController.m
#import "FirstController.h"
#interface FirstController(){
//stuff
}
#end
#implementation FirstController
#synthesize levels;
//stuff
- (IBAction)backButton:(id)sender { // This is the changeAnswerString method
if (levels ==nil) self.levels = [[LevelsCompleted alloc]init];
self.levels.answersString=#"1";
[self dismissModalViewControllerAnimated:NO];
}
#end
SecondController.m
#import "SecondController.h"
#import "FirstController.h"
#interface SecondController(){
//stuff
}
#end
#implementation SecondController
-(void) viewWillAppear:(BOOL)animated{
NSLog(#"%#",FirstController.levels.answersString);
// the line above gives me the error "Property 'levels' not found on object of type FirstController
}
#end
Can someone tell me what I am doing wrong here? I have tried to create a FirstController object in the SecondController.h, but this does not give me the same property and hence I do not get the right value of the NSString I modified in the first view.
levels is a instance variable so you cannot access it without instantiating an object first.
You should do something like
FirstController *controller = [[FirstController alloc] initWithNibName:#"First" bundle:nil];
NSLog(#"%#",controller.levels.answersString);
[controller release]
You cannot access another viewcontroller from current viewcontroller directly. Define Level in AppDelagte method and then you can access it from anywhere.
What about moving/adding the LevelsCompleted *levels property to the secondviewcontroller and fill SecondViewcontroller.levels.answerstring when you use backbutton: in you first controller?
As a advice try NSUSERDEFAULT to access it,.,
By Doing Things As Below you can Achive as You want
Ddeclare NSMutableString As in your viewController Class As Global variable.
1) LevelsCompleted.h Class
#import <UIKit/UIKit.h>
NSMutableString *answersString;// In this way this answersString would accessible through out the Application and No Need to make property & synthesiz answersString .
#interface LevelsCompleted : UIViewController{
}
LevelsCompleted.m Class
//First create that NSMutableString object in its LevelsCompleted.m class
#import"LevelsCompleted.h"
#interface LevelsCompleted
-(void)viewDidLoad{
answersString=[NSMutableString alloc]init];//here created answersString object
}
#end //end of LevelsCompleted
2)FirstController.h class
#import <UIKit/UIKit.h>
extern NSMutableString *answersString;
#interface FirstController : UIViewController{
// some declarations
}
#end
FirstController.m class
#import "FirstController.h"
#implementation FirstController
- (IBAction)backButton:(id)sender {
// Because i have created that answersString Global in LevelsCompleted.h class
//we can directly Access and can set the any string Value to that answersString as Below
answersString=#"1";
[self dismissModalViewControllerAnimated:NO];
}
#end
SecondController.h class
extern NSMutableString *answersString;// please do this carefully fro getting access the answersString instance
#interface SecondController:UIViewController{
//stuff
}
#end
SecondController.m class
#implementation SecondController
-(void) viewWillAppear:(BOOL)animated{
NSLog(#"%#",answersString);//here you may access easily.
}
#end
In above code everything would work because i have done the same thing in my app
just try to catch the concept of extern, global variable .

Problems implementing a protocol

I am developing a game and I have a settings view that is pushed modally. I want if I turn music off in that view, stop the background music. I'm using a protocol (I am using automatic reference counting):
game.h
#import <UIKit/UIKit.h>
#import "AVFoundation/AVFoundation.h"
#import "stackButton.h"
#import "tvr_AppDelegate.h"
#protocol settingsChanger <NSObject>
-(void)changeSettings:(int)soundVal musicSetting:(int)musicVal;
#end
#interface game : UIViewController <UIAlertViewDelegate, settingsChanger>{
...
}
game.m
-(void)changeSettings:(int)soundVal musicSetting:(int)musicVal{
if (musicVal == 1) {
[self playMusic];
}else{
[audioPlayer stop];
}
settings.h
#import <UIKit/UIKit.h>
#protocol settingsChanger;
#interface settings : UIViewController{
id<settingsChanger> settingsDelegate;
}
#property (nonatomic, strong) id<settingsChanger> settingsDelegate;
-(IBAction)updateMusicSetting;
#end
settings.m
-(IBAction)updateMusicSetting{
tvr_AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
if (swMusic.on) {
[delegate updateMusicSetting:1];
[settingsDelegate changeSettings:0 musicSetting:1];
}
else {
[delegate updateMusicSetting:0];
[settingsDelegate changeSettings:0 musicSetting:0];
}
}
My IBAction is triggered by a UISwitch. All goes fine, except that id settingsDelegate references to memory 0x0 and I think that's the my method changeSettings is never called in game.h. What am I missing?.
I would suggest as a good programming practice to name your classes with an uppercase, that is: "Game" instead of "game" and your protocols as well: "SettingsChanger" instead of "settingsChanger". Your method naming conventions seem also to need some improvement, just take 30 minutes time and read Apples "Cocoa Guidelines For Cocoa" link to the "Cocoa Guidelines For Cocoa document"