To allow user interaction with links I use code like this:
UITextView *t1 = [UITextView new];
[self.view addSubview:t1];
t1.frame = self.view.frame;
t1.font = [UIFont systemFontOfSize:16];
t1.text = #"go to http://apple.com";
t1.dataDetectorTypes = UIDataDetectorTypeLink;
t1.editable = NO;
But if I need to set new text, it reuse style:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
t1.text = #"test";
});
Will show "test" like link (blue color) but without link behaviour (go to link, context menu). I didn't find in documentation why this is legal.
As I understand the only way to "fix" this is reset attributes like font, text color to initial values.
I found this way to fix:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
t1.dataDetectorTypes = UIDataDetectorTypeNone;
t1.dataDetectorTypes = UIDataDetectorTypeLink;
t1.text = #"another text with http://link.com link";
});
But maybe there is more correct/elegant solution.
Related
I'm trying to change though a timer in a different method the text of a label I created programmatically in a UIView overlay that goes on a UIImagePickerviewController, but of course when I try to change the text in this way
labelname.text = #"TEST";
I get the error "use of undeclared identifier labelname"
How can I refer to that specific label? Should I create a new label each time the timer ticks?
I tried to declare it in the .h file, but I'm guessing i'm just creating a different label...any ideas?
Just Pass the Label As a whole to the Timer Function:
Say Your Label is defined in ViewDidLoad like this :
- (void)viewDidLoad
{
//Do Something here
UILabel * label = [[UILabel alloc]
initWithFrame:CGRectMake(xcoordinateLabel, ycoordinateLabel, width, height)];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = UITextAlignmentCenter;
label.textColor=[UIColor whiteColor];
label.text = #"TEST";
[self.view addSubview:label];
[self changeLabelText:label];
}
Where your changeLabelText is defined as this with some delay:
- (void) changeLabelText:(UILabel *)label
{
//Changing Values after 10s Delay
double delayInSeconds = 10.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
label.text = #"TESTING Change";
});
}
Your Timer function can replace changeLabelText
I am doing one application.In that i am doing the animation for uiimageview to show the different image like below
UIImageView * fearthersanimate = nil;
[fearthersanimate setCenter:sender.center];
fearthersanimate = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 120,200)];
[fearthersanimate setCenter:CGPointMake(sender.center.x, sender.center.y)];
fearthersanimate .animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"water_can_1.png"],
[UIImage imageNamed:#"water_can_2.png"],[UIImage imageNamed:#"water_can_3.png"],
[UIImage imageNamed:#"water_can_4.png"],[UIImage imageNamed:#"water_can_5.png"],
[UIImage imageNamed:#"water_can_6.png"],[UIImage imageNamed:#"water_can_7.png"],
[UIImage imageNamed:#"water_can_8.png"],
nil];
fearthersanimate.animationDuration = 1.0f;
fearthersanimate.animationRepeatCount = 1;
[self.view addSubview: fearthersanimate];
[fearthersanimate startAnimating];
But remaining operation is starting before end of this animation.But i need to do this animation first and until i need to stop the remaining process.
You can call your rest of operation in other method and call it after the same delay as you set animation time for images.
Below is the line of code by which you can call other method after some time interval
[self performSelector:#selector(restOfOperations) withObject:nil afterDelay:1.0];
//restOfOperations method defination/implementation
-(void)restOfOperations
{
//your code you want to perform after image animation
}
You can use the UIView animation block. For example:
[UIView animateWithDuration:0.5 animations:^{
} completion:^(BOOL finished) {
}];
Put the remaining process in the completion block.
Those animations are performed asynchronously, so you just need to fight async with async.
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(feathersanimate.animationDuration * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// Remaining logic
});
In an iOs app I am using a UINavigationController. On start-up this will have a title set but after a few seconds (in response to some data from a server) this title will need to change.
I tried:
self.title = #"new title";
self.navigationController.title = #"new";
self.navigationItem.title- #"new";
Nothing works... any suggestions?
self.title = #"new";
This might set again after you have to got response from server in the method which is calling to get response.
self.navigationItem.title = #"Old title";
// after some time
double waitToUpdate = .5;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(waitToUpdate * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
self.navigationItem.title = #"New title";
});
change UINavigationController title for each view is easy enough. you just need to change the value of self.navigationItem.title. If you wan't to change it with some delay, you can use performSelector:withObject:afterDelay. For example :
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self performSelector:#selector(changeTitle:) withObject:#"New Title" afterDelay:2.]; // two seconds delay
}
- (void)changeTitle:(NSString *)title {
self.navigationItem.title = title;
}
I am trying to execute ball blasting effect to play sequentially. One after another.
What I have done yet:
For ball blasting effect i had used
UIButton *ballButton = (UIButton *)[cell viewWithTag:10];
ballButton.imageView.animationImages = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"1.png"],
[UIImage imageNamed:#"2.png"],
[UIImage imageNamed:#"3.png"],
[UIImage imageNamed:#"4.png"],
nil];
ballButton.imageView.animationDuration = 1;
ballButton.imageView.animationRepeatCount = 1;
and this line on code is attached to multiple buttons in a cell of a collection view.
I call these ballbutton.imageview start the animation like this
[UIView animateWithDuration:1 delay:5 options:UIViewAnimationOptionCurveEaseOut animations:^{
NSIndexPath *path2 = [NSIndexPath indexPathForRow:x inSection:0];
UICollectionViewCell *cell = [ballContainer cellForItemAtIndexPath:path2];
UIButton *ballObject = (UIButton *) [cell viewWithTag:10];
[ballObject.imageView startAnimating];
} completion:^(BOOL b){
NSLog(#" here i call next animation of ball blast to execute ");
}];
I nested 3 animations buttons like this.
First of all, why don't you create one big animation for all other three? The thing with the UIView animateWithDuration: is that it performs the animation block in the period of time you gave to it, i.e. setting the frame from (200,200) to (0,0) will move it proportionally in the time of a second, in your case. But UIImageView's properties regarding animations are made in such way that the animation is already done for you.
Personally, I would suggest using a timer, like this:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:ballObject.imageView.animationDuration
target:self
selector:#selector(performNextAnimation:)
userInfo:nil repeats:NO];
[ballObject.imageView startAnimating];
And in the performNextAnimation method:
- (void) performNextAnimation{
[timer invalidate]; // you have to access the timer you've scheduled with the animation
timer = nil;
/* code for starting the next animation */
}
this way i solved my issue.
initially i started animation by calling this
[self startAnim:index];
than implemented this StartAnim like this and problem solved.
-(void)StartAnim :(int)x{
NSIndexPath *path2 = [NSIndexPath indexPathForRow:x inSection:0];
UICollectionViewCell *cell = [ballContainer cellForItemAtIndexPath:path2];
UIButton *ballObject = (UIButton *) [cell viewWithTag:10];
[ballObject setBackgroundImage:nil forState:UIControlStateNormal];
ballObject.imageView.image = nil;
[ballObject.imageView startAnimating];
double delayInSeconds = 0.15;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
if(x-6>=0){
[self StartAnim :(x-6)];
}
});
}
Am changing the color of the selected segment. It works fine but uisegment control tint color is set to default until it is touched for the first time.
This is the method that changes the color for the selected segment. It works fine but when the segment shows up first time. It has pale gray color. Then when touched it starts working fine as I needed.
(This segment control is added as subview to uialertview)
-(void)segmentValueChanged:(UISegmentedControl*)sender
{
for (int i=0; i<[sender.subviews count]; i++)
{
if ([[sender.subviews objectAtIndex:i]isSelected] )
{
UIColor *tintcolor=[UIColor colorWithRed: 98/255.0 green:156/255.0 blue:247/255.0 alpha:1.0];
[[sender.subviews objectAtIndex:i] setTintColor:tintcolor];
trackType = sender.selectedSegmentIndex;
}
else{
UIColor *tintcolor=[UIColor colorWithRed: 225/255.0 green:220/255.0 blue:210/255.0 alpha:1.0];
[[sender.subviews objectAtIndex:i] setTintColor:tintcolor];
}
}
}
you can call segmentControlValueChanged method forcefully in viewDidLoad method. Like this:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.05 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self segmentedControlValueChanged:segmentedControlOne];
});
Can you please change it from viewdidload or viewwillappear method of your view? because as per your code, it will change, when user first time touch it.
truy this code
i solved my app in this code
- (void)viewDidAppear:(BOOL)animated
{
for(UIView *v in [self.view subviews] )
{
if([v isKindOfClass:[UISegmentedControl class]])
{
// ((UISegmentedControl*)v).enabled=NO;
dispatch_async(dispatch_get_main_queue(),^{
for (int i=0; i<[ ((UISegmentedControl*)v).subviews count]; i++)
{
if ([[((UISegmentedControl*)v).subviews objectAtIndex:i]isSelected] )
{
[[((UISegmentedControl*)v).subviews objectAtIndex:i] setTintColor:[UIColor colorWithRed: 0/255.0 green:176/255.0 blue:223/255.0 alpha:1.0]];
//[[((UISegmentedControl*)v).subviews objectAtIndex:0]setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
// break;
}
else
{
[[((UISegmentedControl*)v).subviews objectAtIndex:i] setTintColor:[UIColor whiteColor]];
//[[((UISegmentedControl*)v).subviews objectAtIndex:0]setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
}
}
});
}
}
}
I figured it out myself. Since alertview creates all the views only after [alertview show]. color changes to segmentcontrol is not afftected since segmentcontrol is not really created yet. So what I did was I delayed the process of segmentcontrol tintcolor changes until it's been created by alertview
[alertview show];
double delayInSeconds = 0.01;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self performSelectorOnMainThread:#selector(segmentValueChanged:) withObject:segControl waitUntilDone:YES];
});