My product owner wants us to report more information on the state of the product when a user contacts customer service through an in-app form.  The form eventually results in an email being sent to a customer service email list and handled elsewhere.The part I'm struggling with is how to augment my existing iOS project to allow for some controller to collect diagnostic information from a variety of disparate classes, and do it in a way that's minimally invasive and won't cause a headache if refactoring later.BlocksI've experimented with a few ideas, including having an interface that allows an arbitrary class to register a block to be executed when attempting to collect the diagnostic information:[DiagnosticCollectionController addBlockForDiagnosis:^(DiagnosticCollectionController *controller){    // Add some information here to the controller to send in the diagnostic report}];NotificationsAnother idea I had in mind was to have the diagnostic controller broadcast a notification when it's ready to start gathering information, so that other objects can attach what they need to.  The (potential) advantage here is that I can get away from using blocks thus prevent myself from having block copy issues:[[NSNotificationCenter defaultCenter] addObserver:self                                          selector:@selector(someSelectorToHandleDiagnosticPopulation:)                                              name:DiagnosticCollectionControllerWillSendDiagnostics                                            object:someDiagnosticController];// Elsewhere- (void) someSelectorToHandleDiagnosticPopulation:(NSNotification *)note {    DiagnosticController *controller = [note object];    [controller addDiagnosticData:someDataDictionary];}
Architecture for application-wide diagnostic-gathering tool?
architecture;ios
Finally, I went with a setup close to what Randall suggested, after some more thinking and some distraction.The interfaces that handle coordinating the diagnostic work look like this:@interface DiagnosticController+ (void) addDiagnosticProvider:(id<DiagnosticProvider>)provider;+ (void) removeDiagnosticProvider:(id<DiagnosticProvider>)provider;@end@protocol DiagnosticProvider <NSObject>- (NSDictionary *) diagnosticData;@endThe DiagnosticController itself keeps a list of __unsafe_unretained pointers so objects can remove themselves from the list of providers when they dealloc.  I went with __unsafe_unretained to make this backward compatible with earlier versions of iOS instead of, say, NSHashTable with the NSHashTableWeakMemory option.  If I have some time in the future, I might cluster the DiagnosticController to allow for multiple backing stores depending on the runtime.