use of undeclared identifier objective-c - ios

I am getting the use of undeclared identifier 'data' in the didreceiveresponse method. I have imported the Model header file which has the array and data declared. I found that if I declare them inside the viewcontroller.h file the error goes away. What is the cause of this problem?
#import "ViewController.h"
#import "DetailViewController.h"
//#import "Model.h"
#import "Model.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL *url = [NSURL URLWithString:#"https://s3.amazonaws.com/jon-hancock-phunware/nflapi-static.json"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
data = [[NSMutableData alloc]init];
}
This is the model header file.
#import <UIKit/UIKit.h>
#interface Model : UIViewController
//NSArray *bars;
//NSMutableData *data;
#property (nonatomic, retain) NSArray *bars;
#property (nonatomic, retain) NSMutableData *data;
#end
This fixes the error defining the variables inside the viewcontroller.h file.
import
#interface ViewController : UIViewController {
IBOutlet UITableView *mainTableView;
NSArray *bars;
NSMutableData *data;
}
#end

It's Objective-C not Swift. You access properties with self.data or _data. It doesn't know well enough to look to your global variables unless you're explicit about it. Also, I would lean towards self.data over directly accessing _data so the setter gets called. In this case, it's almost certainly not going to be an issue but setting ivars directly with an underscore can mess up key value observation and might have unexpected consequences that are difficult to debug.

Related

Setting up delegate for NSURLSession and unit testing it

I'm currently trying to set up a custom delegate on an async dataTaskWithRequest via NSURLSession. I've set up the protocol and implemented the delegate method, but I am stuck at figuring out whether I've implemented it correctly, and how to unit test it. Specifically, I'd like to test if the delegate returns something after it has been called, and test with a live API call. I've tried testing via the approach suggested here (OCUnit test for protocols/callbacks/delegate in Objective-C), but the test fails, probably because I'm missing something or am not taking into account the async call. Code of attempted delegate implementation and unit test are below.
Delegate protocol declaration:
#include "PtvApiPublic.h"
#ifndef PtvApiDelegate_h
#define PtvApiDelegate_h
#class PtvApi;
#protocol PtvApiDelegate <NSObject>
-(void) ptvApiHealthCheck: (PtvApi *) sender;
#end
#endif /* PtvApiDelegate_h */
Header file:
#include "PtvApiDelegate.h"
#ifndef PtvApi_h
#define PtvApi_h
#interface PtvApi : NSObject
#property (nonatomic, weak) id <NSURLSessionDelegate> delegate;
- (void)ptvApiHealthCheck;
#end
#endif /* PtvApi_h */
Snippet of PtvApi.m
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonHMAC.h>
#import <CommonCrypto/CommonDigest.h>
#import "PtvApiPublic.h"
#import "PtvApiPrivate.h"
#import "PtvApiDelegate.h"
#implementation PtvApi
#synthesize delegate;
...
- (void)ptvApiHealthCheck
{
NSString *fullUrl = [self GenerateRequestUrl];
NSURLSession *apiSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:delegate delegateQueue:nil];
NSURL *apiUrl = [NSURL URLWithString: fullUrl];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:apiUrl];
[apiSession dataTaskWithRequest:urlRequest];
}
#end
Unit test:
#import <XCTest/XCTest.h>
#import "PtvApiPublic.h"
#interface APIDelegateTests : XCTestCase <NSURLSessionDelegate>
{
PtvApi *testApi;
BOOL callbackInvoked;
}
#end
#implementation APIDelegateTests
- (void)setUp {
[super setUp];
testApi = [[PtvApi alloc] init];
testApi.delegate = self;
}
- (void)tearDown {
testApi.delegate = nil;
[super tearDown];
}
- (void)testThatApiCallbackWorks {
[testApi ptvApiHealthCheck];
XCTAssert(callbackInvoked, #"Delegate should return something, I think...");
}
#end
Alright I figured it out myself with the help of Apple's documentation for NSURLSession and the blog at http://www.infinite-loop.dk/blog/2011/04/unittesting-asynchronous-network-access/. I've tested it with the live URL for now, I'll update the answer when I add API mocking to my unit test and make the unit test more robust.
The short of it is that NSURLSession has its own delegate methods, and in this case where dataTaskWithRequest is used, an NSURLSessionDataDelegate can be set up and used to retrieve the API results.
The code for the delegate declaration is mostly correct, I just needed to change NSURLSessionDelegate to NSURLSessionDataDelegate in the header file.
The unit test requires a bit of set up, but is otherwise pretty straightforward. It involves initialising the class with the NSURLSession call, setting the object's delegate to self, and initialise a flag variable to NO. The flag variable will be set to YES when the delegate is called, which is what I am initially testing for. The fully set up unit test is below.
#interface APIDelegateTests : XCTestCase <NSURLSessionDataDelegate>
{
PtvApi *testApi;
BOOL callbackInvoked;
}
#end
#implementation APIDelegateTests
- (void)setUp {
[super setUp];
testApi = [[PtvApi alloc] init];
testApi.delegate = self;
callbackInvoked = NO;
}
- (void)tearDown {
testApi.delegate = nil;
[super tearDown];
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
callbackInvoked = YES;
}
// Method is credit to Claus Brooch.
// Retrieved from http://www.infinite-loop.dk/blog/2011/04/unittesting-asynchronous-network-access/ on 10/04/2016
- (BOOL)waitForCompletion:(NSTimeInterval)timeoutSecs {
NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeoutSecs];
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeoutDate];
if([timeoutDate timeIntervalSinceNow] < 0.0)
break;
} while (!callbackInvoked);
return callbackInvoked;
}
- (void)testThatApiCallbackWorks {
[testApi ptvApiHealthCheck];
XCTAssert([self waitForCompletion:30.0], #"Testing to see what happens here...");
}
#end

iOS should model objects be able to access network with NSURLSession

I am in the middle of an app re-design and am refactoring and extending my model.
One aspect of my apps model is that the app retrieves data from a web service and populates the model.
My question is: Should my model objects have the capability to implement NSURLSession or should I rely on the VC to provide the connection?
I'm asking from a best practices standpoint. What's the best way to think about this? Should the model be totally on its own or should it have network access?
One consideration is that these model objects are essentially useless without data from the network, meaning data from the Internet is a fundamental aspect of their existence.
If we take SOLID — especially the S for Single Responsible Principle — in account, it becomes obvious, that neither the VC nor the model should do the networking:
a VC's single responsible would be to handle views
the model's purpose would be to hold data
networking should be done by a third class, a networking controller.
This three points will fulfill SOLID, but how do you get data from the network into model objects show on a view?
Well, this depends on your overall architectural design on the app, but a common approach would be to use callback — either a delegate protocol or a block — with your network controller.
You create a network controller in the app delegate and pass it from view controller to view controller via properties to any place in the app were newly fetched data is needed. I wouldn't use a singleton here, as that violates O, I & D of SOLID.
Add a class method to your model +(NSArray *)modelObjectsFromDictionaries:(NSArray *) or similar.
In the view controller you can now do
-(void)viewDidLoad
{
[super viewDidLoad];
__weak typeof(self) weakSelf = self;
[self.networkController fetchModels:^(NSArray *modelDictionaries, NSError *error){
typeof(weakSelf) self = weakSelf;
if(self) {
if(!error){
[self.dataSource addOrUpdateData:[Model modelObjectsFromDictionaries:modelDictionaries]];
} else {
// error handling
}
}
}];
}
This is just a starting point. For more complicated APIs it might be useful to use an api controller that itself uses the networking controller and maybe a persistence controller.
Although instead of a Model class method you might want to use some sort of mapping and abstract factory pattern… But all this things would require more information about your app and are out of the scope for this question.
Update:
I created a sample project to demonstrate this.
It is slightly different than what I say above:
As it uses a table view, I am using a data source class to populate it. Instead of the view controller the data source will tell the network controller to fetch new data.
I am using OFAPopulator for this, a library written by me to populate table views and collection views in a SOLID-conform fashion, or to «Keep view controllers clean and MVC smart».
#import "AppDelegate.h"
#import "VSNetworkController.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self.window.rootViewController setValue:[[VSNetworkController alloc] initWithBaseURL:[NSURL URLWithString:#"http://api.goeuro.com/api/v2/"]]
forKey:#"networkController"];
return YES;
}
#end
// VSNetworkController.h
#import <Foundation/Foundation.h>
#interface VSNetworkController : NSObject
-(instancetype)initWithBaseURL:(NSURL *) baseURL;
-(void)suggestionsForString:(NSString *)suggestionString
responseHandler:(void(^)(id responseObj, NSError *error))responseHandler;
#end
// VSNetworkController.m
#import "VSNetworkController.h"
#interface VSNetworkController ()
#property (nonatomic, strong) NSURL *baseURL;
#end
#implementation VSNetworkController
-(instancetype)initWithBaseURL:(NSURL *)baseURL
{
self = [super init];
if (self) {
_baseURL = baseURL;
}
return self;
}
-(void)suggestionsForString:(NSString *)suggestionString
responseHandler:(void(^)(id responseObj, NSError *error))responseHandler
{
NSURL *url = [self.baseURL URLByAppendingPathComponent:[NSString stringWithFormat:#"position/suggest/en/%#", suggestionString]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *connectionError) {
responseHandler([NSJSONSerialization JSONObjectWithData:data options:0 error:nil], connectionError);
}];
}
#end
// VSLocationSuggestion.h
#import <Foundation/Foundation.h>
#import CoreLocation;
#interface VSLocationSuggestion : NSObject
#property (nonatomic, copy, readonly) NSString *name;
#property (nonatomic, copy, readonly) NSString *country;
#property (nonatomic, strong, readonly) CLLocation *position;
+(NSArray *)suggestionsFromDictionaries:(NSArray *)dictionaries;
#end
// VSLocationSuggestion.m
#import "VSLocationSuggestion.h"
#interface VSLocationSuggestion ()
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *country;
#property (nonatomic, strong) CLLocation *position;
#end
#implementation VSLocationSuggestion
+(NSArray *)suggestionsFromDictionaries:(NSArray *)dictionaries
{
NSMutableArray *array = [#[] mutableCopy];
[dictionaries enumerateObjectsUsingBlock:^(NSDictionary *suggestionDict, NSUInteger idx, BOOL *stop) {
[array addObject:[[self alloc] initWithDictionary:suggestionDict]];
}];
return [array copy];
}
-(instancetype)initWithDictionary:(NSDictionary *)dict
{
self = [super init];
if (self) {
_name = dict[#"name"];
_country = dict[#"country"];
CLLocationDegrees latitude = [dict[#"geo_position"][#"latitude"] doubleValue];
CLLocationDegrees longitude =[dict[#"geo_position"][#"longitude"] doubleValue];
_position = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
}
return self;
}
#end
// VSSuggestionDataSource.h
#import <Foundation/Foundation.h>
#import <OFADataProvider.h>
#class VSNetworkController;
#interface VSSuggestionDataSource : NSObject <OFADataProvider>
-(instancetype)initWithNetworkController:(VSNetworkController *)networkController;
-(void)setNewSuggestions:(NSArray *)suggetsions;
-(void)enteredStringForSuggestions:(NSString *)suggestionString;
#end
// VSSuggestionDataSource.m
#import "VSSuggestionDataSource.h"
#import "VSNetworkController.h"
#import "VSLocationSuggestion.h"
#interface VSSuggestionDataSource ()
#property (nonatomic, copy) void (^available)(void);
#property (nonatomic, strong) VSNetworkController *networkController;
#end
#implementation VSSuggestionDataSource
#synthesize sectionObjects;
-(instancetype)initWithNetworkController:(VSNetworkController *)networkController
{
self = [super init];
if (self) {
_networkController = networkController;
}
return self;
}
-(void)dataAvailable:(void (^)(void))available
{
_available = available;
}
-(void)setNewSuggestions:(NSArray *)suggetsions
{
self.sectionObjects = suggetsions;
self.available();
}
-(void)enteredStringForSuggestions:(NSString *)s
{
__weak typeof(self) weakSelf = self;
[self.networkController suggestionsForString:s responseHandler:^(NSArray *responseObj, NSError *error) {
typeof(weakSelf) self = weakSelf;
if (self) {
if (!error && responseObj) {
NSArray *suggestion = [VSLocationSuggestion suggestionsFromDictionaries:responseObj];
[self setNewSuggestions:suggestion];
}
}
}];
}
#end
// ViewController.h
#import <UIKit/UIKit.h>
#class VSNetworkController;
#interface ViewController : UIViewController
#property (nonatomic, strong) VSNetworkController *networkController;
#end
// ViewController.m
#import "ViewController.h"
#import "VSLocationSuggestion.h"
#import <OFAViewPopulator.h>
#import <OFASectionPopulator.h>
#import "VSSuggestionDataSource.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (strong, nonatomic) OFAViewPopulator *viewPopultor;
#property (strong, nonatomic) VSSuggestionDataSource *dataSource;
- (IBAction)textChanged:(UITextField *)sender;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.dataSource = [[VSSuggestionDataSource alloc] initWithNetworkController:self.networkController];
OFASectionPopulator *sectionPopulator = [[OFASectionPopulator alloc] initWithParentView:self.tableView
dataProvider:self.dataSource
cellIdentifier:^NSString *(id obj, NSIndexPath *indexPath) {
return #"Cell";
} cellConfigurator:^(VSLocationSuggestion *obj, UITableViewCell *cell, NSIndexPath *indexPath) {
cell.textLabel.text = obj.name;
}];
sectionPopulator.objectOnCellSelected = ^(VSLocationSuggestion *suggestion, UIView *cell, NSIndexPath *indexPath ){
NSString * string =[NSString stringWithFormat:#"%#, %# (%f %f)", suggestion.name, suggestion.country, suggestion.position.coordinate.latitude, suggestion.position.coordinate.longitude];
UIAlertController *avc = [UIAlertController alertControllerWithTitle:#"Selected" message:string preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction
actionWithTitle:NSLocalizedString(#"Cancel", #"Cancel action")
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action)
{
;
}];
[avc addAction:cancelAction];
[self presentViewController:avc animated:YES completion:NULL];
};
self.viewPopultor = [[OFAViewPopulator alloc] initWithSectionPopulators:#[sectionPopulator]];
}
- (IBAction)textChanged:(UITextField *)sender
{
NSString *s = sender.text;
if ([s length]) {
[self.dataSource enteredStringForSuggestions:s];
}
}
#end;
I made this code available on github: https://github.com/vikingosegundo/LocationSugesstion

How to pass database from AppDelegate to ViewController

I don't know why this code error.
Please help.
I read some articles and I think the problem is about context.
What Should I do?
This program is about shows data in coredata to label in viewcontroller.
AppDelegate.h
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "Test.h"
#import "ViewController.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSManagedObjectContext *context = [self managedObjectContext];
Test *t = [NSEntityDescription insertNewObjectForEntityForName:#"Test"
inManagedObjectContext:context];
t.name = #"please";
return YES;}
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *label;
#property (nonatomic,strong) NSArray *temp;
#property (nonatomic,strong) NSManagedObjectContext* managedObjectContext;
#end
ViewController.m
#import "ViewController.h"
#import "Test.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize managedObjectContext;
#synthesize temp;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Test"
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSError *error;
self.temp = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
for(Test *info in temp){
_label.text = info.name;
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Test.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface Test : NSManagedObject
#property (nonatomic, retain) NSString * name;
#end
Test.m
#import "Test.h"
#implementation Test
#dynamic name;
#end
I don't know why this code error.
Please help.
I read some articles and I think the problem is about context.
What Should I do?
In your view controller, replace the line:
#synthesize managedObjectContext;
With this:
- (NSManagedObjectContext *) managedObjectContext {
return ((AppDelegate *)[[UIApplication sharedApplication] delegate]).managedObjectContext;
}
Instead of storing another, different object context in your view controller, this property will return the object context that you set up in the app delegate.
There are other ways to do this, such as creating a Core Data helper class following the Singleton pattern (as #NewYork167 suggests), but this should at least solve your current problem.
For any future reference, you can also try subclassing the NSManagedObjectContext like this:
#interface MyManagedObjectContext : NSManagedObjectContext
+ (MyManagedObjectContext *)mainThreadContext;
#end
#implementation MyManagedObjectContext
+ (MyManagedObjectContext *)mainThreadContext;
{
static MyManagedObjectContext *moc;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
moc = [[self alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
// Setup persistent store coordinator here
});
return moc;
}
#end
Reference: Best practices for passing NSManagedObjectContext around to UITabBarController child view controllers?

SoundBoard error no visible #interface for 'NSBundle' declares the selector 'pathForRescource:ofType:'

i am trying to make a simple audio board application, i am following the Apple documentation on the AVFoundationPlayer, but i keep getting this error (no visible #interface for 'NSBundle' declares the selector 'pathForRescource:ofType:' ) and i have searched for an hour, with no result.
my .h file
#import <UIKit/UIKit.h>
#import <AVFoundation/AVAudioPlayer.h>
#interface ViewController : UIViewController <AVAudioPlayerDelegate> {
}
//actions
-(IBAction)playSound1;
-(IBAction)playSound2;
-(IBAction)playSound3;
-(IBAction)playSound4;
#property (nonatomic, strong) AVAudioPlayer *player;
#end
my .m file
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize player;
- (void)viewDidLoad
{
NSString *soundFilePath1 =
[[NSBundle mainBundle] pathForRescource: #"trumpet"
ofType: #"mp3"];
NSURL *fileURL1 = [[NSURL alloc] initFileURLWithPath: soundFilePath1];
AVAudioPlayer *newPlayer =
[[AVAudioPlayer alloc] initWithContentsOfURL:fileURL1 error:nil];
[fileURL1 release];
self.player= newPlayer;
[newPlayer release];
[player prepareToPlay];
[player setDelegate: self];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
If i can provide any other details i would be happy to help and thank you for reading.
It's a typo. You have written pathForRescource: and it is pathForResource:ofType:.
- (NSString *)pathForResource:(NSString *)name ofType:(NSString *)extension

How to create my own delegate (user defined delegate in Objective-C) [duplicate]

This question already has answers here:
How do I create delegates in Objective-C?
(20 answers)
Closed 9 years ago.
On iOS, how do I create a delegate (user defined)?
First define a declare a delegate like this -
#protocol IconDownloaderDelegate;
Then create a delegate object like this -
#interface IconDownloader : NSObject
{
NSIndexPath *indexPathInTableView;
id <IconDownloaderDelegate> delegate;
NSMutableData *activeDownload;
NSURLConnection *imageConnection;
}
Declare a property for it -
#property (nonatomic, assign) id <IconDownloaderDelegate> delegate;
Define it -
#protocol IconDownloaderDelegate
- (void)appImageDidLoad:(NSIndexPath *)indexPath;
#end
Then you can call methods on this delegate -
[delegate appImageDidLoad:self.indexPathInTableView];
Here is the complete source code of the image downloader class -
.h file -
#class AppRecord;
#class RootViewController;
#protocol IconDownloaderDelegate;
#interface IconDownloader : NSObject
{
AppRecord *appRecord;
NSIndexPath *indexPathInTableView;
id <IconDownloaderDelegate> delegate;
NSMutableData *activeDownload;
NSURLConnection *imageConnection;
}
#property (nonatomic, retain) AppRecord *appRecord;
#property (nonatomic, retain) NSIndexPath *indexPathInTableView;
#property (nonatomic, assign) id <IconDownloaderDelegate> delegate;
#property (nonatomic, retain) NSMutableData *activeDownload;
#property (nonatomic, retain) NSURLConnection *imageConnection;
- (void)startDownload;
- (void)cancelDownload;
#end
#protocol IconDownloaderDelegate
- (void)appImageDidLoad:(NSIndexPath *)indexPath;
#end
.m file -
#import "IconDownloader.h"
#import "MixtapeInfo.h"
#define kAppIconHeight 48
#define TMP NSTemporaryDirectory()
#implementation IconDownloader
#synthesize appRecord;
#synthesize indexPathInTableView;
#synthesize delegate;
#synthesize activeDownload;
#synthesize imageConnection;
#pragma mark
- (void)dealloc
{
[appRecord release];
[indexPathInTableView release];
[activeDownload release];
[imageConnection cancel];
[imageConnection release];
[super dealloc];
}
- (void)startDownload
{
self.activeDownload = [NSMutableData data];
// alloc+init and start an NSURLConnection; release on completion/failure
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:
[NSURLRequest requestWithURL:
[NSURL URLWithString:appRecord.mixtape_image]] delegate:self];
self.imageConnection = conn;
[conn release];
}
- (void)cancelDownload
{
[self.imageConnection cancel];
self.imageConnection = nil;
self.activeDownload = nil;
}
#pragma mark -
#pragma mark Download support (NSURLConnectionDelegate)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.activeDownload appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
// Clear the activeDownload property to allow later attempts
self.activeDownload = nil;
// Release the connection now that it's finished
self.imageConnection = nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// Set appIcon and clear temporary data/image
UIImage *image = [[UIImage alloc] initWithData:self.activeDownload];
self.appRecord.mixtape_image_obj = image;
self.activeDownload = nil;
[image release];
// Release the connection now that it's finished
self.imageConnection = nil;
// call our delegate and tell it that our icon is ready for display
[delegate appImageDidLoad:self.indexPathInTableView];
}
#end
and here is how we use it -
#import "IconDownloader.h"
#interface RootViewController : UITableViewController <UIScrollViewDelegate, IconDownloaderDelegate>
{
NSArray *entries; // the main data model for our UITableView
NSMutableDictionary *imageDownloadsInProgress; // the set of IconDownloader objects for each app
}
in .m file -
- (void)startIconDownload:(AppRecord *)appRecord forIndexPath:(NSIndexPath *)indexPath
{
IconDownloader *iconDownloader = [imageDownloadsInProgress objectForKey:indexPath];
if (iconDownloader == nil)
{
iconDownloader = [[IconDownloader alloc] init];
iconDownloader.appRecord = appRecord;
iconDownloader.indexPathInTableView = indexPath;
iconDownloader.delegate = self;
[imageDownloadsInProgress setObject:iconDownloader forKey:indexPath];
[iconDownloader startDownload];
[iconDownloader release];
}
}
here is delegate gets called automatically -
// called by our ImageDownloader when an icon is ready to be displayed
- (void)appImageDidLoad:(NSIndexPath *)indexPath
{
IconDownloader *iconDownloader = [imageDownloadsInProgress objectForKey:indexPath];
if (iconDownloader != nil)
{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:iconDownloader.indexPathInTableView];
// Display the newly loaded image
cell.imageView.image = iconDownloader.appRecord.appIcon;
}
}
This is basic concepts to create a own delegate
Delegates are very useful to control transfer within the array of view controllers in app manually. Using delegates you can manage the control flow very well.
here is small example of own delegates....
Create a protocol class.... (.h only)
SampleDelegate.h
#import
#protocol SampleDelegate
#optional
#pragma Home Delegate
-(NSString *)getViewName;
#end
Import above protocol class in the class whom you want to make delegate of another class. Here in my ex. I m using AppDelegate to make delegate of The HomeViewController's Object.
also add above DelegateName in Delegate Reference < >
ownDelegateAppDelegate.h
#import "SampleDelegate.h"
#interface ownDelegateAppDelegate : NSObject <UIApplicationDelegate, SampleDelegate> {
}
ownDelegateAppDelegate.m
//setDelegate of the HomeViewController's object as
[homeViewControllerObject setDelegate:self];
//add this delegate method definition
-(NSString *)getViewName
{
return #"Delegate Called";
}
HomeViewController.h
#import
#import "SampleDelegate.h"
#interface HomeViewController : UIViewController {
id<SampleDelegate>delegate;
}
#property(readwrite , assign) id<SampleDelegate>delegate;
#end
HomeViewController.h
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UILabel *lblTitle = [[UILabel alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
lblTitle.text = [delegate getViewName];
lblTitle.textAlignment = UITextAlignmentCenter;
[self.view addSubview:lblTitle];
}

Resources