Display Random String from a Selection? - iphone

I'm just palying around with Xcode (I'd like to start making iPhone apps) and I was wondering how you would make this progress HUD randomly show strings? Currently:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText = #"Give me a sec...";
}
So I'd like it to randomly choose from things like, 'Give me a sec', 'Hold on', etc. Just something I'd like to learn, thanks for any help!
I tried searching around but it's very hard to think of appropiate search terms!

Put all your strings in an array, get a random number between 0 and size of array (minus 1), and use that to retrieve the msg. Put in method to make it easy. Define the msg array outside though, for better code.
Something similar to this:
-(NSString*) getRandomMsg {
NSArray *arr = #[#"Give me a sec", #"Hold on"];
int randNum = arc4random_uniform([arr count]); // or arc4random, possibly rand % max
NSString *msg = arr[randNum];
return msg;
}

Related

Using an array of strings for UISlider

I want to change a UILabel with strings based on an array. Here is what I have so far:
- (IBAction) sliderValueChanged:(UISlider *)sender {
scanLabel.text = [NSString stringWithFormat:#" %.f", [sender value]];
NSString *wholeText = #"Very Bad";
self.scanLabel.text = wholeText;
}
Instead of just "Very Bad," I want different values to show "very Bad, Bad, Okay, Good, Very Good."
Where do I declare the NSMutableArray, and how do I implement it with the slider?
Update: Thank you all for your help! (I love stackoverflow)
This is not compiler checked...but you may get some idea.
NSArray *texts=[NSArray arrayWithObjects:#"very Bad", #"Bad", #"Okay", #"Good", #"Very Good",nil];
NSInteger sliderValue=[sender value]; //make the slider value in given range integer one.
self.scanLabel.text=[texts objectAtIndex:sliderValue];
You declare it in the same class as the above method.
Let's say it's called wholeTexts.
The code will look like this:
- (IBAction) sliderValueChanged:(UISlider *)sender {
scanLabel.text = [NSString stringWithFormat:#" %.f", [sender value]];
NSString *wholeText = [wholeTexts objectAtIndex:(wholeTexts.count - 1) * (int)(sender.value - sender.minimumValue)/(sender.maximumValue - sender.minimumValue)];
self.scanLabel.text = wholeText;
}
Put your text values into an array
NSArray* array = #[#"very Bad", #"Bad", #"Okay", #"Good", #"Very Good"];
set your slider to have a min value of 0 and maximum value of 4
turn your [sender value] into an int, eg floor([sender value])
pick an item from the array using your int, eg
NSString* result = [array objectAtIndex:myInt];
You can implement the array anywhere you want, as long as it's created before you need to use the slider. Sliders can only have a value between 0 and 1 in iOS, so you'll need to multiply the value by something to get numbers as high as the number of items in your array (minus 1), and you'll need to convert them to an integer, so you can use that value as the index into the array. Something like this:
- (IBAction) sliderValueChanged:(UISlider *)sender {
scanLabel.text = [myArray objectAtIndex:(int)(sender.value * 10)];
}

Display JSON as List in ViewController (Not in TableView)

I am producing a JSON string that I need to parse out and display onto the page. My JSON string outputs information about the contents of a CD like this:
[{"song_name":"Song 1","artist":"John","price":"$1"},
{"song_name":"Song 2","artist":"Anna","price":"$2"},
{"song_name":"Song 3","artist":"Ryan","price":"$3"}]
I would like to display the contents in my viewController in a list format displaying the song_name, artist, and price. I do not want to use a tableView to display this information, but would rather just have a list displayed. How might I go about doing this? I would assume that I need to use NSJSONSerialization, but have only used that for a tableView in the past. Thank you!
In addition to other answers, you can use only one label, just create NSMutableString (for dynamicly adding tracks info) with #"\n" between tracks info, pass it to label.text and set UILabel's property numberOfLines to 0
Follow these steps:
Parse the JSON and store the key-value pair(NSDictionary of CDs) in an NSArray (say infoArray)
Add a UIScrollview as a subview on your viewController's view.
Allocate UILabels dynamically, depending on infoArray count. Looking at your data I believe you can initialize labels with static frames i.e your y can remain static.
Add the text from the infoArray on this label.
Still, I would suggest use UITableView only. It is much simpler and a better approach
You make an array of dictionaries using NSJSONSerialization indeed, then you parse this array one by one and create a view of every dictionary. You're probably best of using a method for this:
-(UIView *) listView: (NSString *)songName andArtist:(NSString *)artist andPrice:(NSString *)price andIndex:(int)viewIndex {
//create your view here and do anything you want
UIView *subView = [[UIView alloc] init] autoRelease];
subView.frame = CGRectMake(0, viewIndex * 70, self.view.frame.width, 70);
//add labels and other stuff
// return the view
return subView;
}
The you add it to the current view by setting different Y values so they appear underneath each other by using the viewIndex of the former method... So if you have an array it goes something like this:
for (int i = 0; i < [array count]; i++) {
NSDictionary *dict = [array objectAtIndex:i];
NSString *songName = [dict valueForKey:#"song_name"];
NSString *artist = [dict valueForKey:#"artist"];
NSString *price = [dict valueForKey:#"price"];
UIView *tempView = [self listView:songName andArtist:artist andPrice:price andIndex:i];
[self.view addSubView:tempView];
}
You have to add it all to a scrollview otherwise you will run into the problem of to many rows on the page. Google for UIScrollView if you don't know how.
But I would recommend against this approach.. Tableviews are there with a reason. They are made for this stuff. Because the also provide for scrolling, drawing and refreshing. If you can, use them!

iOS Beginner: Tweet calculated result (HowTo add a result to a NSString and tweet it)

I am trying to integrate twitter framework into my app to give the users the option
to tweet their calculated results. Tweeting works fine but I'm unable to get the results
to the Twitter window automatically.
User enters played holes and strokes needed on the golf course.
App calculates average strokes per hole.
After clicking on tweet results button twitter window appears and has already
the calculated average as a part of the twitter message.
Right now the Twitter window shows up but I can only assign static text as default.
Can anyone help?
Here is my code:
CALCULATION: (works fine)
- (IBAction)calculateNow:(id)sender {
double holes = [[holesTextField text]doubleValue];
double strokes = [[strokesTextField text]doubleValue];
double result = strokes / holes;
[averageTextField setText:[NSString stringWithFormat:#"%.2f", result]];
}
TWITTER: (works but window does not include the calculated average)
- (IBAction)tweetMyAverage:(id)sender {
if ([TWTweetComposeViewController canSendTweet]) {
TWTweetComposeViewController *tweetSheet = [[TWTweetComposeViewController alloc]init];
[tweetSheet setInitialText:[NSString stringWithFormat:#"My Average is: %#", result]];
[self presentModalViewController:tweetSheet animated:YES];
}
}
I think that the variable result (from the calculation) is not
known in the twitter IBAction but how can I make it available?
Add an variable to your .h file in the #interface section:
#interface MyClass : UIViewController {
double result;
}
#end
Then it will be available to use in your .m in every method.
Remove the double class from the instance variable you create in the calculateNow method to make sure you don't get a warning as you are creating a separate variable.
result = strokes / holes;
Also, make sure that you use %d for doubles, %# is for strings.
[tweetSheet setInitialText:[NSString stringWithFormat:#"My Average is: %d", result]];
Assuming that all the code you supplied is in the same view controller, you can do this:
[tweetSheet setInitialText:[NSString stringWithFormat:#"My Average is: %#",
averageTextField.text]];

Convert a string + a number to an onject

I am new to Obj C, but familiar with OOP. I am working on a game that uses collision detection to score points and change UIImageView properties like background color.
I have a finite number of UIImageViews that are subviews of a larger view. I can manually check for collision and set the background colors of the UIImageViews accordingly. The problem is that this creates a rather large if / else block that I can see growing out of control. In JavaScript I can use a for loop and eval() to evaluate a string + i (the loop var) and then simply call the new var.backgroundColor = someColor;
It seems that eval is not used in OBJ C, so I am looking for an equivalent that will allow me to create a loop that executes the same block of code on a given object that only differs from other objects by name only:
Example:
if (someStatement == true){
object_01.someProperty = newProperty;
} else if (someOtherStatement == true){
object_02.someProperty = newProperty;
} else if (someOtherOtherStatement == true){
object_03.someProperty = newProperty;
}
I want to write the above as a loop. I realize I can use an Array, but if so, how? Also, I want to loop through CGRects which are not storing properly in an Array.
Any help greatly appreciated!
Damon
Creating your array:
NSMutableArray *items = [NSMutableArray array];
Populating your array with CGRects:
[items addObject:[NSValue valueWithCGRect:frame]];
Pulling a CGRect from the array:
CGRect frame = [[items objectAtIndex:0] CGRectValue];
Replacing an index in the array:
[items replaceObjectAtIndex:0 withObject:[NSValue valueWithCGRect:frame]];
The best way is to put object_01, object_02, ... into an array and then use `-[NSArray objectAtIndex:] to access the objects.
You could also use Key-Value Coding:
NSString *keyPath = [NSString stringWithFormat:#"object_0%d.someProperty", objectIndex];
[self setValue:newProperty forKeyPath:keyPath];
But as rpetrich mentioned, it's not good programming style.

Problem adding multiple annotations to map

Ok, so I’m having this problem. What I want to do is manually add multiple annotations to a map. When I add just one annotation, it works flawlessly. The pin drops, you can click on it to see its callout, life is good.
The problem comes when I want to add more than one. When I add the second, suddenly the pin’s aren’t coloured correctly (i.e. depending on their magnitude they should be a certain color, but they’re now both the same…), and more importantly when you click on them, to see their callout, the app crashes with exex_bad_access. I really have no idea what’s wrong, maybe I’m adding too many views to the map? But it’s only 9 pins and the pins themselves add just fine.
Here’s my code…
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *stops = [[NSMutableArray alloc] init]; //Get list of all the stops available
Bus *bus1 = [[Bus alloc] init]; // Bus 1 holds the stops
stops = [bus1 returnStops];
for (NSString *stop in stops) //Go through each stop to add annotation to map
{
Bus *bus2 = [bus1 initWithStop:stop]; //Create an instance of bus with a given stop
MapAnnotation *eqAnn = [MapAnnotation annotationWithBus:bus2];
[self.mapView addAnnotation:eqAnn]; //Add the annotation to the map
//[eqAnn release];
//[bus2 release];
}
[self recenterMap];
[stops release];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView
viewForAnnotation:(id <MKAnnotation>)annotation {
MKAnnotationView *view = nil;
if(annotation != mapView.userLocation) {
MapAnnotation *eqAnn = (MapAnnotation*)annotation;
view = [self.mapView dequeueReusableAnnotationViewWithIdentifier:#"busLoc"];
if(nil == view) {
view = [[[MKPinAnnotationView alloc] initWithAnnotation:eqAnn
reuseIdentifier:#"busLoc"] autorelease];
}
CGFloat magnituide = [eqAnn.bus.magnitude floatValue];
if(magnituide >= .80f) {
[(MKPinAnnotationView *)view setPinColor:MKPinAnnotationColorRed];
} else if(magnituide >= .60f) {
[(MKPinAnnotationView *)view setPinColor:MKPinAnnotationColorPurple];
} else
{
[(MKPinAnnotationView *)view setPinColor:MKPinAnnotationColorGreen];
}
[(MKPinAnnotationView *)view setAnimatesDrop:YES];
[view setCanShowCallout:YES];
}
return view;
}
even tried removing the second function, but it didn’t do anything.
Thanks for the help!
P.S I should also add, there’s usually one or two pins out of the 9 which works when you click the annotation…
If i even try to manually just two annotations by hand in the program (i.e., remove the loop), it still fails and the color is still wrong...
It would appear that your memory management of the stops variable is incorrect. You allocate a mutable array, then replace that array with the return value of -[Bus returnStops], then release that. Also it's not clear what's going on with bus2 - does -[Bus initWithStop:] return a different instance of Bus? It's not usual to send any method -init* on an already-initialised object. I think that you probably are confused by the memory management conventions in Cocoa Touch. Here's a collection of articles and other references on Cocoa memory management (which is the same beast).
Have you tried using AddAnnotations instead of add annotation? - (void)addAnnotations:(NSArray *)annotations. This might work for you...but looking at the answer above and further inspection you are having some memory managment issues in your viewDidLoad (though thi s might not be the cause of your problem, but it could be). First of you are allocating the array (stops) and then ovveriding it with some array in the Bus object, this will cause a leak. Also you are then releasing that array which might be causing the crash since you are releasing the array that is actually in the Bus object w ithout having increased a reference count to it. I am not sure what initWithStop is doing but you might be getting a leak here too if initWithStop retains the object.
I wouldn't call it a memory management problem -- I'd just say you are using array references incorrectly.
After constructing the array with NSMutableArray *stops = [[NSMutableArray alloc] init], the next step is to use [stops addObject: ] to add each stop you want to store.
After that? It's not clear what you are really trying to do.
SO the answer was that I kept sending bus1 the init object, so it got confused.
"Hi David,
Your data model looks hosed to me. You only have one bus object that you are repeatedly sending initWithStop: to.
Hope this helps.
Good luck!
"
Thank you guys for your help! You all helped me quite a bit!