Pick a next item from NSArray and then start over - objective-c

I need to toggle three different font sizes in the view controller for terms and conditions screen in an endless loop (13 , 15, 17..13, 15, 17..etc..). The screen is pretty simple, just text on full screen and a button in the navigation bar that when pressed, triggers and event handled in action.
The three fonts are represented by three NSString constants.
-(IBAction)toggleFontSize:(id)sender
{
if (self.currentFontIdentifier == regularFontIdentifier)
{
self.currentFontIdentifier = largeFontIdentifier;
}
else if (self.currentFontIdentifier == largeFontIdentifier)
{
self.currentFontIdentifier = smallFontIdentifier;
}
else
{
self.currentFontIdentifier = regularFontIdentifier;
}
self.termsAndConditionsTextView.font = [[BrandingManager sharedManager] fontWithIdentifier:self.currentFontIdentifier];
}
This code works (for now :)), but it's a nice Mediterranean IF yacht.I am wondering if there is some more mature approach. I already see the stakeholders changing their mind and adding a 4th font size. I want it to be manageable better, so basically once they add a new size I would only add it into some Array and that would be it.
Any ideas for a more mature algorithm?

Declare an instance variable for the current selected index and an array for the three fonts (small, regular and large) and try this:
-(IBAction)toggleFontSize:(id)sender {
_currentSelectedIndex = (_currentSelectedIndex + 1) % 3;
self.currentFontIdentifier = _fontIdentifiers[_currentSelectedIndex];
self.termsAndConditionsTextView.font = [[BrandingManager sharedManager] fontWithIdentifier:self.currentFontIdentifier];
}
You may not need currentFontIdentifier property since it can be obtained with _fontIdentifiers[_currentSelectedIndex]

You could use the methods 'indexOfObject and 'lastObject' of the NSArray class, something like:
Using an array of sizes:
NSArray *fontList = #[#"12","14","18"];
Then you could iterate through it using the indexOfObject
NSUInteger ix = [fontList indexOfObject:self.currentFontIdentifier] + 1;
if ([[fontList lastObject] isEqual:self.currentFontIdentifier])
ix=0;
self.currentFontIdentifier = [fontList objectAtIndex:ix];
or
NSUInteger ix = [fontList indexOfObject:self.currentFontIdentifier] + 1;
if (ix >= [fontList count])
ix=0;
self.currentFontIdentifier = [fontList objectAtIndex:ix];

Related

Objective C Math - Geometric sequence results

For my app (OSX, not IOS) i have a geometric sequence (stored in container array) generated like this:
- (void)initContainerFor:(NSInteger)maxRows
{
self.container = [[NSMutableArray alloc] init];
NSInteger start = [self.firstTextFieldValue integerValue];
NSInteger ratio = [self.secondTextFieldValue integerValue];
// ASCENDING
for (NSInteger i = 1; i < (maxRows +1 ); i++)
{
NSInteger currentValue = start * pow(ratio,i-1);
[self.container addObject:currentValue];
}
}
User can enter the "start" and "ratio" integer. I want to give a feedback if limit (MAX_INT) is exceeded. I wrote this function:
- (BOOL)maxCheck
{
if ([self.container lastObject] > INT_MAX)
return false;
return true;
}
But this seems not to work. If i enter 2 for start and 200 for ratio i have this container content:
Container: (
2,
400,
80000,
16000000,
"-1094967296",
49872896,
1384644608,
2051014656,
"-2113929216",
0
)
Please help to understand what i see in the container (strings??) and how to get a correct check for the maximum value.
As you can see from log of array, you actually exceed INT_MAX limit twice, when next element become negative. So you can just add check to initContainer: method - if element is less then the previous, INT_MAX limit is reached.
TIP: INT_MAX is a signed value.
You can not compare the value after overflow with INT_MAX, as the overflow already happened. Or put differently, by its very definition and semantics, no integer can be bigger than INT_MAX.
What you can test is
[self.container lastObject] > INT_MAX/ratio
to find the sequence element that would cause overflow in the next step.

Objective C: Using a BOOL to return 'YES' if a condition can be applied

Hi there I have some code at the moment that gives me the error ("0") is not equal to ("50") - condition not applied correctly Basically I am currently using a traditional for loop within a BOOL which goes through the list of items and checks whether or not the condition can be applied, if it can be applied to an item then the BOOL will return YES. I cannot see where I am currently going wrong and need guidance. My code is shown below:
-(BOOL)conditionCanBeApplied:(NSArray *)items{
bool itemConditionCanBeApplied = NO;
for (int i = 0; i < items.count; i++)
{
id myItem = [[items valueForKeyPath:#"itemId"]objectAtIndex: i];
if ([self.applicableItems containsObject:myItem]) {
itemConditionCanBeApplied = YES;
}
}
return itemConditionCanBeApplied;
}
First, don't mix BOOL and bool, they might be very similar but they aren't the same data type. Second, always use fast enumeration if you have a choice. I am assuming in the code below that your items collection is something like an NSArray. Also, there is no reason to test with an if statement just to set a BOOL since the test is a boolean statement. (I am doing it in my example to allow for the break) Lastly, short-circuiting your logic with a break keeps the processor from doing unnecessary work once you have at least one match.
Do something like this:
- (BOOL)conditionTest
{
BOOL itemConditionCanBeApplied = NO;
for (id item in items) {
if ([self.applicableItems containsObject:item]) {
itemConditionCanBeApplied = YES;
break;
}
}
return itemConditionCanBeApplied;
}

comparing the delta between two numbers from NSArray in Objective C

I am trying to find out the best way to compare adjacent numbers in an array and to make sure they are withing +/- 5 of the current value.
I havent done any code as I dont know where to start however I will try to explain what I am trying to achive below.
// if you had an NSArray of numbers
objectAtIndex:0 = 200
//compaire that with
object at Index:1 = 205
OR
objectAtIndex:4 = 300
//compaire that with
object at Index:5 = 305
// and also compaire it with
object at Index:4 = 495
So what I need to do is comapire each index item with the values adjacent to the current index.
I have looked on Foundation Framework Reference however I am unable to find any sort of method I may be able to use to do this.
You can try comparing like this below:-
NSArray *arr=#[#200,#300,#400,#500];
for (NSInteger i=0; i<arr.count; i++)
{
NSInteger j=i+1;
if (j <=arr.count -1)
{
if ([arr[i] compare:arr[j]]==NSOrderedAscending)
{
NSLog(#"%ld",i);
}
}
else
{
NSLog(#"%ld",i);
}
}

How to get multiple sprites to bounce off the bounds of a scene in Objective-C

I have a game I'm creating with sprite-kit with 25 sprites that are all children of one sprite node BOMNeutNode. At the beginning of the game I create 25 child nodes within the scene using a for-loop, and set them all moving in a random direction using physicsBody.velocity.
What I want to do is to get them to bounce off the bounds of the scene when they reach the edge. I assumed the code below would do the trick to begin with, but it only seems to work on 1 of the 25 nodes (for that one node it is working perfectly well). I'm thinking this must be due to where I have this code positioned in my GamePlayScene code. I thought it would be appropriate to put it in the update section of the game run loop. Maybe I have to set this rule in the node itself?
I also thought it might be that I need to identify ALL nodes named #"Neut" but I can't find the syntax to do this. Please let me know if you need more code than I have provided.
(void) update:(NSTimeInterval)currentTime {
BOMNeutNode *neut = (BOMNeutNode*)[self childNodeWithName:#"Neut"];
if (neut.position.y > self.frame.size.height-50) {
neut.physicsBody.velocity = CGVectorMake(0, -100);
} else if (neut.position.y < 50) {
neut.physicsBody.velocity = CGVectorMake(0, 100);
} else if (neut.position.x > self.frame.size.height-50) {
neut.physicsBody.velocity = CGVectorMake(-100, 0);
} else if (neut.position.x < 50) {
neut.physicsBody.velocity = CGVectorMake(100, 0);
}
}
Any suggestions would be greatly appreciated.
One easy way to do this is to add a SKPhysicsBody created with bodyWithEdgeLoopFromRect: to your SKScene. That way the physics engine can handle all the bouncing for you (with the correct angles and everything).
Typically you'd want to add it in your SKScene's didMoveToView: method. Something like:
- (void)didMoveToView:(SKView*)view {
// ... any other setup you might need ...
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(50, 50, self.size.width - 100, self.size.hight - 100)];
}
If you go this route, that should take care of everything; you shouldn't need the code you currently have in your update: method.
The problem is that you have many nodes called Neut and its finding one of them and checking if its inside the frame, what you need to do is to find all nodes with that name and run the code on all of them
-(void)update:(NSTimeInterval)currentTime {
[self enumerateChildNodesWithName:#"Neut" usingBlock:^(SKNode *node, BOOL *stop) {
if (node.position.y > self.frame.size.height-50) {
node.physicsBody.velocity = CGVectorMake(0, -100);
} else if (node.position.y < 50) {
node.physicsBody.velocity = CGVectorMake(0, 100);
} else if (node.position.x > self.frame.size.height-50) {
node.physicsBody.velocity = CGVectorMake(-100, 0);
} else if (node.position.x < 50) {
node.physicsBody.velocity = CGVectorMake(100, 0);
}
}];
}

elliptical fixture in box2d and cocos2d

I am trying to develop an iOS game in Cocos2d + Box2d. I want to use elliptical fixtures in Box2D. I tried using b2Capsule shape, but its not exactly what I want as the collision is not proper. Anyone has done this before?
For specific shapes in Box2D you will have to triangulate you original polygon (in your case an ellipse in which you keep a certain number of vertices).
For this, you can use the poly2tri excellent constrained Delaunay triangulation at http://code.google.com/p/poly2tri/
It is very simple. Here is the way I get my triangles :
- (NSArray*) triangulate:(NSArray*)verticesArray
{
NSMutableArray* outputTriangles = [[[NSMutableArray alloc] init] autorelease];
p2t::CDT* triangulationContainer;
vector<p2t::Triangle*> p2tTriangles;
vector< vector<p2t::Point*> > polylines;
vector<p2t::Point*> polyline;
for (hOzPoint2D *point in verticesArray) {
polyline.push_back(new p2t::Point([point x], [point y]));
}
polylines.push_back(polyline);
triangulationContainer = new p2t::CDT(polyline);
triangulationContainer->Triangulate();
p2tTriangles = triangulationContainer->GetTriangles();
for (int i = 0; i < p2tTriangles.size(); i++) {
p2t::Triangle& t = *p2tTriangles[i];
p2t::Point& a = *t.GetPoint(0);
p2t::Point& b = *t.GetPoint(1);
p2t::Point& c = *t.GetPoint(2);
[outputTriangles addObject:[NSArray arrayWithObjects:
[hOzPoint2D point2DWithDoubleX:a.x doubleY:a.y],
[hOzPoint2D point2DWithDoubleX:b.x doubleY:b.y],
[hOzPoint2D point2DWithDoubleX:c.x doubleY:c.y], nil]];
}
delete triangulationContainer;
for(int i = 0; i < polylines.size(); i++) {
vector<p2t::Point*> poly = polylines[i];
FreeClear(poly);
}
return [outputTriangles copy];
}
hOzPoint2D here is my custom point class, but you can pass any couple of coordinates. You don't even have to output a NSArray : you can insert this method in your body creation one.
Be careful that poly2tri has some restrictions :
you can't have twice the same point in your polygon ;
the polygon must not be self-intersecting ;
...
Read the poly2tri page to know more.
The resulting array contains triangles that you attach as fixtures to the same body.
I have used approximation as well. This has some performance drawbacks, but nothing major I guess. Code (Flash ActionScript 3, but you should be able to port that easily):
var vertices:Vector.<b2Vec2> = new Vector.<b2Vec2>();
var a:Number = _image.width / 2 / PhysicsVals.RATIO;
var b:Number = _image.height / 2 / PhysicsVals.RATIO;
var segments:int = ellipse_approximation_vertices_count; (the more the more precise shape is, but the more time it takes to do collision detection)
var segment:Number = 2 * Math.PI / segments;
for (var i:int = 0; i < segments; i++)
{
vertices.push(new b2Vec2(a * Math.cos(segment * i), b * Math.sin(segment * i)));
}
var shape:b2PolygonShape = new b2PolygonShape();
shape.SetAsVector(vertices, vertices.length);
var fixtureDef:b2FixtureDef = new b2FixtureDef();
fixtureDef.shape = shape;