Access methods or property from another class without calling ViewDidLoad? - ios

Typically, I would call another class method like this:
MyClass *class = [[MyClass alloc] init];
[class myMethod];
But the problem is that, it will call the ViewDidLoad. That is a problem for me.
Is there any way to access a property in another method or call a class in another method without calling the ViewDidLoad?
Thanks!
Edit1: So are you are saying that if I do this it will not call my VDL?:
MyClassB *classB = [[[MyClassB alloc] init] autorelease];
[classB.pauseButton setHidden:NO];
Also how about when I call a method will that trigger the ViewDidLoad?

Sure; refactor myMethod to not call viewDidLoad.
That is, if you call method a and method a calls b, but you don't want to call b, then you need to modify the implementation of a to sometimes not call b. Either by modifying a or creating a new method c on the class containing a that doesn't call b.
If the problem is that you are calling a method in the system frameworks and it is calling viewDidLoad when you don't want, then the answer is that you really can't do what you think you want to do. But that is just a symptom; the real answer is that your app's architecture needs to be revisited to better fit with the system's frameworks.
Edit1: So are you are saying that if I do this it will not call my
VDL?:
MyClassB *classB = [[[MyClassB alloc] init] autorelease];
That is creating a new instance of MyClassB. If there is already an instance being displayed on screen, then you most likely do not need a new instance and, yes, that is the reason why viewDidLoad is being called.
Either create an instance variable that can point to the already existing instance of classB or otherwise have a means of grabbing that instance; hang it off the app delegate or something.
Overall, it sounds like you are confused about what it means to instantiate an object vs. simply referring to one and how all that fits into the UIKit model of app creation. It is a bit tricky until you get the hang of it. Study some of the many examples that show how to use view controllers as they will likely have solved a similar problem.

You could create the view controller once and save it in an instance variable, then use the instance variable to call the method or access properties.
eg.
if(self.myClass==nil)
self.myClass = [[MyClass alloc] init];
[self.myClass doStuff];
[self.myClass.pauseButton setHidden:NO];

Related

Why init.. methods are required in Objective C?

Wherever I've read, it's written to never use an object without calling it's initializer function. And initializer functions always "have to" start with "init".
Is there a reason behind this naming (Does naming a method starting with init do something special)? What happens if I do not call the initializer function i.e. if I just do [MyClass alloc] and start using the object?
Alloc is called to allocate space in memory for the data type you are specifying. Whether it is NSString or NSNumber, calling Alloc will reserve the most efficient space in memory as possible for that data type (small or large).
Init is called to instantiate the class and superclass's important variables. These variables could include the Rect to recalculate a certain size in order to layout subviews, or perhaps instantiate with a delegate of some kind to perform some protocol upon creation. If it all becomes too much for you Objective-C does allow you to instantiate objects like MyClass *myObject = [MyClass new];
It may all seem redundant and a waste of time, but fortunately Swift has cut down tremendous amounts of redundancies like this in the new programming language. Now all you have to do is var myObject = MyClass() and if there are any custom initializers they would likely be writen like so var myObject = MyClass(frame: CGRectZero)
Happy coding!
I recommend reading the Apple Documentation on Object Initialization, and Initialization.
Is there a reason behind this naming (Does naming a method starting with init do something special)?
It is the convention, beginning a method name with init does not do anything special.
There are some minor quirks, such as if a method beginning with init returns type id, the compiler will convert the return type to instancetype, but these are barely worth mentioning.
What happens if I do not call the initializer function i.e. if I just do [MyClass alloc] and start using the object?
If you're using a standard SDK class, you'll likely run into a crash / exception. Initialization is used to set up the initial state of the instance variables, and without doing this can lead to undefined behaviour.
For a small example, if you called [[MyObject alloc] vegetable]; with the following class, you'd get nil returned because _vegetable hasn't been assigned.
#interface MyObject : NSObject
-(NSString*)vegetable;
#end
#implementation MyObject {
NSString *_vegetable;
}
-(instancetype)init {
self = [super init];
if (self) {
_vegetable = #"Cabbage";
}
return self;
}
-(NSString*)vegetable {
return _vegetable;
}
#end
It is the way you create objects in Objective-C. It is a hard requirement of the language. Creating an object in Objective-C is a 2 step process: alloc and init.
Under the covers, the reason you must call init is, wait for it, initialization.
The call to alloc creates a block of memory for your object and zeros it out. Calling init allows the object and it's ancestors to set things up so the object is ready to function. It initializes the object's memory and does other housekeeping that set the object up.
Further, every object's init method needs to call super init, so the initialization goes all the way up the object chain, all the way to NSObject. All the ancestor classes are designed to assume that their init method is called.

How do I use this private API?

I have found the class PSCellularDataSettingsDetail and its method +(void)setEnabled:(BOOL)enabled;, which I think will give me what I need, which is accessing the mobile data setting.
I found this method by opening up the compiled Preferences.framework using class-dump-z.
Now I found this answer and tried to access the class and method that way, but the class is private too. How can I open this class up to Xcode?
Have you tried calling performSelector? That is usually the trick to call private methods. Remember all that makes a method private in Objective-C is the fact that it is not advertised in the h file. But if you send a message to an object and the object can respond to that message it will, regardless of what's in the header file.
If it's a class method like +(void)setEnabled you would just call [MyClass performSelector(#selector(myMethod)] and if it is an instance method you would call it on a variable that is an instance of the class:
MyClass *c = [[MyClass alloc] init];
[c performSelector: #selector(myMethod)]
It gets tricky when you need to pass parameters though like in this case, because the only way performSelector can pass parameters is if they are objects not primitives. You can also look into using objc_msgSend.
There is a ton of stuff online explaining how those two work. Either way it's messy to try to call private methods and is very risky.

Custom init from from NSClassFromString

I try to dynamically call certain viewController/Feature depends on his Name.NSClassFromString
(that kind of idea was suggested by Facebook).
For Instance from my server I can define in IOS app which feature or viewController should be used.(or On/Off them)
I searched all over Stack but still cant find an elegant way to implement what I want
Class myclass = NSClassFromString(className);
id obj = [[myclass alloc] init];
will work.
But I would like to call my custom init.
Class myclass = NSClassFromString(className);
id obj = [[myclass alloc] initWithCostumInitializer:userInfo];
I cant find a proper way to do it. Of course every time I receive an error because initWithCostumInitializer is not recognised.So I need to make the decision in run time.I believe I missing something.
Tnx a lot.
First off, you shouldn't get a compile-time error about an unknown method if the headers for the possible classe(s) are imported into the .m file where this code is running. Because of exactly this sort of dynamism, ObjC should let you get away with calling fairly arbitrary methods on objects of type id.
But that's just a bandaid solution. Really, if you know that that custom initializer method is present, then it's not an arbitrary class, right? You have some idea what kind of object it is, or at least what kind of base class it derives from, otherwise you wouldn't know to call that method. So you could always:
id customObj = [((BaseViewController *)[myclass alloc]) initWithCustumInitializer:userInfo];
If your error is a runtime error about the receiver missing that selector, then you have a real problem, which is: why are you calling a named method on an object that might not be the kind of object that has that method? If that's what's happening, you'll need to look at the class first to figure out what kind of thing you're actually about to create, and then behave appropriately for the init.

Passing owner reference to created objects

I need to pass the reference of a view controller to one of the object it creates. I have the following piece of code where I instantiate my object
//Method in OwnerClass
- (void) someMethod{
SomeObject *obj = [[SomeObject alloc] init];
obj.instanceVar = self.iVar;
}
Now in SomeObject I want to access the owner(instance of OwnerClass) which created it.
//Method in SomeObject
- (void) callback{
[ownerObj callMethod] //ownerObj is the instance of OwnerClass that created an instance of SomeObj
}
I want to know how do I access the instance of OwnerClass inside instance of SomeObject. Of course, I can simply write a property inside SomeObject like
#property(nonatomic) OwnerClass *ownerReference;
and assign it when I'm initializing SomeObject and access it from there.
What I want to is if there is any standard way of getting the owner. Something similar to
self.parentViewController
which is Apple's standard way of obtaining the parent of a particular view controller.
There is no general, formal concept of "Ownership" for objects in Objective C or the iOS SDK. So no, there is no standard "magic" way of doing what you want.
it's wrong to pass a reference from view to another view..
if you want to call method in another controller you can use protocols and delegate

self in objective C

-(void)setFaceView:(FaceView *)faceView
{
_faceView= faceView;
self.faceView.dataSource = self;
}
I just started learning IOS programming with famous Stanford lectures on iTunes. I am currently at lecture 6 and I start to have difficulty catching up with the class.
It is a really basic thing, but I really don't understand how 'self' works. Can anyone teach me what 'self's in this code are doing?
self is an implicit parameter in objective-c of instance methods that refers to the object performing the method - see here: Messages to Self and Super
In this case, self.faceView is a call to the property accessor for faceView that is bound to the instance that runs this method, while the assignment _faceView= faceView; is assigning the input parameter faceView to the iVar _faceView. self.faceView.dataSource = self; assigns the object performing this method to the dataSource property of the object's faceView property.
self is the object itself. when you alloc an object. it sets aside enough memory to hold all the variables that class will use.
when you init the object however you attach that memory to self. self is essentially a "variable" (and i use the term loosely) that gives you access to all the functions of the object you are within.
if you have an object with the following method
+(BOOL) isThisWorking{ return YES;}
you would have to call the method on the class. Self is not involved.
however if you have a method
-(BOOL) isThisWorking{ return YES; }
then you would have a method attached to an instance of a class.
calling the first one would require you to call it on the class object itself.
[MyObject isThisWorking];
calling the second one would require you to call it on an instance.
MyObject *testObject = [[MyObject alloc] init];
[testObject isThisWorking];
when you are in a method within test object you will not have the 'testObject' to call methods on.
self fills that void.
if you come from another programming language you will be familiar with other constructs that do the same thing.
for instance in .net the object is "this"
and in old school vb if i remember correctly the object is "Me"

Resources