[英]didEnterRegion and didExitRegion animation conflicting
我正在构建一个使用GeoFencing的应用程序。 我的didEnterRegion和didExitRegion方法按照预期的顺序调用,看似顺序正确,但未能相应地更新UI。
什么有效:
什么不起作用:
我的方法:
用于更新标签的自定义函数(从didEnterRegion和didExitRegion调用):
-(void)updateCurrentLocationLabelAndImage:(NSString *)locationText subLocationText:(NSString *)subLocationText;
{
// Clear existing animations before we begin
[self.locationLabel.layer removeAllAnimations];
[self.subLocationLabel.layer removeAllAnimations];
[self.ovalImageView.layer removeAllAnimations];
if (![locationText isEqual:@""])
{
// Only animate if the text changes
if (![self.locationLabel.text isEqualToString:locationText])
{
// Update the ovalImageView
CGSize maxLabelSize = CGSizeMake(([UIScreen mainScreen].bounds.size.width - (([UIScreen mainScreen].bounds.size.width * 0.0267) * 2)), 64); // maximum label size
float expectedLabelWidth = [locationText boundingRectWithSize:maxLabelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{ NSFontAttributeName:self.locationLabel.font } context:nil].size.width; // get expected width
CGFloat xValueForImage = ((([UIScreen mainScreen].bounds.size.width - expectedLabelWidth) / 2) - 25); // Calcuate the x-coordinate for the ovalImageView
if (xValueForImage < 15)
{
xValueForImage = 15; // we don't want it to display off-screen
}
self.ovalImageViewLeadingConstraint.constant = xValueForImage;
[self.view setNeedsUpdateConstraints];
[self changeLabelText:self.subLocationLabel string:subLocationText];
// Update the subLocationLabel
[UIView animateWithDuration:.15 animations:^{
// Animate
self.locationLabel.alpha = 0;
self.ovalImageView.alpha = 1;
[self.view layoutIfNeeded]; // update the UI
}completion:^(BOOL finished) {
// Set the text
self.locationLabel.text = locationText;
self.locationLabel.adjustsFontSizeToFitWidth = YES;
[UIView animateWithDuration:.15 animations:^{
// Animate
self.locationLabel.alpha = 1;
}completion:^(BOOL finished) {
// Complete
}];
}];
}
} else if ([locationText isEqual:@""])
{
// Move it to the center
self.ovalImageViewLeadingConstraint.constant = (([UIScreen mainScreen].bounds.size.width / 2) - 9); // Default center calculation for this image
[self.view setNeedsUpdateConstraints];
[self changeLabelText:self.subLocationLabel string:subLocationText]; // Update the subLocationLabel
[UIView animateWithDuration:.15 animations:^{
self.locationLabel.alpha = 0;
self.ovalImageView.alpha = 1;
[self.view layoutIfNeeded];
}completion:^(BOOL finished) {
// Complete
self.locationLabel.text = @"";
}];
}
}
但是标签保持不变,即使它记录了正确的执行顺序并且一切正常。 有任何想法吗? 我真的很困..
谢谢!
为了详细解释,
让我们考虑用户退出region1和直接进入region2的场景。
第1步:
因此,触发了事件出口,执行了以下几行,
NSLog(@"changing text from: %@, to: %@", label.text, string);
// Only animate if the text changes
if (![label.text isEqualToString:string])
如果选中此选项,则标签文本为“内部区域”(用于区域1)。 由于该方法是从退出方法调用的,因此参数string
的值将为“外部区域”。 两个值都不相同,因此控件进入该区域。
步骤2:此时,您开始了一个持续时间为0.15的动画,但是直到代码完成时动画的完成,标签的值才会更改,因为代码在完成块中。
// Complete
label.text = string;
步骤3:触发了进入区域2事件。 标签文字尚未更新,因此会刺激以下行
NSLog(@"changing text from: %@, to: %@", label.text, string);
但是,由于标签文本是“内部区域”,而字符串值也是“内部区域”,因此控件将移出if条件。
if (![label.text isEqualToString:string])
核实:
在调用更改标签文本时传递自定义的字符串值,以使文本特定,即“内部区域1”,“出口区域1”,“内部区域2”等,这样,值将有所不同并将被更新。
紧接在动画之前设置标签的值。
将值分配给原子字符串属性,然后检查属性Value。
例如:
@property (atomic, strong) NSString * currentLabelText;
-(void)changeLabelText:(UILabel *)label string:(NSString *)string
{
NSLog(@"changing text from: %@, to: %@", label.text, string);
// Only animate if the text changes
if (![self. currentLabelText isEqualToString:string])
{
self. currentLabelText = string; //Ultimately this would be our value
[UIView animateWithDuration:.15 animations:^{
// Animate
label.alpha = 0;
}completion:^(BOOL finished) {
// Complete
label.text = self. currentLabelText;
[UIView animateWithDuration:.15 animations:^{
// Animate
label.alpha = 1;
}completion:^(BOOL finished) {
// Complete
}];
}];
}
}
或其他适合您需求的方式。
你可以试试这个...
static NSString *currentText;
currentText = locationText;
[UIView animateWithDuration:.15 animations: ^{
// Animate
self.locationLabel.alpha = 0;
self.ovalImageView.alpha = 1;
[self.view layoutIfNeeded]; // update the UI
} completion: ^(BOOL finished) {
// Set the text
if (![currentText isEqualToString:locationText]) {
return;
}
self.locationLabel.text = locationText;
self.locationLabel.adjustsFontSizeToFitWidth = YES;
[UIView animateWithDuration:.15 animations: ^{
// Animate
self.locationLabel.alpha = 1;
} completion: ^(BOOL finished) {
// Complete
}];
}];
我建议您将UI更新代码放在调度块中,以确保UI更新将在主线程上执行。
dispatch_async(dispatch_get_main_queue(), ^{
//... UI Update Code
});
我猜主线程是您最大的问题。 在我看来,这段代码看起来有些奇怪:
请参阅CocoaTouch64BitGuide,这可能是一个问题,但我认为它不能解决您的布局问题。 一般而言,魔术数字更为关键。
我相信没有必要通过操纵LeadingConstraint移动椭圆图像视图。 只需将contentMode设置为center / left / right和autolayout即可进行重置。 如果确实需要更改约束,请在[yourView updateConstraints]方法中进行更改。 如果需要标签宽度,请提出以下要求: [label internalContentsize]并在需要时使用setPreferredMaxLayoutWidth 。 如果您的自动版式代码正确,则任何视图都不会出现在“屏幕外”。
您首先使用removeAllAnimations。 基本上是正确的,但是如果您希望频繁更新,我建议仅在运行前一个动画时更改标签/图像的内容。 否则,您的图像会跳回,并且将开始新的动画。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.