I have the excellent GCDAsyncSocket running perfectly on an iOS app I have developed.
I was just playing around with setting up a Mac OSX command line program that uses the library in a similar way to log to SQLite DB but can't get it to even attempt to connect to host. No errors get generated. The program doesn't crash or anything so don't have an idea about why it's not working. Does anyone have an idea why this won't work?
The console only prints out the following (with no connect/disconnect/read/write logging i.e. the socket delegate methods are not being called):
Attempting to connect to host: 192.168.1.2 on port: 1234 to refresh
Here is quite a bit of the code I am using:
main.m
#import <Foundation/Foundation.h>
#import "LoggerClass.h"
int main(int argc, const char * argv[]) {
#autoreleasepool {
LoggerClass *logger = [[LoggerClass alloc] init];
[logger startLogging];
while (logger.status == 0) {
sleep(1);
continue;
}
return 0;
}
}
LoggerClass.h
#import <Foundation/Foundation.h>
#import "Device.h"
#interface LoggerClass : NSObject <DeviceProtocol>
#property (nonatomic, strong) FMDatabase *database;
#property (nonatomic, strong) NSArray *devices;
#property (nonatomic) int status;
- (void)startLogging;
#end
LoggerClass.m
#import "LoggerClass.h"
#import "FMDatabase.h"
#define kLoggingInProgress 0
#define kLoggingCompleted 1
#implementation LoggerClass
#synthesize database = _database;
#synthesize devices = _devices;
#synthesize status = _status;
- (id)init {
if (self = [super init]) {
self.status = kLoggingInProgress;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *path = [docsPath stringByAppendingPathComponent:#"database.sqlite"];
self.database = [FMDatabase databaseWithPath:path];
Device *d1 = [Device deviceWithName:#"Device 1" address:#"192.168.1.2" delegate:self];
self.devices = [NSArray arrayWithObjects:d1, nil];
}
return self;
}
- (void)startLogging {
for (Device *d in self.devices) {
[d refresh];
}
}
- (void)didUpdateDevice:(Device *)device {
// Insert DB entry code
NSLog(#"%# has finished Logging", device.name);
self.status = kLoggingCompleted; // This would obviously register completed if only 1 device returned but for sake of this test that fine
}
#end
Device.h
#import <Foundation/Foundation.h>
#import "GCDAsyncSocket.h"
#protocol DeviceProtocol;
#interface Device : NSObject
#property (nonatomic, weak) id<DeviceProtocol> delegate;
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *address;
#property (nonatomic, strong) GCDAsyncSocket *socket;
+ (Device *)deviceWithName:(NSString *)n address:(NSString *)a delegate:(id<DeviceProtocol>)d;
- (void)refresh;
#end
#protocol DeviceProtocol <NSObject>
#required
- (void)didUpdateDevice:(Device *)device;
#end
Device.m
#import "Device.h"
#define DEVICE_PORT 1234
#implementation Device
#synthesize delegate = _delegate;
#synthesize name = _name;
#synthesize address = _address;
#synthesize socket = _socket;
- (id)initWithName:(NSString *)name andAddress:(NSString *)address andDelegate:(id<DeviceProtocol>)delegate { // Designated Initialiser
if (self = [super init]) {
self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
self.name = name;
self.address = address;
self.delegate = delegate;
}
return self;
}
+ (Device *)deviceWithName:(NSString *)n address:(NSString *)a delegate:(id<DeviceProtocol>)d {
return [[Device alloc] initWithName:n andAddress:a andDelegate:d];
}
#pragma mark - GCD Async Socket Delegate Methods
- (void)socket:(GCDAsyncSocket *)sender didConnectToHost:(NSString *)host port:(UInt16)port {
NSLog(#"Connected to: %#", self.address);
}
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)error {
NSLog(#"Socket for %# disconnected %#.", self.address, error);
if (self.delegate) [self.delegate didUpdateDevice:self];
}
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {
NSLog(#"socket:didWriteDataWithTag:");
}
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
NSLog(#"socket:didReadData:withTag:");
[self.socket disconnect];
}
- (void)refresh {
if ([self.address length] == 0) { [self.delegate didUpdateDevice:self]; return; }
NSLog(#"Attempting to connect to host: %# on port: %i to refresh", self.address, DEVICE_PORT);
NSError *error = nil;
if (![self.socket connectToHost:self.address onPort:DEVICE_PORT withTimeout:15 error:&error]) NSLog(#"ERROR: %#", error);
NSData *dataToSend;
// Build byte data here to send to device (exact same data works on iOS)
[self.socket writeData:dataToSend withTimeout:10 tag:0];
[self.socket readDataWithTimeout:-1 tag:0];
}
#end
I just re-read your comment and realized what your main() looks like. I think that's where your problem lies. The callbacks are probably sitting in the main dispatch queue but it never gets a chance to execute them. In a Cocoa application, the main queue normally runs as part of the main run loop, but you aren't starting a run loop.
See the dispatch_get_main_queue() documentation.
I think the simplest initial fix is to replace your spin loop with this:
dispatch_main();
Related
thanks in advance for any input. I have been trying to write a program that interprets a serial command into text change in a label. I can change the label text easily with an Action attached to a button, but for some reason all my attempts at changing the label text outside that button action result in nothing being changed.
// MasterViewController.m
//
// Created by Daniel Payne on 2/28/15.
// Copyright (c) 2015 Daniel Payne. All rights reserved.
//
#import "MasterViewController.h"
#interface MasterViewController ()
#property (strong) IBOutlet NSTextField *score;
#property (nonatomic, strong) ORSSerialPort *serialPort;
#property (nonatomic, strong) MasterViewController *masterView;
#end
static MasterViewController *serialPortHelper = nil;
void connectPort(void) {
ORSSerialPort *serialPort = [ORSSerialPort serialPortWithPath:#"/dev/tty.usbmodem1411"];
serialPortHelper = [[MasterViewController alloc] init];
serialPortHelper.serialPort = serialPort;
serialPort.delegate = serialPortHelper;
serialPort.baudRate = #9600;
NSLog(#"port open");
[serialPort open];
}
int main(int argc, const char * argv[]) {
connectPort();
return NSApplicationMain(argc, argv);
}
#implementation MasterViewController
- (IBAction)pushButton:(id)sender {
[self.score setStringValue:#"1"]; //works
}
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void)awakeFromNib
{
NSLog(#"View controller instance with view: %#", self.view);
}
- (void)serialPort:(ORSSerialPort *)serialPort didReceiveData:(NSData *)data
{
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if ([string rangeOfString:#"g"].location == NSNotFound) {
NSLog(#"no goal");
} else {
[self.score setStringValue:#"1"]; //does not work
NSLog(#"GOOOOAL");
}
}
- (void)serialPortWasRemovedFromSystem:(ORSSerialPort *)serialPort
{
self.serialPort = nil;
}
- (void)serialPort:(ORSSerialPort *)serialPort didEncounterError:(NSError *)error
{
NSLog(#"%s %# %#", __PRETTY_FUNCTION__, serialPort, error);
}
- (void)serialPortWasOpened:(ORSSerialPort *)serialPort
{
NSLog(#"Serial port %s was opened", [serialPort.name UTF8String]);
}
#end
The instance of MasterViewController that is listening to your serial port is not the same one that you are seeing on screen.
You create a new one and assign it to a static variable - this is not the same one you have loaded from a nib with all its outlets connected.
Log self in both methods to confirm.
I'm trying to create a subclass of NSTask, that is augmented with a name and an activityDescription property, for the purpose of displaying status, in a UI in an OSX desktop application.
However, when I try to set the launchPath or arguments property on my subclass instance, I get these errors:
launchPath only defined for abstract class. Define -[Task launchPath]!
arguments only defined for abstract class. Define -[Task arguments]!
So, I defined setLaunchPath: and setArguments: as shown below, and I still get the same errors.
By the way, NSData stringValue is defined in NSData+Additions.h:
- (NSString *) stringValue {
return [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding];
}
Any help is greatly appreciated!
Task.h
#import <Foundation/Foundation.h>
#protocol TaskDelegate;
#interface Task : NSTask {
NSString *_launchTask;
NSArray *_arguments;
}
#property (weak, nonatomic) id<TaskDelegate> delegate;
#property (strong, nonatomic) NSString *name;
#property (strong, nonatomic) NSString *activityDescription;
//To be implemented by subclasses, should be called just before launch
- (void) setupTask;
- (BOOL) isConfigured;
//Launches the task - includes any setup required before the task is launched
- (void) launchAndWait;
- (void) setLaunchPath:(NSString *)launchPath;
- (void) setArguments:(NSArray *)arguments;
#end
#protocol TaskDelegate <NSObject>
- (void) task:(Task *)task didReceiveTaskError:(NSString *)errorString;
#end
Task.m
#import "Task.h"
#import "NSData+Additions.h"
#interface Task ()
#end
#implementation Task
- (id) init
{
self = [super init];
if (self) {
}
return self;
}
- (void) errorOccurred:(NSNotification *)notification {
if (_delegate) {
NSData *readData = [[notification userInfo] objectForKey:NSFileHandleNotificationDataItem];
NSString *outputString = [readData stringValue];
if (outputString.length)
[_delegate task:self didReceiveTaskError:outputString];
}
}
- (void) setupTask
{
//To be implemented by subclasses
}
- (BOOL) isConfigured
{
return (self.launchPath != nil);
}
//Process task conguration and execution is optional - if process task is not configured, this returns immediately
- (void) launchAndWait
{
//Allow setupTask to be used, without actually launching
if (![self isConfigured])
return;
NSPipe *errorPipe = [NSPipe pipe];
self.standardError = errorPipe;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(errorOccurred:)
name:NSFileHandleReadToEndOfFileCompletionNotification
object:[errorPipe fileHandleForReading]];
[[errorPipe fileHandleForReading] readToEndOfFileInBackgroundAndNotify];
[self launch];
[self waitUntilExit];
//Tear down
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void) setLaunchPath:(NSString *)launchPath
{
_launchTask = launchPath;
}
- (void) setArguments:(NSArray *)arguments
{
_arguments = arguments;
}
#end
I decided to use the composition approach and use NSTask inside my Task class, instead of inheritance, and it's working well.
Here is the updated class:
Task.h
#import <Foundation/Foundation.h>
#protocol TaskDelegate;
#interface Task : NSObject {
__weak id<TaskDelegate> _delegate;
NSTask *_processTask;
}
#property (weak, nonatomic) id<TaskDelegate> delegate;
#property (strong, nonatomic) NSString *name;
#property (strong, nonatomic) NSString *activityDescription;
//To be called just before launch
- (void) setupTask;
- (BOOL) processTaskConfigured;
//Launches the task - includes any setup required before the task is launched
- (void) launchAndWait;
//////////////////////////////////////////////////////////////////////////////////////////////// Process task delegation
#property (readonly) int terminationStatus;
- (BOOL) isRunning;
- (void) terminate;
#end
#protocol TaskDelegate <NSObject>
- (void) task:(Task *)task didReceiveTaskError:(NSString *)errorString;
#end
Task.m
#import "Task.h"
#import "NSData+Additions.h"
#interface Task ()
//Delegating to NSTask
#property (strong, nonatomic) NSTask *processTask;
#end
#implementation Task
- (id) init
{
self = [super init];
if (self) {
self.processTask = [NSTask new];
}
return self;
}
- (void) errorOccurred:(NSNotification *)notification {
if (_delegate) {
NSData *readData = [[notification userInfo] objectForKey:NSFileHandleNotificationDataItem];
NSString *outputString = [readData stringValue];
if (outputString.length)
[_delegate task:self didReceiveTaskError:outputString];
}
}
- (void) setupTask
{
//To be implemented by subclasses
}
- (BOOL) processTaskConfigured
{
return (_processTask.launchPath != nil);
}
//Process task conguration and execution is optional - if process task is not configured, this returns immediately
- (void) launchAndWait
{
if (!_processTask.launchPath)
return;
NSPipe *errorPipe = [NSPipe pipe];
_processTask.standardError = errorPipe;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(errorOccurred:)
name:NSFileHandleReadToEndOfFileCompletionNotification
object:[errorPipe fileHandleForReading]];
[[errorPipe fileHandleForReading] readToEndOfFileInBackgroundAndNotify];
[_processTask launch];
[_processTask waitUntilExit];
//Tear down
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
////////////////////////////////////////////////////////////////////////////////////////// Process task delegation
- (int) terminationStatus
{
if ([self processTaskConfigured]) {
return [_processTask terminationStatus];
}
return 0;
}
- (BOOL) isRunning
{
return [_processTask isRunning];
}
- (void) terminate
{
if ([self processTaskConfigured]) {
[_processTask terminate];
}
}
#end
I'm new to Xcode and Objective C, but learning fast. I am writing a Bluetooth LE app to collect data from multiple BLE devices. Happy with CoreBluetooth and am able to get what I want to function and collect the data.
However, I did it all within AppDelegate and now want to separate out different sections of code into neat Classes.
Code compiles okay but nothing runs other than AppDelegate.
Example of the class - SensorDev.m:
#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
#class SensorDev;
#protocol SensorDevDelegate<NSObject>
- (void) sensorDevDidChangeStatus:(SensorDev*)dev;
#end
#interface SensorDev : NSObject
#property (nonatomic, assign, readonly) id<SensorDevDelegate> delegate;
#property (nonatomic, readonly) CBPeripheral *peripheral;
- (id)initWithPeripheral:(CBPeripheral *)peripheral controller:(id<SensorDevDelegate>)controller;
- (void)start;
#end
Example of the class - SensorDev.h
#import "SensorDev.h"
NSString *SR1Device9DOFServiceUUIDString = #"346D0000";
NSString *SR1Device9DOFCharacteristicUUIDString = #"346D0001-12A9-11CF-1279-81F2B7A91332";
#interface SensorDev() <CBPeripheralDelegate> {
CBService *_temperatureService;
CBCharacteristic *_temperatureCharacteristic;
}
#end
#implementation SensorDev
#pragma mark - Setup
- (id)initWithPeripheral:(CBPeripheral *)peripheral controller:(id<SensorDevDelegate>)controller
{
self = [super init];
if (self) {
_peripheral = peripheral;
_peripheral.delegate = self;
_delegate = controller;
}
return self;
}
#pragma mark - Start
// -------------------------------------------------------------------------------
// Startup
// -------------------------------------------------------------------------------
- (void)start
{
NSLog(#"- (void) start"); //--Debug
CBUUID *serviceUUID = [CBUUID UUIDWithString:SR1Device9DOFServiceUUIDString];
NSArray *serviceArray = [NSArray arrayWithObjects:serviceUUID, nil];
[_peripheral discoverServices:serviceArray];
}
#end
I don't get the debug line in the log:
NSLog(#"- (void) start"); //--Debug
Looking for help guys....what am I missing ...thanks in advance ....
UPDATE
So I have a second class that does all the CoreBluetooth setup and discovery
Discovery.h
#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
#import "SensorDev.h"
// -------------------------------------------------------------------------------
//UI Setup/Protocols
// -------------------------------------------------------------------------------
#protocol DiscoveryDelegate <NSObject>
- (void) discoveryDidRefresh;
- (void) discoveryStatePoweredOff;
#end
#interface Discovery : NSObject
+(Discovery*) sharedInstance;
#property (nonatomic, assign) id<DiscoveryDelegate> discoveryDelegate;
#property (nonatomic, assign) id<SensorTagDelegate> peripheralDelegate;
// -------------------------------------------------------------------------------
// Actions
// -------------------------------------------------------------------------------
- (void) startScanningForUUIDString:(NSString *)uuidString;
- (void) stopScanning;
- (void) connectPeripheral:(CBPeripheral*)peripheral;
- (void) disconnectPeripheral:(CBPeripheral*)peripheral;
// -------------------------------------------------------------------------------
// Access to the devices
// -------------------------------------------------------------------------------
#property (readonly, nonatomic) NSMutableArray *foundPeripherals;
#property (retain, nonatomic) NSMutableArray *connectedPeripherals;
#end
Discover.m (extract)
#import "Discovery.h"
extern NSString *SR1Device9DOFServiceUUIDString; //346D0000
extern NSString *SR1Device9DOFCharacteristicUUIDString; //346D0001-12A9-11CF-1279-81F2B7A91332
#interface Discovery() <CBCentralManagerDelegate, CBPeripheralDelegate> {
CBCentralManager *_centralManager;
BOOL _pendingInit;
}
#end
#implementation Discovery
#pragma mark - Setup
+ (Discovery*) sharedInstance
{
static Discovery *this = nil;
if (!this)
this = [[Discovery alloc] init];
return this;
}
- (id) init
{
self = [super init];
if (self) {
_pendingInit = YES;
_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil];
_foundPeripherals = [[NSMutableArray alloc] init];
_connectedPeripherals = [[NSMutableArray alloc] init];
}
return self;
}
#pragma mark - CoreBluetooth Services
// -------------------------------------------------------------------------------
// CoreBluetooth Start/Stop Scanning
// -------------------------------------------------------------------------------
- (void)startScanningForUUIDString:(NSString *)uuidString
{
NSLog(#"- (void) startScanningForUUIDString"); //--Debug
[_centralManager scanForPeripheralsWithServices:
[NSArray arrayWithObjects:SR1Device9DOFServiceUUIDString, nil] options:nil];
}
- (void)stopScanning
{
NSLog(#"- (void) stopScanning"); //--Debug
}
// -------------------------------------------------------------------------------
// CoreBluetooth Connect/Disconnect
// -------------------------------------------------------------------------------
- (void) connectPeripheral:(CBPeripheral*)peripheral
{
NSLog(#"- (void) connectPeripheral"); //--Debug
if (peripheral.state == CBPeripheralStateDisconnected) {
[_centralManager connectPeripheral:peripheral options:nil];
}
}
- (void) disconnectPeripheral:(CBPeripheral*)peripheral
{
NSLog(#"- (void) disconnectPeripheral"); //--Debug
[_centralManager cancelPeripheralConnection:peripheral];
}
- (void) centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
NSLog(#"- (void) didConnectPeripheral"); //--Debug
SensorDev *tag = nil;
// Create a service instance.
tag = [[SensorDev alloc] initWithPeripheral:peripheral controller:_peripheralDelegate];
[tag start];
if (![_connectedPeripherals containsObject:tag])
[_connectedPeripherals addObject:tag];
[_peripheralDelegate sensorTagDidChangeStatus:tag];
[_discoveryDelegate discoveryDidRefresh];
}
This isn't running either ...
The reason why the classes were not running as there was nothing calling them. The class associated to the view controller was not calling the class:
BLEController.h
#import <Foundation/Foundation.h>
#interface BLEController : NSObject {
enter code here
NSMutableArray *_periphralItems;
}
#end
BLEController.m
#import "SensorDev.h"
#import "Discovery.h"
#import "BLEController.h"
#interface BLEController() <DiscoveryDelegate, SensorTagDelegate>
{
BOOL _selfSelection;
}
#end
#implementation BLEController
- (void)awakeFromNib
{
[[Discovery sharedInstance] setDiscoveryDelegate:self];
[[Discovery sharedInstance] setPeripheralDelegate:self];
_periphralItems = [NSMutableArray new];
}
- (void) discoveryDidRefresh
{
}
- (void) discoveryStatePoweredOff
{
}
- (void)sensorTagDidChangeStatus:(SensorTag *)tag
{
if(tag.peripheral.state == CBPeripheralStateConnected) {
//Do something
}
}
#end
The awakeFromNib allows me to call the other classes....
I have downloaded this project from https://github.com/yahoo/yos-social-objc .
I have changed the ConsumerKey,
ConsumerSecret
and ApplicationId but When I Run the app it crashes. It gives an error of BAD-Excess.
Does anyone has any idea of this??
please advise
Thanks
Basically its just downloaded project from yahoo's developer's page still.
This is my Complete code
SocialSampleAppDelegate.h file
#import <UIKit/UIKit.h>
#import "YOSSession.h"
#class SocialSampleViewController;
#interface SocialSampleAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
SocialSampleViewController *viewController;
YOSSession *session;
NSMutableDictionary *oauthResponse;
BOOL launchDefault;
}
#property BOOL launchDefault;
#property (nonatomic, readwrite, retain) YOSSession *session;
#property (nonatomic, readwrite, retain) NSMutableDictionary *oauthResponse;
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet SocialSampleViewController *viewController;
- (void)getUserProfile;
- (void)createYahooSession;
- (void)handlePostLaunch;
#end
SocialSampleAppDelegate.m
#import "SocialSampleAppDelegate.h"
#import "SocialSampleViewController.h"
#import "YOSUser.h"
#import "YOSUserRequest.h"
#import "NSString+SBJSON.h"
#implementation SocialSampleAppDelegate
#synthesize window;
#synthesize viewController;
#synthesize session;
#synthesize launchDefault;
#synthesize oauthResponse;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
[window addSubview:viewController.view];
[window makeKeyAndVisible];
launchDefault = YES;
[self performSelector:#selector(handlePostLaunch) withObject:nil afterDelay:0.0];
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
launchDefault = NO;
if (!url) {
return NO;
}
NSArray *pairs = [[url query] componentsSeparatedByString:#"&"];
NSMutableDictionary *response = [NSMutableDictionary dictionary];
for (NSString *item in pairs) {
NSArray *fields = [item componentsSeparatedByString:#"="];
NSString *name = [fields objectAtIndex:0];
NSString *value = [[fields objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[response setObject:value forKey:name];
}
self.oauthResponse = response;
[self createYahooSession];
return YES;
}
- (void)handlePostLaunch
{
if(self.launchDefault) {
[self createYahooSession];
}
}
- (void)createYahooSession
{
// create session with consumer key, secret and application id
// set up a new app here: https://developer.yahoo.com/dashboard/createKey.html
// because the default values here won't work
self.session = [YOSSession sessionWithConsumerKey:#"MYConsumer KEy"
andConsumerSecret:#"MY Secret"
andApplicationId:#"My APPID"];
if(self.oauthResponse) {
NSString *verifier = [self.oauthResponse valueForKey:#"oauth_verifier"];
[self.session setVerifier:verifier];
}
BOOL hasSession = [self.session resumeSession];
if(!hasSession) {
[self.session sendUserToAuthorizationWithCallbackUrl:nil];
} else {
[self getUserProfile];
}
}
- (void)getUserProfile
{
// initialize the profile request with our user.
YOSUserRequest *userRequest = [YOSUserRequest requestWithSession:self.session];
// get the users profile
[userRequest fetchProfileWithDelegate:self];
}
- (void)requestDidFinishLoading:(YOSResponseData *)data
{
NSDictionary *userProfile = [[data.responseText JSONValue] objectForKey:#"profile"];
// NSLog(#"%#",[userProfile description]);
if(userProfile) {
[viewController setUserProfile:userProfile];
}
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
#end
SocialSampleViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
[nicknameLabel setText:#"loading..."];
}
- (void)setUserProfile:(NSDictionary *)data
{
NSString *welcomeText = [NSString stringWithFormat:#"Hey %# %#!",
[[data objectForKey:#"profile"] objectForKey:#"givenName"],
[[data objectForKey:#"profile"] objectForKey:#"familyName"]];
[nicknameLabel setText:welcomeText];
}
info plist
I am writing a code that reads data from a http connection and stores in a byte array.
I have written my own NSOperation class. Reference of the code is
Concurrent Operations Demystified
My HttpWorker class declaration is like
#interface HttpWorker : NSOperation{
NSString *param;
double requestCode;
BOOL isLive;
long initSleep;
BOOL _isFinished;
BOOL _isExecuting;
NSURL *_url;
NSURLConnection *_connection;
NSData *_data;
}
#property (nonatomic, retain) NSString *param;
#property (nonatomic) double requestCode;
#property (nonatomic) BOOL isLive;
#property (nonatomic) long initSleep;
#property (readonly) BOOL isFinished;
#property (readonly) BOOL isExecuting;
#property (readonly, copy) NSURL *url;
#property (nonatomic, retain) NSURLConnection *httpCon;
#property (readonly, retain) NSData *data;
-(id)initWithUrl:(NSURL *)_url;
-(void) setRequestParameters:(NSString *)parameters iRequestCode:(double)iRequestCode initialSleep:(long)initialSleep;
#end
And my HttpWorker.m class is like
#import "HttpWorker.h"
#import "Resources.h"
#implementation HttpWorker
#synthesize param;
#synthesize requestCode;
#synthesize isLive;
#synthesize initSleep;
#synthesize isFinished = _isFinished;
#synthesize isExecuting = _isExecuting;
#synthesize url = _url;
#synthesize data = _data;
-(id) initWithUrl: (NSURL *)Url{
self = [super init];
if(self == nil){
return nil;
}
_url = [Url copy];
_isExecuting = NO;
_isFinished = NO;
return self;
}
-(BOOL) isConcurrent{
return YES;
}
-(void) start{
if(![NSThread isMainThread]){
[self performSelectorOnMainThread:#selector(start) withObject:nil waitUntilDone:NO];
return;
}
[self willChangeValueForKey:#"isExecuting"];
_isExecuting = YES;
[self didChangeValueForKey:#"isExecuting"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:_url];
NSLog(#"Connecting... %#",_url);
_connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately: YES];
if(_connection == nil){
NSLog(#"connection is nil");
}
}
-(void) setRequestParameters:(NSString *)parameters iRequestCode:(double)iRequestCode initialSleep:(long)initialSleep {
self.param = parameters;
self.requestCode = iRequestCode;
self.initSleep = initialSleep;
}
/////////////////////////// delegate methods ///////////////////////////////
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"receieved response...");
_data = [[NSData alloc] init];
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)incomingData {
NSLog(#"receieved data...");
}
-(void) connectionDidFinishLoading:(NSURLConnection *) connection {
NSLog(#"connection did finish loading...");
}
#end
Problem is that when i run this code and add httpworker object to the NSOperationQueue, the code runs successfully and _connection is not nil but none of the delegate methods is executed. Can anyone please help?
Thanks and Best Regards...
Your delegate for the connection is "self" (= your NSOperation object). I assume this object is already gone when the connection wants to send messages to the delegate.
Your NSOperation does not have a "main" implementation. Consequently nothing will happen after the thread is started. It will (asynchronously!) fire the NSOperation and quit.
See:
http://developer.apple.com/mac/library/documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html#//apple_ref/occ/instm/NSOperation/main
Bottom line: I highly recommend ASIHTTPRequest for this kind of task.
http://allseeing-i.com/ASIHTTPRequest/