That may sound odd, but please consider following:
-(instancetype)initWithModel:(FRPPhotoModel *)photoModel{
self = [super initWithModel:photoModel];
if (!self) return nil;
// a lot of code here
return self;
}
Actually it underline as error following line:
self = [super initWithModel:photoModel];
Error is: No visible #interface for 'RVMViewModel' declares the selector 'initWithModel:'
It actually reference to same method it declared is. Of course, superclass does not know about it. But, in a book im reading following work fine (that is the same method:
-(instancetype)initWithModel:(FRPPhotoModel *)photoModel {
self = [super initWithModel:photoModel];
if (!self) return nil;
#weakify(self);
[self.didBecomeActiveSignal subscribeNext:^(id x) {
#strongify(self);
[self downloadPhotoModelDetails];
}];
RAC(self, photoImage) = [RACObserve(self.model, fullsizedData) map:^id(id value) {
return [UIImage imageWithData:value];
}];
return self;
}
It work perfectly fine. How to fix that?
Related
I am calling the block from second class which has been declared and maintained in first class.
In ViewController.h
#property (copy) void (^simpleBlock)(NSString*);
In View Controller.m
- (void)viewDidLoad {
[super viewDidLoad];
self.simpleBlock = ^(NSString *str)
{
NSLog(#"Hello My Name is: %#",str);
};
}
In SecondViewController.m
In ViewDidload
ViewController *VC = [[ViewController alloc]init];
VC.simpleBlock(#"Harjot");//bad execution error
Please suggest me some solutions because the code is giving me bad execution error.
How can i call the block in any another way?
It's the correct way of run the block. However if you try to run a block that is nil you'll have a crash - so you should always check that it's not nil before calling it:
ViewController *vc = [[ViewController alloc] init];
if (vc.simpleClock) {
vc.simpleBlock(#"Harjot");//this will not get called
}
The reason why in your case the block is nil is because you set it in viewDidLoad - however viewDidLoad is not called until its view is ready to go on screen. For testing purposes try to move the assignment from viewDidLoad to init and this should work:
- (instancetype)init
{
self [super init];
if (self) {
_simpleBlock = ^(NSString *str)
{
NSLog(#"Hello My Name is: %#",str);
};
}
return self;
}
At first, sorry for my english. I trying to resolve problem with a few enter points (a few initializators like initWithFrame: and initWithCoder:). Not to repeat my setup code. At first i had a simple solution, just create method ("setup" for example) that called by initializators. But there is a little problem with subclasses. If my subclass have own initializator like initWithFrame:backgroundColor: and property "backgroundColor" then its own overriden "setup" will be called by super initializator but "backgroundColor" will still nil. So this "setup" will cant use this property. I think its common problem and its have nice common solution, that i cant find.Thanks.
Typically, I'll create static function called _commonInit(MyClass *self) and call that from each initializer. It is a function because it won't be inherited.
base class
-(instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self setup];
}
return self;
}
-(instancetype)initWithCoder:(NSCoder*)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self setup];
}
return self;
}
-(void)setup
{
//some setup code
}
child class
-(instancetype)initWithFrame:(CGRect)frame param:(id)param
{
self = [super initWithFrame:frame];
if(self)
{
self.param = param;
//setup will be run by parent
}
return self;
}
-(void)setup
{
[super setup];
//child setup code
//when this code will work self.param will still nil!
}
thats what i mean
Bear with me here, when we link one UIViewController to another one with a segue, which "init" method does the segue use to initiate the new UIViewController? Is it "initWithCoder" ? or something else? I need to know because I need to modify the init method that segue uses to initiate the UIViewController.
Thoughts?
It is this method
initWithCoder
I think this solution is better
You write some common code in
-(void)setUp{
//Set up
}
Then you put this code in every initMethod:
-(instancetype)initWithCoder:(NSCoder *)aDecoder{
if (self = [super initWithCoder:aDecoder]) {
[self setUp];
}
return self;
}
-(instancetype)init{
if (self = [super init]) {
[self setUp];
}
return self;
}
//Also other init method
I've been programming in Objective-C for years now, and I always bump into this problem: If you have an object with multiple initializers, but there is code in common to all of them, how do you extract it out?
The best I've been able to come up with is something like this:
#implementation Example
- (void)privateInitWithString:(NSString*)aString
{
self.str = aString;
}
- (id)init
{
self = [super initWithWindowNibName:#"MyNib"]
if(self) {
[self privateInitWithString:#""];
}
return self;
}
- (id)initWithString:(NSString*)aString
{
self = [super initWithWindowNibName:#"MyNib"]
if(self) {
[self privateInitWithString:aString];
}
return self;
}
#end
There is a lot of duplication in the individual initializers which a code smell. However I can't think of a way to get one initializer to "fall through" to another one because there is no guarantee that self has been set before calling [super init]
Is there a best practice for this that I'm missing?
You write one "designated initialiser". That initialiser handles all the different situations. In your case, initWithString seems a good candidate. And init just becomes
- (instancetype)init { return [self initWithString:#""]; }
You can read more about it here:
https://developer.apple.com/library/ios/documentation/general/conceptual/CocoaEncyclopedia/Initialization/Initialization.html
I've been trying to save strings in Xcode such as email and password so i can open them in different view, So far every attempt for the past 2 weeks have failed.
does anyone have a working way, and if so can you post the code.
Thanks
*edit***
Almost done just having an error here
(MemberPage *)initWithString: (NSString) S {
self = [super init];
if ( self ) {
//DO STUFF;
UserNAME.text = S.text;
}
return self;
}
error is on the first line:
use of undeclared identifier with initWithString
Also get should be a ; before :
(MemberPage *)initWithString: (NSString *) s {
self = [super init];
if ( self ) {
//DO STUFF;
UserNAME = s;
}
return self;
}
Forgot the '*'?
One of the easiest way's I've done this in the past is just to pass them in when I create my View:
RecieverClass.m:
(RecieverClass*) initWithString: (NString) S {
self = [super init];
if ( self ) {
//DO STUFF;
myLocalString = S;
}
return self;
}
SenderClass (where you create your view)
RecieverClass *recieverClass= [[RecieverClass alloc] initWithString:sendString];
[[self navigationController] pushViewController:recieverClass animated:YES];
[recieverClass release];
You could pass them in as pointers or w/e really. Just depends what you're trying to do really.
I use a singleton class to share data between different views and for me it works. In the source viewController, I assign the value as a parameter to the "shared" class, and in the destination viewController I retrieve it.
Dunno if it's the "legal" way to do it, but it's simple and it works.
Check out this tutorial: http://www.bit-101.com/blog/?p=1969
At a certain point you arrive at this piece of code:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// Custom initialization
Model *model = [Model sharedModel];
[model addObserver:self forKeyPath:#"text" options:NSKeyValueObservingOptionNew context:nil];
}
return self;
}
Adding the observer didn't immediately work for me, dunno why but I didn't look into this issue deeper.
I changed it into:
Model *model = [Model sharedModel];
model.parameter = #"btnMainToTarget";
Follow the instruction from beginning till end - it will work.
To any other people; don't hesitate to react if you didn't think my reply was accurate.
Greetings