I am very new to ios and having a problem to call four different methods one after the other, as I would like to call them after comparison like if(number<6)
method2->method3->method4->method1-> such that it would make a loop until the comparison of (number)become false.
Also I want method1 to be activated in viewDidLoad.
Something like this, if I understood your question properly
[[[method2 method3] method4] method1]
You can use
[yourObject performSelector:#selector(method1:)]
You can call it on any NSObject (and subclasses of course). You may want to try before :
[yourObject respondToSelector:#selector(method1:)]
This will tell you if your object has this method or not (avoid exceptions and errors).
More informations on the official documentation of performSelector.
use [self method1]; somewhere else and use as follows:
-(void) method1
{
[self method2];
}
-(void) method2
{
[self method3];
}
-(void) method3
{
[self method4];
}
-(void) method4
{
// do if you need.
}
Or Try NSNotificationCenter
I hope i'm interpreting your question correctly. But here's a simple implementation...
- (void)viewDidLoad {
[super viewDidLoad];
[self method1];
}
- (void)method1 {
/* do stuff */
[self method2];
}
- (void)method2 {
/* do stuff */
[self method3];
}
- (void)method3 {
/* do stuff */
[self method4];
}
- (void)method4 {
/* do stuff */
}
-(void) method1
{
if (number<6)
{
[self method2];
}
}
-(void) method2
{
[self method3];
}
-(void) method3
{
[self method4];
}
-(void) method4
{
[self method1];
}
Related
I am currently working on an implementation where many blocks are used. Every block needs to communicate with self.
Currently I am doing this:
#implementation Foo
- (void) bar
{
__weak Foo *weakSelf = self;
[self doBlockStuff:^(id something) {
[weakSelf doSomething];
}];
}
#end
I have many functions that do the same with the weak instantiation.
Is it right to instantiate the weak property once in the interface block and use it everywhere?
It's working but is it an accepted practice?
#interface Foo ()
{
__weak Foo *_weakSelf;
}
#end
#implementation Foo
-(instancetype) init
{
self = [super init];
if(self) {
_weakSelf = self;
}
return self;
}
- (void) bar1
{
[self doBlockStuff:^(id something) {
[_weakSelf doSomething];
}];
}
- (void) bar2
{
[self doBlockStuff:^(id something) {
[_weakSelf doSomething];
}];
}
- (void) bar3
{
[self doBlockStuff:^(id something) {
[_weakSelf doSomething];
}];
}
- (void) bar4
{
[self doBlockStuff:^(id something) {
[_weakSelf doSomething];
}];
}
#end
Edit after Testing with new Informations:
I did wrote a little test case and now i can demonstrate why the second one is not working.
In my Testclass a imake a dispatch after 5 seconds with the relevant self usage and i logged when my dealloc was called.
#implementation Foo
- (void)dealloc
{
NSLog(#"dealloc");
}
- (instancetype)init
{
self = [super init];
if (self) {
}
return;
}
- (void)bar
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self doSomething];
});
}
#end
If the class loses the holder, because the controller is closed or whatever and the function is still running, the class will dialoged after the dispatch is done.
#interface Foo ()
{
__weak Foo *_weakSelf;
}
#end
#implementation Foo
- (void)dealloc
{
NSLog(#"dealloc");
}
- (instancetype)init
{
self = [super init];
if (self) {
_weakSelf = self;
}
return;
}
- (void)bar
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[_weakSelf doSomething];
});
}
#end
This one will also on dealloc if the dispatch is done. Because the _weakSelf property is still holing by the class, a shorthand for using self->_weak. Self means self :)
#implementation Foo
- (void)dealloc
{
NSLog(#"dealloc");
}
- (instancetype)init
{
self = [super init];
if (self) {
}
return;
}
- (void)bar
{
__weak typeof(self) weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[weakSelf doSomething];
});
}
#end
this one will dealloc immediately because the weak reference is only existing in this function given to the block. The function is over and if the class loses his reference the block has no property that is holing anyone. But the weak property is still usable when the reference class is available.
To be sure, that this weak property will be alive, we can set a strong cycle in the block.
This doesn't at all do what you think it does. That __weak instance variable in those methods? That's just a shorthand for self->_weak. All of those methods using the proposed manner still capture self strongly.
Stick to what you were doing before.
This is really bad then if the __weakSelf still holds a strong reference. The question is that if instantiated in the method and used in the method does it still really have a weak anchor to self or is it holding a strong reference in that very moment. Based on the documentation you can instantiate a weak reference outside the block and even make it strong inside the block if you want. Take a look here
http://aceontech.com/objc/ios/2014/01/10/weakify-a-more-elegant-solution-to-weakself.html
my question at this point in time is that why does a weak self instantiated dealloc it's self when the real self deallocs..? Because I tried to hold the weak self in another viewController and then dealloc the real self. But the weak self was dealloc as soon as I dealloc the real self.
I am trying to implement UITextFieldDelegate textFieldShouldReturn handling with ReactiveCocoa. Unfortunately the subscribeNext block is run when I subscribe for the signal.
The implementation using delegation would be:
- (void)viewDidLoad
{
...
self.myTextField.delegate = self;
}
...
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField == self.myTextField) {
NSLog(#"Let's go!");
}
return YES;
}
In ReactiveCocoa I have added a category for UITextField in a similar fashion like UITextView+RACSignalSupport.
#implementation UITextField (RACKeyboardSupport)
static void RACUseDelegateProxy(UITextField *self)
{
if (self.delegate == self.rac_delegateProxy) return;
self.rac_delegateProxy.rac_proxiedDelegate = self.delegate;
self.delegate = (id)self.rac_delegateProxy;
}
- (RACDelegateProxy *)rac_delegateProxy
{
RACDelegateProxy *proxy = objc_getAssociatedObject(self, _cmd);
if (proxy == nil) {
proxy = [[RACDelegateProxy alloc] initWithProtocol:#protocol(UITextFieldDelegate)];
objc_setAssociatedObject(self, _cmd, proxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return proxy;
}
- (RACSignal *)rac_keyboardReturnSignal
{
#weakify(self);
RACSignal *signal = [[[[RACSignal
defer:^{
#strongify(self);
return [RACSignal return:RACTuplePack(self)];
}]
concat:[self.rac_delegateProxy signalForSelector:#selector(textFieldShouldReturn:)]]
takeUntil:self.rac_willDeallocSignal]
setNameWithFormat:#"%# -rac_keyboardReturnSignal", [self rac_description]];
RACUseDelegateProxy(self);
return signal;
}
#end
Here subscribeNext block is executed even if the Return Key was never pressed:
- (void)viewDidLoad
{
...
[self.myTextField.rac_keyboardReturnSignal subscribeNext:^(id x) {
Log(#"Let's go with RAC!");
}];
}
I have to use skip:1 to avoid that problem:
- (void)viewDidLoad
{
...
[[self.myTextField.rac_keyboardReturnSignal skip:1] subscribeNext:^(id x) {
Log(#"Let's go with RAC!");
}];
}
Any idea why this happens?
Solution:
- (RACSignal *)rac_keyboardReturnSignal
{
RACSignal *signal = [[[self.rac_delegateProxy
signalForSelector:#selector(textFieldShouldReturn:)]
takeUntil:self.rac_willDeallocSignal]
setNameWithFormat:#"%# -rac_keyboardReturnSignal", [self rac_description]];
RACUseDelegateProxy(self);
return signal;
}
You are returning a signal that immediately returns a value in your defer block, then concat-ing new values onto the stream when textFieldShouldReturn is invoked.
The code in UITextView+RACSignalSupport.m is calling reduceEach in order to return a string value that is extracted from the UITextView instance. The defer is used to merely have an initial value generated upon subscription.
Basically, I don't think you want the defer at all for your use case.
Here is the code i'm using to detect if 2 UIImageViews hit each other.
if (CGRectIntersectsRect(Appy.frame, Bottom.frame)) {
[self GameOver];
}
At the moment its detecting the edge of the object.
How do i change it to detect the edge of the image inside the UIImageView.
The image inside has a transparent background and is "practically circle" so they are colliding if the corner of UIImageView hits the corner of another UIImageView but the image is not actually hitting so its making things look a little "messy"
EDIT*
these are the errors im getting
this is my .h
EDIT: below is what my code now looks like
.m Method
if (CGRectIntersectsRect([self: RectBox:Appy].frame, Bottom.frame)) {
[self GameOver];
}
.h
-(UIImageView *)RectBox:(UIImageView *)box;
i put this just above the very last #end on my .h just to be sure.
Im still "getting use of undeclared identifier 'RectBox'"
EDIT
EDIT
As requested here is the code in which i call the method
-(void) PipeMoving2{
PipeTop2.center = CGPointMake(PipeTop2.center.x -2, PipeTop2.center.y);
PipeBottom2.center = CGPointMake(PipeBottom2.center.x -2, PipeBottom2.center.y);
if (PipeTop2.center.x < -53+33) {
[self PlacePipe2];
}
if (PipeTop2.center.x == 62) {
[self Score];
}
if (CGRectIntersectsRect(Appy.frame, PipeTop2.frame)) {
[self GameOver];
}
if (CGRectIntersectsRect(Appy.frame, PipeBottom2.frame)) {
[self GameOver];
}
if (CGRectIntersectsRect(Appy.frame, Top.frame)) {
[self GameOver];
}
if (CGRectIntersectsRect([self RectBox:Appy].frame, Bottom.frame)) {
[self GameOver];
}
}
i think this is all u need to see right?
Change it to the following:
if(CGRectIntersectsRect([self RectBox:Image].frame, Bottom.frame))
Another thing I noticed from your image is that you are placing the method within another method.
Ex: (what I see from your image, it seems)
- (void)yourMethod
{
......
if (CGRectIntersectsRect([self RectBox:Image].frame, Bottom.frame))
{
[self GameOver];
}
.....
//etc etc
//and then you have this
-(UIImageView *)RectBox:(UIImageView *)box
{
box.frame = CGRectMake(box.frame.origin.x +15,
box.frame.origin.y +15,
box.frame.size.width -30,
box.frame.size.height-30);
return box;
}
....
}
You should extract that and place it outside of your method, so it becomes:
- (void)yourMethod
{
......
if (CGRectIntersectsRect([self RectBox:Image].frame, Bottom.frame))
{
[self GameOver];
}
.....
//etc etc
....
}
//take it out and place it here, for example
- (UIImageView *)RectBox:(UIImageView *)box
{
box.frame = CGRectMake(box.frame.origin.x +15,
box.frame.origin.y +15,
box.frame.size.width -30,
box.frame.size.height-30);
return box;
}
Update to questions in comments not exactly related to the original question, but here is my finding from your code:
The reason you character is changing size may stem from the fact that you are changing its frame in your RectBox method.
Here is a rough redefinition of the method, so that we could "preserve" the frame of your character:
- (CGRect)RectBox:(UIImageView *)box
{
CGRect tempRect = CGRectMake(box.frame.origin.x +15,
box.frame.origin.y +15,
box.frame.size.width -30,
box.frame.size.height-30);
return tempRect;
}
And make changes to the call.
Ex:
if (CGRectIntersectsRect([self RectBox:Image], Bottom.frame))
{
[self GameOver];
}
Regarding the movements, check the frequency you set for your NSTimer. I wouldn't go more frequent than 0.1.
Hope this helps.
Try this
.h
-(UIImageView *)RectBox:(UIImageView *)box;
.m
if (CGRectIntersectsRect([self RectBox:Image].frame, Bottom.frame))
{
[self GameOver];
}
-(UIImageView *)RectBox:(UIImageView *)box
{
box.frame = CGRectMake(box.frame.origin.x +15,
box.frame.origin.y +15,
box.frame.size.width -30,
box.frame.size.height-30);
return box;
}
Try this code
CGPoint a = imageViewA.center;
CGPoint b = imageViewB.center;
CGFloat distance = sqrt(pow((b.x - a.x),2) + pow((b.y - a.y),2));
if(distance < (imageViewA.bounds.size.width/2.0 + imageViewB.bounds.size.width/2.0)){
//images are touching.
}
var attributes = [UICollectionViewLayoutAttributes]()
for att in cache {
if (att.frame.intersects(rect))
{
attributes.append(att)
}
}
In swift 3 You can use like this.
I have some source code below which will reproduce this. Calling showWithStatus and dismiss before the HUD has a chance to present itself is causing the control to not show the next time showWithStatus is called. Does anyone know any workarounds?
// Commenting these will show SVProgressHUD
[SVProgressHUD showWithStatus:#"Loading..."];
[SVProgressHUD dismiss];
// Comment above to show SVProgressHUD
[SVProgressHUD showWithStatus:#"Loading..."];
[self performSelector:#selector(dismissHUD) withObject:nil afterDelay:5.0f];
EDIT: I have some source code up here that reproduces this.
I worked around it by doing this for the second HUD display:
[self performSelector:#selector(showHud) withObject:nil afterDelay:0.1];
I have resolved the problem:
1. add property
#property (nonatomic, readonly, getter = isDismissing) BOOL dismissing;
2.add flag
- (void)dismissWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay {
_dismissing = YES;
...
void (^completionBlock)(void) = ^{
...
_dismissing = NO;
};
...
}
Rename function
- (void)showImage:(UIImage)image status:(NSString)status duration:(NSTimeInterval)duration
to with name
- (void)showImageSS:(UIImage)image status:(NSString)status duration:(NSTimeInterval)duration
3.add delay
- (void)showImage:(UIImage*)image status:(NSString*)status duration:(NSTimeInterval)duration
{
if(self.isDismissing){
__weak SVProgressHUD *weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * SVProgressHUDDefaultAnimationDuration),dispatch_get_main_queue(), ^{
[weakSelf showImageSS:image status:status duration:duration];
});
}else{
[self showImageSS:image status:status duration:duration];
}
}
And
- (void)showImageSS:(UIImage*)image status:(NSString*)status duration:(NSTimeInterval)duration
{
// this is orginal function - (void)showImage:(UIImage)image status:(NSString)status duration:(NSTimeInterval)duration code block
}
finsh Thanks Everybody
I have a method that draws a one sprite on the screen with the animation effects,
if I call in init this method
if( (self=[super init]) ) {
// ....
[self myMethod];
// .....
}
Then he does it once on my project
When I call by schedule
-(void)schedulMyMethod:(ccTime)dt {
[self myMethod];
}
if( (self=[super init]) ) {
// ....
[self schedule:#selector(schedulMyMethod:) interval:0.5];
// .....
}
It runs for an unlimited times
I need so that I can call the my method some amount
You mean, you want to have it repeat N times? You'll need to keep state on times remaining for it to run.
#property (nonatomic, assign) NSInteger timesToRunMyMethod;
- (void)beginRunningMyMethod {
self.timesToRunMyMethod = 100; // N==100
[self myMethod];
}
- (void)myMethod {
self.timesToRunMyMethod--;
// do stuff
if (self.timesToRunMyMethod > 0) {
// i used native delayed execution, you can replace it with whatever cocos2d offers if you want
[self performSelector:#selector(myMethod) withObject:nil afterDelay:0.5];
}
}
And it's probably wrong to start this on init. Is it a view controller? Then you can use viewDidAppear or willAppear.