I'm very new to iOS coding and I've been practicing with little app examples found online.
I'm reading examples in the "iOS Sensor Apps with Arduino" book and I've been following instructions for the serial communication example with the Adruino UNO board using the Redpark serial cable for the iPhone/iPad
I have the Redpark serial cable and their demo app, and a registered working developer profile. I've been able to communicate over serial with the demo app on the iPhone and the serial port on my computer.
In working with the example from the book and I've copied in this line to the iOS code:
bytesRead = [rscMgr read:rxBuffer length:numBytes];
However, when compiling this with the rest of the code it throws an error described as
Use of undeclared identifier "if"
I've looked everywhere for the word "if" and can't find it. I've also looked at the sample code from Redpark and the is similar if not identical, except for the buffer name.
Please let me know if I've provided enough detail and I'm forward to any advice this community may have, thanks again for offering your time.
Bellow is more of the code:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
rscMgr = [[RscMgr alloc] init];
[rscMgr setDelegate: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.
}
- (IBAction)sendString:(id)sender {
[self.textEntry resignFirstResponder];
//Add code here
}
#pragma mark - RscMgrDelegate methods
- (void)cableConnected:(NSString *)protocol {
[rscMgr setBaud:9600];
[rscMgr open];
}
- (void)cableDisconnected {
}
- (void)portStatusChanged {
- (void) readBytesAvailable:(UInt32)numBytes {
int bytesRead;
// Read the data out
**bytesRead = [rscMgr read:rxBuffer length:numBytes];**
NSLog( #"Read %d bytes from serial cable.", bytesRead);
for(int i = 0;i < numBytes;++i) {
lf.serialView.text =
[NSString stringWithFormat:#"%#%c",
self.textView.text,
((char *)rxBuffer)[i]];
}
}
- (BOOL) rscMessageReceived:(UInt8 *)msg TotalLength:(int)len {
return FALSE;
}
- (void) didReceivePortConfig {
}
#end
Related
I want to write unit tests using Apple's default SenTestingKit for the below method:
- (NSDictionary*)getValueTags {
return _tags;
}
- (NSString*)getFlag {
NSString* jo = #"";
for (NSString* key in _tags) {
jo = [jo stringByAppendingFormat:#"%#=\"%#\"&", key, [_tags objectForKey:key]];
}
if ([jo length] > 0) {
jo = [jo substringToIndex:[jo length] - 1];
}
return jo;
}
I used default SenTesting
- (void)setUp
{
[super setUp];
// Set-up code here.
}
- (void)tearDown
{
// Tear-down code here.
[super tearDown];
}
-(void)testValueTags{
}
-(void)testGetFlag{
}
I am new to writing TestCases, I need some guideline for sample methods to write test cases
A test case has four distinct phases:
set up
exercise
verify
tear down
Some of these phases can be empty. For example, most tear down happens automatically if you use ARC.
When you're starting, don't put anything into the setUp or tearDown methods. Just write a single unit test. Here's a worked example. (I'm going to change the names, because Objective-C idiom is not to use the word "get". So instead of getFlag let's just call it flag.) I'm going to call the class `Example, and I'll use ARC. And I use the abbreviation "sut" for "system under test".
- (void)testFlagGivenOneEntry
{
// set up
Example *sut = [[Example alloc] init];
[sut setTags:#{ #"key1" : #"value1" }];
// execute & verify
STAssertEqualObjects([sut flag], #"key1=\"value1\"", nil);
}
That's one test. Let's add another.
- (void)testFlagGivenTwoEntries
{
// set up
Example *sut = [[Example alloc] init];
[sut setTags:#{ #"key1" : #"value1",
#"key2" : #"value2" }];
// execute & verify
STAssertEqualObjects([sut flag], #"key1=\"value1\"&key2=\"value2\"", nil);
}
At this point, we have duplicate code: the creation of the sut. Now we can promote the variable up to an instance variable of the class. Then we create it in setUp and destroy it in tearDown:
#interface ExampleTest : SenTestCase
#end
#implementation ExampleTest
{
Example *sut;
}
- (void)setUp
{
[super setUp];
sut = [[Example alloc] init];
}
- (void)tearDown
{
sut = nil;
[super tearDown];
}
- (void)testFlagGivenOneEntry
{
[sut setTags:#{ #"key1" : #"value1" }];
STAssertEqualObjects([sut flag], #"key1=\"value1\"", nil);
}
- (void)testFlagGivenTwoEntries
{
[sut setTags:#{ #"key1" : #"value1",
#"key2" : #"value2" }];
STAssertEqualObjects([sut flag], #"key1=\"value1\"&key2=\"value2\"", nil);
}
#end
For a more involved example, see Objective-C TDD: How to Get Started.
Please help me in this what I am trying to do is I have
a Cocoa application with webkit in it.
an HTML5 based web application with local database.
I am trying to run this HTML5 application in cocoa application and get this error "Error: Unknown error Error: SECURITY_ERR: DOM Exception 18." same application is working fine in
Safari
iphone safari
UIWebkit
I have tried following things
#interface WebPreferences (WebPreferencesPrivate)
- (void) _setLocalStorageDatabasePath:(NSString *)path;
- (void) setDatabasesEnabled: (BOOL) databaseEnabled;
- (void) setLocalStorageEnabled: (BOOL) localStorageEnabled;
#end
WebPreferences* prefs = [self.mainWebVEW preferences];
[prefs _setLocalStorageDatabasePath:appdir];
[prefs setDatabasesEnabled:YES];
[prefs setLocalStorageEnabled:YES];
[prefs setDefaultFontSize:20];
only preference that seem working is font size.
Can anybody help me how to get over this?
Thanks in advance
Regards
Ankit
ok so finally resolved it all you have to do is use one more private API
#interface WebView(WebViewPrivate)
- (void)webView:(WebView *)sender frame:(WebFrame *)frame exceededDatabaseQuotaForSecurityOrigin:(id) origin database:(NSString *)databaseIdentifier;
#end
- (void)webView:(WebView *)sender frame:(WebFrame *)frame exceededDatabaseQuotaForSecurityOrigin:(id) origin database:(NSString *)databaseIdentifier
{
static const unsigned long long defaultQuota = 5 * 1024 * 1024;
if ([origin respondsToSelector: #selector(setQuota:)]) {
[origin performSelector:#selector(setQuota:) withObject:[NSNumber numberWithLongLong: defaultQuota]];
} else {
NSLog(#"could not increase quota for %#", defaultQuota);
}
}
(This is a work in progress. I wonder if someone could to improve it)
in Objective C, it's easy to resolve a hostname with NSHost.
[[NSHost hostWithName:#"www.google.com"] address]
Sadly iOS (iPhone) contains only a private version of NSHost.
I found many ways of doing this with other Objects or methods, but all of them got only IPv4 addresses in the results. So here is for the moment the only efficient method I have found.
I first tried to use the asynchronous CFHostStartInfoResolution as did bdunagan, but failed to adapt it to IPv6.
Some of you will appreciate to get a method working, so here is one, but if you know a way which would be Asynchronous I would appreciate to learn about it... cause for the moment I use a Popup to alert about the next freeze that could occur with slow cellular connection
/**
Give the IPs corresponding to a Hostname
Sometime only 1 IPv4 is shown even if there's more.
Sometime only 1 IPv6 is shown even if there's more.
Certainly due to iOS Memory optimisation when locally cached
#author Christian Gonzalvez, http://wiki.gonzofamily.com
#param hostName A hostname
#return an Array of NSString of all the corresponding IP addresses. The first
is the Canonical name, the following are IPs (all NSString)
*/
+ (NSArray *)addressesForHostname:(NSString *)hostname
{
const char* hostnameC = [hostname UTF8String];
struct addrinfo hints, *res;
struct sockaddr_in *s4;
struct sockaddr_in6 *s6;
int retval;
char buf[64];
NSMutableArray *result; //the array which will be return
NSMutableArray *result4; //the array of IPv4, to order them at the end
NSString *previousIP = nil;
memset (&hints, 0, sizeof (struct addrinfo));
hints.ai_family = PF_UNSPEC;//AF_INET6;
hints.ai_flags = AI_CANONNAME;
//AI_ADDRCONFIG, AI_ALL, AI_CANONNAME, AI_NUMERICHOST
//AI_NUMERICSERV, AI_PASSIVE, OR AI_V4MAPPED
retval = getaddrinfo(hostnameC, NULL, &hints, &res);
if (retval == 0)
{
if (res->ai_canonname)
{
result = [NSMutableArray arrayWithObject:[NSString stringWithUTF8String:res->ai_canonname]];
}
else
{
//it means the DNS didn't know this host
return nil;
}
result4= [NSMutableArray array];
while (res) {
switch (res->ai_family){
case AF_INET6:
s6 = (struct sockaddr_in6 *)res->ai_addr;
if(inet_ntop(res->ai_family, (void *)&(s6->sin6_addr), buf, sizeof(buf))
== NULL)
{
NSLog(#"inet_ntop failed for v6!\n");
}
else
{
//surprisingly every address is in double, let's add this test
if (![previousIP isEqualToString:[NSString stringWithUTF8String:buf]]) {
[result addObject:[NSString stringWithUTF8String:buf]];
}
}
break;
case AF_INET:
s4 = (struct sockaddr_in *)res->ai_addr;
if(inet_ntop(res->ai_family, (void *)&(s4->sin_addr), buf, sizeof(buf))
== NULL)
{
NSLog(#"inet_ntop failed for v4!\n");
}
else
{
//surprisingly every address is in double, let's add this test
if (![previousIP isEqualToString:[NSString stringWithUTF8String:buf]]) {
[result4 addObject:[NSString stringWithUTF8String:buf]];
}
}
break;
default:
NSLog(#"Neither IPv4 nor IPv6!");
}
//surprisingly every address is in double, let's add this test
previousIP = [NSString stringWithUTF8String:buf];
res = res->ai_next;
}
}else{
NSLog(#"no IP found");
return nil;
}
return [result arrayByAddingObjectsFromArray:result4];
}
NB: I noticed that most of the time only 1 IPv6 is returned, I suspect it's due to iOS Memory optimisation when locally cached. if you run this method again and again, sometime you have 3 IPv6, but then you have only 1 IPv4.
If you want a method to run on a background thread, the simplest way is to use performSelectorInBackground:withObject:; this is an instance method of NSObject, so any object can use it without any extra work (including, interestingly enough, class objects, which is good in this case because this is a class method):
[[self class] performSelectorInBackground:#selector(addressesForHostName:)
withObject:theHostName];
Inside the method, you will need to set up an autorelease pool for the thread. You will also need some kind of callback method set up to get the return value back to your main thread. Make sure that you don't try to do any GUI activity on the background thread. It's only safe to do that on the main thread.
+ (NSArray *)addressesForHostname:(NSString *)hostname
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Do your stuff...
// Wait until done to allow memory to be managed properly
// If we did not do this, the array might be deallocated
// before the main thread had a chance to retain it
[self performSelectorOnMainThread:#selector(addressesCallback:)
withObject:[result arrayByAddingObjectsFromArray:result4]
waitUntilDone:YES];
// Inside a class method, self refers to the class object.
[pool drain];
}
If you were not on the main thread to begin with, or if you needed more control, you could also look into NSOperation, which is more powerful and therefore requires more work. It's still easier than explicit thread management, though!
Hope that solves your problem. It sounded like you have this method doing what you need, you just need it to not block the main thread.
thanks to Josh I could do it, but here is what I had to do :
Instead of calling directly
self.ipAddressesString = [CJGIpAddress addressesForHostname:#"www.google.com"];
I call
[self resolveNow:#"www.google.com"];
And create 3 new methods:
- (void)resolveNow:(NSString *)hostname
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
[self performSelectorInBackground:#selector(hostname2ipAddresses:)
withObject:hostname];
}
- (void)hostname2ipAddresses:(NSString *)hostname
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//Here is my previous lonely line !! safely started in an other thread
self.ipAddressesString = [CJGIpAddress addressesForHostname:hostname];
[self performSelectorOnMainThread:#selector(resolutionDidFinish)
withObject:nil
waitUntilDone:YES];
[pool drain];
}
- (void)resolutionDidFinish
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
//My STUFF with self.ipAddressesString (now filled)
}
Edit:
In practice I use all of that in a Model, so I had a crash when I close the View before the end of the resolution
So in the view I added in dealloc what is necessary to avoid a crash
- (void)dealloc
{
self.model.delegate = nil;
[super dealloc];
}
Then - in the model - I test delegate before doing anything with it.
Currently I'm trying to use a NSMutableURLRequest, setting the HTTPBody to a custom written NSInputStream of mine that provides this chunks.
This would be fine if it were not for the fact that NSMutableURLRequest keeps asking me to implement more and more methods in my NSInputStream class. First it asked me to implement - streamStatus: and that was rather straightforward to implement however now it's asking for _scheduleInCFRunLoop:forMode:...
Basically I'm generating data out of an algorithm and would like to send it to the server via chunked request.
Here's the code:
#interface GERHTTPChunkInputStream : NSInputStream
{
uint8_t counter_;
}
- (GERHTTPChunkInputStream *)init;
- (void)dealloc;
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len;
- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len;
- (BOOL)hasBytesAvailable;
- (NSStreamStatus)streamStatus;
#end
#implementation GERHTTPChunkInputStream
- (GERHTTPChunkInputStream *)init {
[super init];
return self;
}
- (void)dealloc {
assert(NO);
[super dealloc];
}
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len {
NSLog(#"Getting more bytes!!!");
for (int i = 0; i < len; ++i) {
buffer[i] = ++counter_;
}
return len;
}
- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len {
return NO;
}
- (BOOL)hasBytesAvailable {
return YES;
}
- (NSStreamStatus)streamStatus {
return NSStreamStatusNotOpen;
}
#end
According to a few discussions on the net, it is difficult to subclass NSInputStream. Have a look at Multipart POST using NSInputStream or NSInputStream subclass asynchronous.
It seems that you indeed need to implement these strange private methods...
I have an object that i intalize it's propertis with call to an init function, it works fine,
when i tried to add another object and intalize it the first object didn't get the properites, how do i initalize it to more then one object with diffrent or the same properties?
- (void)viewDidLoad {
pic1 = [[peopleAccel alloc] init];
}
Class peopleAccel:
- (id) init
{
self = [super init];
if (self != nil) {
position = CGPointMake(100.0, 100.0);
velocity = CGPointMake(4.0, 4.0);
radius = 40.0;
bounce = -0.1f;
gravity = 0.5f;
dragging = NO;
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
acceleratedGravity = CGPointMake(0.0, gravity);
}
return self;
}
I see a problem with setting the delegate of sharedAccelerometer. Only one object can be a delegate of another object at a time. So you should create only one peopleAccel object.
EDIT:
If you need to send accelerometer events to more than one object, you can create a specific delegate object in charge of receiving accelerometer events and broadcasting them to your several peopleAccel objects via notifications. See this question for some hints: NSNotificationCenter vs delegation?
Create a proxy so multiple objects can receive accelerometer events.
Whether you should do this or use NSNotificationCenter is debatable and there are two camps, but personally I would use this approach. NSNotificationCenter has to check string names to recognise event type; this kind of approach could be ever so slightly faster especially with a bit more optimisation. A bit more typing but I would say also easier for someone else to follow.
Something like this...
/* PLUMBING */
/* in headers */
#protocol MyAccelSubDelegate
-(void)accelerometer:(UIAccelerometer*)accelerometer
didAccelerate:(UIAcceleration*)acceleration;
#end
#interface MyAccelSubDelegateProxy : NSObject <UIAccelerometerDelegate> {
NSMutableArray subDelegates;
}
-(id)init;
-dealloc;
-(void)addSubDelegate:(id<MyAccelSubDelegate>)subDelegate;
-(void)removeSubDelegate:(id<MyAccelSubDelegate>)subDelegate;
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:
(UIAcceleration *)acceleration;
#end
/* in .m file */
#implementation MyAccelSubDelegateProxy
-(id)init { self = [super init];
if (self!=nil) subDelegates = [[NSMutableArray alloc] init]; return self; }
-dealloc { [subDelegates release]; }
-(void)addSubDelegate:(id<MyAccelSubDelegate>)subDelegate {
[subDelegates insertObject:subDelegate atIndex:subDelegates.count]; }
-(void)removeSubDelegate:(id<MyAccelSubDelegate>)subDelegate {
for (int c=0; c < subDelegates.count; c++) {
id<MyAccelSubDelegate> item = [subDelegates objectAtIndex:c];
if (item==subDelegate) { [subDelegates removeObjectAtIndex:c];
c--; continue; }
}
}
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:
(UIAcceleration *)acceleration {
for (int c=0; c < subDelegates.count; c++)
[((id<MyAccelSubDelegate>)[subDelegates objectAtIndex:c])
accelerometer:accelerometer didAccelerate:acceleration];
}
#end
/* SOMEWHERE IN MAIN APPLICATION FLOW STARTUP */
accelProxy = [[MyAccelSubDelegateProxy alloc] init];
[UIAccelerometer sharedAcclerometer].delegate = accelProxy;
[UIAccelerometer sharedAcclerometer].updateInterval = 0.100; // for example
/* TO ADD A SUBDELEGATE */
[accelProxy addSubDelegate:obj];
/* TO REMOVE A SUBDELEGATE */
[accelProxy removeSubDelegate:obj];
/* SOMEWHERE IN MAIN APPLICATION SHUTDOWN */
[UIAccelerometer sharedAcclerometer].delegate = nil;
[accelProxy release];