Very basic question here...
I have 2 classes and I want to keep an NSArray in one class and access it in different class.
Questions.h
#import <Foundation/Foundation.h>
#interface Questions : NSObject
#property NSMutableArray *questions;
-(void) questionMethod;
#end
Questions.m
#import "Questions.h"
#implementation Questions
-(void) questionMethod {
NSArray *questionBank = [4,5,6];
}
#end
ViewController.m
#import "Questions.h"
-(void)generateRandomQuestionOrder {
Questions *questions = [[Questions alloc] init];
}
How do I count the values of questionBank array in generateRandomQuestionOrder method?
Not the best naming convention but take a look at the following example. You declare a public property in the Questions object and access it from the controller after you initialised a new object there. You may consider declaring it readonly and set it to readwrite in the private interface extension.
Questions.h
#import <Foundation/Foundation.h>
#interface Questions : NSObject
#property NSMutableArray *questions;
#end
Questions.m
#import "Questions.h"
#implementation Questions
-(id) init {
if (self = [super init]) {
_questions = #[4,5,6];
}
return self;
}
#end
ViewController.m
#import "Questions.h"
-(void)generateRandomQuestionOrder {
Questions *theQuestions = [[Questions alloc] init];
NSLog(#"%#", [theQuestions.questions description]);
}
Related
Question
How do we hide private class when using it in Objective-C?
For example, as described below
PrivateFilter is the class I want to hide.
CustomFilter is the class I make, which is open.
GPUImageFilter is the class public on Github, which is open, too.
And CustomFilter actully wraps the functionallity of PrivateFilter.
#interface CustomFilter : GPUImageFilter
#end
#interface PrivateFilter : GPUImageFilter
#end
Possible Solutions
So there are two solutions:
Solution 1: Class cluster
Have a look at the example A Composite Object: An Example in the Apple document.
I followed the steps and make the following code.
// CustomFilter.h
#interface CustomFilter : GPUImageFilter
#end
// CustomFilter.m
#interface CustomFilter()
#property (nonatomic, strong) PrivateFilter *privateFilter;
#end
#implementation CustomFilter
- (instancetype)init
{
self = [super init];
if (self) {
_privateFilter = [[PrivateFilter alloc] init];
}
return self;
}
// and then override the most of GPUImageFilter functions...
#end
But somehow it doesn't work, so I try the solution 2.
Solution 2: Init with PrivateFilter
// CustomFilter.h
#interface CustomFilter : GPUImageFilter
#end
// CustomFilter.m
#implementation CustomFilter
- (CustomFilter *)init
{
self = (CustomFilter *)[[PrivateFilter alloc] init];
return self;
}
#end
This works, but it's very strange to use alloc in init.
So I try the solution 3.
Solution 3: factory class method
// CustomFilter.h
#interface CustomFilter : GPUImageFilter
+ (CustomFilter *)filter;
#end
// CustomFilter.m
#implementation CustomFilter
+ (CustomFilter *)filter
{
CustomFilter *filter = (CustomFilter *)[[PrivateFilter alloc] init];
return filter;
}
#end
This works, but it could not be inherited, just like class cluster.
Repeat Question
SO which is the best solution? Or is there other some good solutions?
I think you need protocol, instead of CustomFilter with factory approach. If you need some GPUImageFilter subclass you can make GPUImageFilter<CustomFilter>
//CustomFilter.h
#protocol CustomFilter
...
#end
typedef GPUImageFilter<CustomFilter> CustomFilter;
//PrivateFilter.h
#import "CustomFilter.h"
#interface PrivateFitler: CustomFilter
...
#end
//GPUImageFilter+CustomFilter.h
#interface GPUImageFilter(CustomFilter)
+ (CustomFilter *)filter;
#end
//GPUImageFilter+CustomFilter.m
#import "PrivateFilter.h"
#implementation GPUImageFilter(CustomFilter)
+ (CustomFilter *)filter
{
return [[PrivateFilter alloc] init;
}
#end
With such approach Xcode even give you warnings if you forget to implement some methods.
I want to inherit my base class properties and methods which will be used by my several derived classes. I want these properties and methods to be exactly protected so that they will only be visible in derived class and not to any external class. But it always gives me some errors.
#interface BasePerson : NSObject
#end
#interface BasePerson ()
#property (nonatomic, strong) NSMutableArray<Person*>* savedPersons;
#property (nonatomic) BOOL shouldSavePerson;
#end
#interface DerivedPerson1 : BasePerson
#end
#implementation DerivedPerson1
- (instancetype)init
{
if (self = [super init]) {
self.savedPersons = [NSMutableArray array];
self.shouldSavePerson = NO;
}
return self;
}
It always gives me an error that
Property 'savedPersons' not found on object of type 'DerivedPerson1 *'
Property 'shouldSavePerson' not found on object of type 'DerivedPerson1 *'
How i can make use of inheritance in Objective C, I don't want savedPersons and shouldSavePerson properties to be visible to external classes. I only want them to visible in my base class and all the derived classes.
Any help will be great. Thanks
This is not something that the objectiveC really support. There are some ways though. So lets see.
If you put a property in the source file class extension then it is not exposed and you can not access it in the subclass either.
One way is to put all of the subclasses into the same source file as the base class. This is not a good solution at all as you do want to have separate files for separate classes.
It seems logical to import the BaseClass.m in the SubClass source file but that will produce a linker error saying that you have duplicate symbols.
And the solution:
Separate the extension into a separate header. So you have a MyClass
Header:
#import <Foundation/Foundation.h>
#interface MyClass : NSObject
#end
Source:
#import "MyClass.h"
#import "MyClassProtected.h"
#implementation MyClass
- (void)foo {
self.someProperty = #"Some text from base class";
}
#end
Then you create another header file (only the header) MyClassProtected.h which has the following:
#import "MyClass.h"
#interface MyClass ()
#property (nonatomic, strong) NSString *someProperty;
#end
And the subclass MyClassSubclass
Header:
#import "MyClass.h"
#interface MyClassSubclass : MyClass
#end
And the source:
#import "MyClassSubclass.h"
#import "MyClassProtected.h"
#implementation MyClassSubclass
- (void)foo {
self.someProperty = #"We can set it here as well";
}
#end
So now if the user MyClassSubclass he will not have the access to the protected property which is essentially what you want. But the downside is the user may still import MyClassProtected.h after which he will have the access to the property.
Objective-C doesn't have member access control for methods, but you can emulate it using header files.
BasePerson.h
#interface BasePerson : NSObject
#property (strong,nonatomic) SomeClass *somePublicProperty;
-(void) somePublicMethod;
#end
BasePerson-Private.h
#import "BasePerson.h"
#interface BasePerson ()
#property (nonatomic, strong) NSMutableArray<Person*>* savedPersons;
#property (nonatomic) BOOL shouldSavePerson;
#end
BasePerson.m
#import "BasePerson-Private.h"
...
DerivedPerson1.h
#import "BasePerson-Private.h"
#inteface DerivedPerson1 : BasePerson
...
#end
Now any class that #imports BasePerson.h will only see the public methods. As I said though, this is only emulating access control since if a class #imports *BasePerson-Private.h" they will see the private members; this is just how C/Objective-C is.
We can achieve using #protected access specifier
#interface BasePerson : NSObject {
#protected NSMutableArray *savedPersons;
#protected BOOL shouldSavePerson;
}
DerivedPerson1.m
#implementation DerivedPerson1
- (instancetype)init
{
if (self = [super init]) {
self->savedPersons = [NSMutableArray array];
self->shouldSavePerson = NO;
}
return self;
}
#end
OtherClass.m
#import "OtherClass.h"
#import "BasePerson.h"
#implementation OtherClass
- (void)awakeFromNib {
BasePerson *base = [[BasePerson alloc]init];
base->savedPersons = #[];//Getting Error. Because it is not a subclass.
}
#end
I need to pass a string from a NSObject class to a UIViewController, I understand that the best way is delegation but the delegate method isn't being called. I'm trying to set the UILabel an DieFacesViewController as the selectedOption from TemporarySelection.
A tableview shows the value of CustomOptionStore, once it's tapped passes its value to TemporarySelection and opens the modal view DieFacesViewCountroller which should, at least in my mind, take the label value from TemporarySelection. The reason I created TemporarySelection is because the DieFacesViewController will be used by other classes, not only by CustomOptionStore, and it will need to load the label from all those classes when different tableViews are selected.
I tried to set the delegate as self in both viewDidLoad and viewWillAppear with no luck, I don't understand if the view loads before being able to call the delegate method or if there's something wrong the way I set the method up.
I've been stuck here for two days, this is the first time I post a question so please forgive me if it's a bit confused.
my delegator class TemporarySelection.h is
#import <Foundation/Foundation.h>
#import "CustomOptionsStore.h"
#class DieFacesViewController;
#protocol TemporarySelectionDelegate <NSObject>
-(void)sendSelection;
#end
#interface TemporarySelection : NSObject
#property (nonatomic, weak) id <TemporarySelectionDelegate> delegate;
#property (nonatomic, strong) NSString *selectedOption;
-(void)addSelection: (CustomOptionsStore *) selection;
#end
and my TemporarySelection.m is
#import "TemporarySelection.h"
#implementation TemporarySelection
-(void)addSelection: (CustomOptionsStore *) selection{
self.selectedOption = selection.description;
[self.delegate sendSelection];
}
#end
the delegate class DiewFacesViewController.h is
#import <UIKit/UIKit.h>
#import "SelectedStore.h"
#import "TemporarySelection.h"
#interface DieFacesViewController : UIViewController <TemporarySelectionDelegate>
#property (strong, nonatomic) IBOutlet UILabel *SelectionName;
#end
and the DieFacesViewController.m is
#import "DieFacesViewController.h"
#interface DieFacesViewController ()
#end
#implementation DieFacesViewController
- (void)viewDidLoad {
TemporarySelection *ts = [[TemporarySelection alloc]init];
ts.delegate = self;
[super viewDidLoad];
}
-(void)sendSelection{
TemporarySelection *ts = [[TemporarySelection alloc]init];
self.SelectionName.text = ts.selectedOption;
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
}
You are not setting the delegate object properly.Check the above code
#import "DieFacesViewController.h"
#interface DieFacesViewController ()<TemporarySelectionDelegate>
{
//global object
TemporarySelection *ts;
}
#end
#implementation DieFacesViewController
- (void)viewDidLoad {
ts = [[TemporarySelection alloc]init];
ts.delegate = self;
[super viewDidLoad];
}
-(void)sendSelection{
//Use the object to extract
self.SelectionName.text = ts.selectedOption;
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
}
I've a main class where I want to define two protocols (1 used by a class A, the other by class B) (ios 6.1, xcode 4.6.3 , ARK mode, storyboard project).
According to official syntax, all my code seems to be correct.
But when I try to use the second delegate , nothing work correctly, my 2nd delegate does not respond
**HEADER myProtocols.h**
#import ...
#class myProtocols;
#protocol myProtocol1 <NSObject>
// list of methods and properties
doStuff:(float) myValue;
#end
#protocol myProtocol2 <NSObject>
// list of methods and properties
doOtherStuff:(float) myValue2 andText:(NSString *)myText andType:(NSString *)myType;
#end
#interface myProtocols:NSObject
{
__unsafe_unretained id <myProtocol1> _myDelegate1;
__unsafe_unretained id <myProtocol2> _myDelegate2;
}
#property (nonatomic, assign) id <myProtocol1> myDelegate1;
#property (nonatomic, assign) id <myProtocol2> myDelegate2;
#end
**MESSAGES myProtocols.m**
#import myProtocols.h
#implementation myProtocols
#synthesize myDelegate1 = _myDelegate1
#synthesize myDelegate2 = _myDelegate2
...
if ([_myDelegate1 respondsToSelector:#selector(doStuff:)])
[_myDelegate1 doStuff:3.5]; **// THIS DELEGATE WORK VERY WELL**
...
if ([_myDelegate2 respondsToSelector:#selector(doOtherStuff:andText:andType:)])
[_myDelegate2 doOtherStuff:4.5 andText:#"YES MAN" andType:#"YES BRO"];
**// THIS DELEGATE DONT WORK, IT'S LIKE IT DOESNT INIT**
...
#end
**HEADER classA.h**
#import "myProtocols.h"
#interface classA: UIViewController <myProtocol1>
#property(strong, nonatomic) myProtocols *myProtoVC;
//-(void) doStuff:(float) myValue; according to comments, nothing to do :(
#end
**MESSAGES classA.m**
#import "classA.h"
#interface classA ()
#end
#implementation classA
- (void)viewDidLoad
{
[super viewDidLoad];
_myProtoVC = [[myProtocols alloc] init];
_myProtoVC.myDelegate1 = self;
}
-(void) doStuff:(float) myValue
{
NSLog(#" YES VALUE IS %f",myValue);
}
**HEADER classB.h**
#import "myProtocols.h"
#interface classB: UIViewController <myProtocol2>
#property(strong, nonatomic) myProtocols *myProtoVC;
//-(void) doOtherStuff:(float) myValue2 andText:(NSString *)myText andType:(NSString *)myType; according to comments, nothing to do :(
#end
**MESSAGES classB.m**
#import "classB.h"
#interface classB ()
#end
#implementation classB
- (void)viewDidLoad
{
[super viewDidLoad];
_myProtoVC = [[myProtocols alloc] init];
_myProtoVC.myDelegate2 = self;
}
-(void) doOtherStuff:(float) myValue2 andText:(NSString *)myText andType:(NSString *)myType;
{
NSLog(#" YES VALUE IS %f and text %# and type %#",myValue2,myText,myType);
}
So, my mistake is to call [_myDelegate2 doOtherStuff..] directly inside a function in myProtocols called only by classA.
Then, if I want to call a function in myProtocols using both delegate I MUST init both these delegates in the class (A or B doesnt matter) I use to call this function:
**MESSAGES myProtocols.m**
#import myProtocols.h
#implementation myProtocols
#synthesize myDelegate1 = _myDelegate1
#synthesize myDelegate2 = _myDelegate2
-(void) pleaseDoIt
{
if ([_myDelegate1 respondsToSelector:#selector(doStuff:)])
[_myDelegate1 doStuff:3.5]; **// THIS DELEGATE WORK VERY WELL**
...
if ([_myDelegate2 respondsToSelector:#selector(doOtherStuff:andText:andType:)])
[_myDelegate2 doOtherStuff:4.5 andText:#"YES MAN" andType:#"YES BRO"];
**// THIS DELEGATE NOW WORK VERY WELL**
}
#end
**HEADER classA.h**
#import "myProtocols.h"
#import "classB.h"
#interface classA: UIViewController <myProtocol1>
#property(strong, nonatomic) myProtocols *myProtoVC;
#property(strong, nonatomic) classB *classBVC;
//-(void) doStuff:(float) myValue;
#end
**MESSAGES classA.m**
#import "classA.h"
#interface classA ()
#end
#implementation classA
- (void)viewDidLoad
{
[super viewDidLoad];
_myProtoVC = [[myProtocols alloc] init];
_classBVC = [[myProtocols alloc] init];
_myProtoVC.myDelegate1 = self;
_myProtoVC.myDelegate2 = _classBVC // THIS IS THE POINT!!!
[_myProtoVC pleaseDoIt];
}
-(void) doStuff:(float) myValue
{
NSLog(#" YES VALUE IS %f",myValue);
}
I have a test case and a helper class. In the helper class I want to use asserts too like here:
MainTests.h
#import <SenTestingKit/SenTestingKit.h>
#interface MainTests : SenTestCase
#end
MainTests.m
#import "MainTests.h"
#import "HelperClass.h"
#implementation MainTests
- (void)testExample {
HelperClass *helperClass = [[HelperClass alloc] init];
[helperClass fail];
}
#end
HelperClass.h
#import <SenTestingKit/SenTestingKit.h>
#interface HelperClass : SenTestCase
- (void)fail;
#end
HelperClass.m
#import "HelperClass.h"
#implementation HelperClass
- (void)fail {
STFail(#"This should fail");
}
#end
Sidenote: I had to make the helper class a subclass from SenTestCase to being able to access the assertion macros.
The assertion from the helper class is ignored. Any ideas why? How can I use assertions in helper classes?
I had this same problem today and came up with a hack that worked for my purposes. Poking into the SenTestCase macros, I noticed that they call [self ...] on the helper but didn't trigger the asserts. So, wiring up the source class to the helper got it working for me. Changes to your question classes would look like:
MainTests.h
#import <SenTestingKit/SenTestingKit.h>
#interface MainTests : SenTestCase
#end
MainTests.m
#import "MainTests.h"
#import "HelperClass.h"
#implementation MainTests
- (void)testExample {
// Changed init call to pass self to helper
HelperClass *helperClass = [[HelperClass alloc] initFrom:self];
[helperClass fail];
}
#end
HelperClass.h
#import <SenTestingKit/SenTestingKit.h>
#interface HelperClass : SenTestCase
- (id)initFrom:(SenTestCase *)elsewhere;
- (void)fail;
#property (nonatomic, strong) SenTestCase* from;
#end
HelperClass.m
#import "HelperClass.h"
#implementation HelperClass
#synthesize from;
- (id)initFrom:(SenTestCase *)elsewhere
{
self = [super init];
if (self) {
self.from = elsewhere;
}
return self;
}
- (void)fail {
STFail(#"This should fail");
}
// Override failWithException: to use the source test and not self
- (void) failWithException:(NSException *) anException {
[self.from failWithException:anException];
}
#end
It is entirely possible that additional overrides are needed for more advanced functionality, but this did the trick for me.