Особого смысла нет, но есть два общих.
Первый связан с базами данных, персистентными слоями, графикой и другими зверями, где вам необходимо некоторое представление о «области действия», «подключении» или «состоянии». Например, при сохранении данных в базу данных вам обычно нужно открыть базу данных, а затем сохранить «дескриптор» БД, на который вы будете ссылаться в последующих операциях. Может быть много разных связей и, таким образом, много разных «ручек». Другими словами, может быть много DB контекстов . То же самое касается OpenGL.
Контекст также часто используется в различных API обратного вызова и передачи селектора. Здесь это просто часть данных, которые вы хотели бы получить, когда происходит обратный вызов или извиняется селектор. Обычный вариант использования для этого - когда вы подписываетесь несколько раз и вам нужно различать эти случаи:
// In one part of code not far away.
[anObject subscribeToEvent:NSObjectEventFoo withContext:@"one"];
// Somewhere else.
[anObject subscribeToEvent:NSObjectEventFoo withContext:@"two"];
// And when the callback happens:
- (void) eventFooHappenedInContext: (id) context
{
if ([context isEqual:@"one"]) { /* something */ }
if ([context isEqual:@"two"]) { /* something else */ }
}
Контекст также используется в API сортировки, как в NSArray
, который вы упомянули. Например, если вы хотите отсортировать объекты по некоторому весу, хранящемуся в NSDictionary
, вы можете использовать контекст для передачи весов:
NSInteger weightSort(id obj1, id obj2, void *context)
{
NSDictionary weights = (NSDictionary*) context;
const int weight1 = [[weights objectForKey:obj1] intValue];
const int weight2 = [[weights objectForKey:obj2] intValue];
if (weight1 < weight2)
return NSOrderedAscending;
else if (weight1 > weight2)
return NSOrderedDescending;
else
return NSOrderedSame;
}
(Это немного надумано, но я думаю, вы поняли.)
Мне показалось интересным, что контекст во многих случаях является просто решением бедного человека для замыканий, которые отсутствуют / отсутствуют в языке. Потому что с замыканиями вы можете просто передать отдельный обработчик обратного вызова, как в JavaScript:
anObject.subscribeToEvent(eventFoo, function() { /* do something */ });
anObject.subscribeToEvent(eventFoo, function() { /* do something else */ });
Это часто было бы более элегантно, чем разграничение вариантов использования в обратном вызове. Теперь в Objective-C можно делать что-то подобное с блоками (см. Учебник Майка Эша ).