Skip navigation

Monthly Archives: March 2013

Delegate: A person sent or authorized to represent others
Delegation

First, DELEGATE is problematic. It’s not a common word, and most people don’t know what it means, and beyond that it’s NOT CLEAR what it means in a software context. It’s a bad metaphor.

The use of the word DELEGATE is different than in C#. A delegate in C# is just a function pointer. A DELEGATE in Objective-C is an OBJECT that implements a bunch of functions (very similar to overriding methods in inheritance), BUT THESE FUNCTIONS AREN’T OVERRIDING FUNCTIONS IN A BASE CLASS. Instead, they are implementing A “PROTOCOL” (not a C++ programming concept, its an objective-c concept). OC PROTOCOLS are like C++ INTERFACES (abstract base classes), only weirder. Delegate classes contain just a bunch of stubs of functionality that would get called by the default Apple UIApplication object, if that object respondsToSelector, for example.

Some Foundation Framework classes are like big assholes, like UIApplication for example. They go about their business in a VERY routine way, and WHEN THEY FEEL LIKE IT, they “delegate” little tasks out to YOUR DELEGATE OBJECT. When you program with Foundation classes, you provide that itty-bitty, gopher-boy, go-do-what-I-said, shoe-shine, lackey-boy, I-have-no-money-please-help-me-sir object (called a DELEGATE). The big king UIApplication Foundation class WILL CALL YOUR DELEGATE WHEN THE TIME COMES.

So your little shitty delegate just implements willDoStep3 here, and arguments may be passed by Framework object. UIApplication has a bunch of points at which it “needs” a delegate to call: applicationDidFinishLaunching, applicationWillResignActive, etc.

So app delegation is like fake inheritance. In normal inheritance, you would OVERRIDE applicationDidFinishLaunching, and provide your own method stub. In Objective C, you “provide a delegate object that implements a protocol”. It is conceptually almost the same thing.

I don’t understand why Apple decided to invent this new language and concepts of protocols and delegates, when C++’s concepts of interfaces and inheritance do just fine.


As an example of implementing a delegate protocol, let’s implement GKMatchDelegate. All the information you need is in the documentation there.

// SFMatchDelegate : inherits from NSObject< Implements GKMatchDelegate protocol >
@interface SFMatchDelegate : NSObject< GKMatchDelegate >
{
}

// any @property here

@end



// Usually in another file:
@implementation SFMatchDelegate

//any @synthesize statements

// "override"/implement protocol "Tasks"

//Receiving Data from Other Players
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID
{
}

//Receiving State Notifications About Other Players
- (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state
{
}

//Handling Errors
- (void)match:(GKMatch *)match didFailWithError:(NSError *)error
{
}

//Reinviting a Player
- (BOOL)match:(GKMatch *)match shouldReinvitePlayer:(NSString *)playerID
{
  return YES ;
}

@end

They play a game of odds.  “If we sell lots of shitty product at a cheap price, with 1/5 dead, then we make money b/c 1/5 will buy the dead product and customers won’t want to pay $15 to return a $20 item.”

 

 

Here is my ray sphere intersection code. Pay special attention to the __6__ possible results for the ray’s situation wrt the sphere.

bool Sphere::intersectExact( const Ray& ray, Intersection* intn )
{
  // an important override

  //If E is the starting point of the ray,
  //.. and L is the end point of the ray,
  //.. and C is the center of sphere you're testing against
  //.. and r is the radius of that sphere

  // Compute:
  //    d = L - E ; // Direction vector of ray, from start to end
  //    f = E - C ; // Vector from center sphere to ray start
  const Vector &d = ray.direction ;
  Vector f = ray.startPos - this->pos ;

  real a = d • d ;  // a is nonnegative, this is actually always 1.0
  real b = 2*(f • d) ;
  real c = f • f - radius*radius ;

  real discriminant = b*b-4*a*c;
  if( discriminant < 0 )
  {
    return false ;  // no intersections.
    // the geometric meaning of this is
    // the ray totally misses the sphere.
  }
  else
  {
    // ray didn't totally miss sphere,
    // so there is a solution to
    // the equation.

    discriminant = sqrt( discriminant );
    // just t1 here implies t1 VALID (ie 0 ≤ t1 ≤ len)
    // 3x HIT cases:
    //       -o->       --|-->  |            |  --|->
    // Impale(t1,t2), Poke(t1,t2>len), ExitWound(t1<0, t2), 
    
    // 3x MISS cases:
    //       ->  o                     o ->              
    // FallShort (t1>len,t2>len), Past (t1<0,t2<0)
    
    // | -> |
    // CompletelyInside(t1<0, t2>len)

    // You might consider CompletelyInside a HIT, but I consider it a miss here.
    // t1 is always the smaller value, because BOTH discriminant and
    // a are nonnegative.
    real t1 = (-b - discriminant)/(2*a);
    real t2 = (-b + discriminant)/(2*a);

    // Just purely sphere info
    if( BetweenIn(t1,0,ray.length) )
    {
      // t1 is the intersection, and its closer
      // Impale, Poke
      Vector p = ray.at( t1 ) ;
      if( intn )  *intn = Intersection( p, getNormalAt( p ), this ) ;
      return true ;
    }

    // here t1 didn't intersect so we are either started
    // inside the sphere or too 
    if( BetweenIn( t2,0,ray.length ) )
    {
      // ExitWound
      Vector p = ray.at( t2 ) ;

      // We invert the normal because you are inside the sphere.
      if( intn )  *intn = Intersection( p, -getNormalAt( p ), this ) ;
      return true ;
    }

    return false ; // no intn: FallShort, Past, CompletelyInside
  }
}