开发者

.Net developer new to Objective-C. Need some critique and suggestions

I've created one of my first apps using Objective-C. Being a noob, there's a lot of stuff I want to do, but don't know how to apply it in Objective-C. Please take a look at the method below (which I created from scratch) and tell me what you would do to make it better. Obviously I've duplicated code across 2 UILabels, but I'd like to simplify that (I hate duplicating code) but I'm unaware what the best way to do it is. I just need suggestions which 开发者_如何学Cwill help me better understand the right way to do stuff in Objective-C

timeText and dateText are of type UILabel

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (isRearranging)
    {
        NSLog(@"touchesMoved");
        NSLog(@"touches=%@,event=%@",touches,event);
        //TOUCH INFO
        UITouch *touch = [[touches allObjects] objectAtIndex:0];
        CGPoint currentLocation = [touch locationInView:touch.view];
        CGPoint previousLocation = [touch previousLocationInView:touch.view];
        //FRAME INFO
        float timeHalfWidth = timeText.frame.size.width / 2;
        float timeHalfHeight = timeText.frame.size.height / 2;
        CGRect timeTextRect = CGRectMake(timeText.center.x - (timeHalfWidth), timeText.cener.y - (timeHalfHeight), timeText.frame.size.width, timeText.frame.size.height);
        float dateHalfWidth = dateText.frame.size.width / 2;
        float dateHalfHeight = dateText.frame.size.height / 2;
        CGRect dateTextRect = CGRectMake(dateText.center.x - (dateHalfWidth), dateText.center.y - (dateHalfHeight), dateText.frame.size.width, dateText.frame.size.height);
        //IF TIME TEXT
        if(CGRectContainsPoint(timeTextRect,previousLocation))
        {
            CGPoint item = timeText.center;
            CGPoint diff;
            diff.x = previousLocation.x - item.x;
            diff.y = previousLocation.y - item.y;
            CGPoint newLoc;
            newLoc.x = currentLocation.x - diff.x;
            newLoc.y = currentLocation.y - diff.y;
            if (newLoc.x<timeHalfWidth)
                newLoc.x = timeHalfWidth;
            if (newLoc.y<timeHalfHeight)
                newLoc.y = timeHalfHeight;
            [timeText setCenter:(newLoc)];
        }
        //IF DATE TEXT
        if(CGRectContainsPoint(dateTextRect,previousLocation))
        {
            CGPoint item = dateText.center;
            CGPoint diff;
            diff.x = previousLocation.x - item.x;
            diff.y = previousLocation.y - item.y;
            CGPoint newLoc;
            newLoc.x = currentLocation.x - diff.x;
            newLoc.y = currentLocation.y - diff.y;
            if (newLoc.x<dateHalfWidth)
                newLoc.x = dateHalfWidth;
            if (newLoc.y<dateHalfHeight)
                newLoc.y = dateHalfHeight;
            [dateText setCenter:(newLoc)];      
        }
    }
    touchMoved = YES;
}

Thanks so much for your help!


A first step, independent from the language you are working in, would be to follow DRY - most of your code is the same for both labels.
Then there is already functionality for hit-testing in the SDK, e.g. -hitTest:withEvent: or -pointInside:withEvent::

NSArray *labels = [NSArray arrayWithObjects:timeText, dateText, nil];
for (UILabel *label in labels) {
    if ([label pointInside:previousLocation withEvent:nil]) {
        [self relocateLabel:label]; 
        break;
    }
}


I will answer an additional question posed by asker in a comment. Quote:

What if I wanted to use mixed types in that array? i.e. a couple UILabel and a couple UIImageView. Is there a way to compare types or use generics? This is a poor guess/example for (NSObject *obj in objects) { if (label.type==UILabel) [self relocateLabel:obj]; else if (label.type==UIImageView) [self relocateImage:obj]; }

As Georg Fritzsche answered there, Objective-C messaging is dynamic. Object will be "queried" if it supports that message at runtime, and if so, it will execute the method associated with the message. Method/message name is called a "selector".

If you explicitly want to figure out object's class, you can do that as well.

if([view isKindOfClass:[UILabel class]])
{
    // your code here
}

If you just want to figure out if the target object responds to a selector (that is, implements a method):

if([view respondsToSelector:@selector(relocateView:)])
{
    // your code here
}

Selectors are derived from method names by omitting arguments themselves, leaving colons intact and appending everything closely. For example, if you had a message send (that is, method call): [thing moveTowardsObject:door movementType:XYZ_CRAWL], its selector would be: moveTowardsObject:movementType: and you'd get it using @selector(moveTowardsObject:movementType:).

In a loop such as what Georg posted, you typically want to just check if the target object responds to a selector, since otherwise an exception would be thrown, and Objective-C code rarely catches exceptions as part of a normal code flow (as opposed to what Python developers do).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜