MKPinAnnotationView loading all data in the didSelectAnnotationView method at once - ios

I have been poking around with the MKMapView for quite some time trying to get more familiar with it and I ran into a problem.
I have my MapView populated with two pins and when I pressed them they have their respective annotations. I also have a button that will take me to a new UIView with UlLabels that will be loaded with data from an array.
Looking at my console I notice that the data is coming through but instead of it being just for the pin I selected its loading all of them and then displaying the last one.
Here is my code for the method I'm using to load the data for the next view:
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:addAnnotation reuseIdentifier:#"currentloc"];
if(annView.tag = 0) {
GSStore * theStore = [globalCMS getStoreById:1];
NSUserDefaults * prefs = [NSUserDefaults standardUserDefaults];
int storeid = theStore.storeid;
[prefs setInteger:storeid forKey:#"selectedstore"];
NSLog(#"%#", theStore.name);
storeName.text = [NSString stringWithFormat:#"%#", theStore.name];
storeCS.text = [NSString stringWithFormat:#"%#,%#", theStore.city, theStore.state];
storeHours.text = [NSString stringWithFormat:#"%#", theStore.hours];
storePhone.text = [NSString stringWithFormat:#"%#", theStore.phone];
storeAddress.text = [NSString stringWithFormat:#"%#", theStore.address];
storeCSZ.text = [NSString stringWithFormat:#"%#,%# %#", theStore.city, theStore.state, theStore.zip];
storeWebsite.text = [NSString stringWithFormat:#"%#", theStore.website];
}
if(annView.tag = 1){
GSStore * theStore = [globalCMS getStoreById:2];
NSUserDefaults * prefs = [NSUserDefaults standardUserDefaults];
int storeid = theStore.storeid;
[prefs setInteger:storeid forKey:#"selectedstore"];
NSLog(#"%#", theStore.name);
storeName.text = [NSString stringWithFormat:#"%#", theStore.name];
storeCS.text = [NSString stringWithFormat:#"%#,%#", theStore.city, theStore.state];
storeHours.text = [NSString stringWithFormat:#"%#", theStore.hours];
storePhone.text = [NSString stringWithFormat:#"%#", theStore.phone];
storeAddress.text = [NSString stringWithFormat:#"%#", theStore.address];
storeCSZ.text = [NSString stringWithFormat:#"%#,%# %#", theStore.city, theStore.state, theStore.zip];
storeWebsite.text = [NSString stringWithFormat:#"%#", theStore.website];
}
if (annView.tag = 2) {
GSStore * theStore = [globalCMS getStoreById:3];
NSUserDefaults * prefs = [NSUserDefaults standardUserDefaults];
int storeid = theStore.storeid;
[prefs setInteger:storeid forKey:#"selectedstore"];
NSLog(#"%#", theStore.name);
storeName.text = [NSString stringWithFormat:#"%#", theStore.name];
storeCS.text = [NSString stringWithFormat:#"%#,%#", theStore.city, theStore.state];
storeHours.text = [NSString stringWithFormat:#"%#", theStore.hours];
storePhone.text = [NSString stringWithFormat:#"%#", theStore.phone];
storeAddress.text = [NSString stringWithFormat:#"%#", theStore.address];
storeCSZ.text = [NSString stringWithFormat:#"%#,%# %#", theStore.city, theStore.state, theStore.zip];
storeWebsite.text = [NSString stringWithFormat:#"%#", theStore.website];
}
}

Just to explain why you are seeing "the method loading all the data":
The if conditions are using a single equals (=) sign instead of a double (==).
The single = is an assignment while the double == is the one for checking equality.
Since the assignment executes successfully in all the ifs, the code inside all the ifs executes.
However, the real problem is that you are creating a new instance of an annotation view in the didSelectAnnotationView delegate method which is not what you want.
Instead of creating a new instance, you can use the annotation view instance that the method is providing you as a parameter (ie. view).
So theoretically you could look at view.tag.
But I would highly recommend not relying on tags and instead placing all the data you need for an annotation in the annotation class itself. Then you can access the annotation in this method using view.annotation and casting it to your custom class to access custom properties:
MyAnnotationClass *myAnn = (MyAnnotationClass *)view.annotation;
NSLog(#"myAnn.someCustomProperty = %#", myAnn.someCustomProperty);

Related

Fetching data from SQLite and want to get only the last value of column id

I am fetching data from SQLite and want to get only the last value of column id in XCode.The code is
NSString *selquery = #"select id from watchlists";
if (self.uid != nil) {
self.uid = nil;
}
self.uid = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:selquery]];
NSString *valvar;
valvar = [_uid lastObject];
NSNumber *custval = [_uid valueForKey: #"#lastObject"];
NSString *imgval1 = [NSString stringWithFormat:#"%#_%s",custval,"1"];
NSLog(#"%#", imgval1);
Please tell me how can I get only the value because by using the above code I am getting array with last value of id.
I think this your case, try this it maybe help you
NSArray *temp=[NSArray arrayWithObjects:#"1",#"2",#"3", nil];
NSArray *temp0ne=[[NSArray alloc]initWithArray:temp];
// NSString *tmmp=[temp0ne lastObject];
NSArray *finalStr=[uid lastObject];
NSLog(#"Dictionary is---->%#",[finalStr lastObject]);
Output:
3_1
EDIT
NSArray *temp=[NSArray arrayWithObjects:#"(1)",#"(2)",#"(3)", nil];
NSArray *temp0ne=[[NSArray alloc]initWithArray:temp];
NSString *tmmp=[temp0ne lastObject];
NSString *final=[tmmp stringByReplacingOccurrencesOfString:#"(" withString:#""];
final=[final stringByReplacingOccurrencesOfString:#")" withString:#""];
NSString *imgval1 = [NSString stringWithFormat:#"%#_%s",final,"1"];
NSLog(#"%#", imgval1);
I don't know is this correct way or not try this....otherwise have look this link
I don't fully understand your code structure hehe. Try this:
NSString *selquery = #"select id from watchlists";
if (self.uid != nil) {
self.uid = nil;
}
self.uid = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:selquery]];
NSNumber *custval = [_uid objectAtIndex:[_uid count]-1];
*
NSString *str = [NSString stringWithFormat#"%#",custval];
str = [str stringByReplacingOccurrencesOfString:#"("
withString:#""];
NSString *finalCustval = [NSString stringWithFormat#"%#",str];
finalCustval = [finalCustval stringByReplacingOccurrencesOfString:#")"
withString:#""];
*
NSString *imgval1 = [NSString stringWithFormat:#"%#_%s",finalCustval ,"1"];
NSLog(#"%#", imgval1);
UPDATE
try adding the ones with *.

Set UILabel's text from custom method

I created a method which gets data from a server, everything works fine except when I try to set string to for example UILabel or UITextView, nothing shows and changed ! here is my code :
- (void)viewDidLoad
{
[super viewDidLoad];
[self getDataFromURL:#"http://somesites.net/panel/services?action=events&num=1"
setTitle:_eTitle1.text image:_eImage1 description:_eNews1.text];
}
Getting Data :
-(void)getDataFromURL:(NSString*)url setTitle:(NSString*)eTitle
image:(UIImageView*)eImages description:(NSString*)eDescriptions {
NSURL *URL = [NSURL URLWithString:url];
NSError *error1;
NSString *strPageContent = [NSString stringWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:&error1];
strPageContent = [strPageContent gtm_stringByUnescapingFromHTML];
if ([strPageContent rangeOfString:#"<plist version=\"1.0\">"].location != NSNotFound) {
NSRange range = [strPageContent rangeOfString:#"<plist version=\"1.0\">"];
strPageContent = [strPageContent substringWithRange:NSMakeRange(range.location+range.length, strPageContent.length-(range.location+range.length))];
strPageContent = [strPageContent stringByReplacingOccurrencesOfString:#"</plist>" withString:#""];
}
NSError *error = nil;
NSDictionary *dict = [XMLReader dictionaryForXMLString:strPageContent options:XMLReaderOptionsProcessNamespaces
error:&error];
if ([dict count]>0) {
NSDictionary *dictInner = [dict objectForKey:#"dict"];
NSArray *arrValues = [dictInner objectForKey:#"string"];
NSString * strTitle = [[arrValues objectAtIndex:0] objectForKey:#"text"];
NSString *strImage = [[arrValues objectAtIndex:1] objectForKey:#"text"];
NSString * strDescription = [[arrValues objectAtIndex:2] objectForKey:#"text"];
eTitle = strTitle;
eDescriptions = strDescription;
// [eImages setImageWithURL:[NSURL URLWithString:strImage]
// placeholderImage:[UIImage imageNamed:#"loadingPad.jpg"]];
NSLog(#"Title: %# | Image: %# | Desc: %#",eTitle,strImage,eDescriptions);
}
}
compiler gives me the right information ! but these string could not set to my lable , IF I put my lable's string into the method it works !!! :
_eTitle1.text = strTitle ;
It's completely normal: when you pass the "text" object to the method, you are passing the pointer to it. Assigning to it directly another NSString object will just assign a new pointer. In order to have side effect on a string you gotta use NSMutableString, but the UILabel has just an immutable NSString for the text attribute. So the only solution is to pass the UILabel or pass an initialized empty mutable string inside the method, change the content via [eTitleText setString:strTitle] and then, outside the method, assign it to the UILabel text attribute.
So, either you change the method like this (as you already did):
-(void)getDataFromURL:(NSString*)url setTitle:(UILabel*)eTitle
image:(UIImageView*)eImages description:(NSString*)eDescriptions {
...
eTitle.text = strTitle;
...
and using it like this:
- (void)viewDidLoad
{
[super viewDidLoad];
[self getDataFromURL:#"http://somesites.net/panel/services?action=events&num=1"
setTitle:_eTitle1 image:_eImage1 description:_eNews1.text];
}
Or you can go this other way:
-(void)getDataFromURL:(NSString*)url setTitle:(NSMutableString*)eTitle
image:(UIImageView*)eImages description:(NSString*)eDescriptions
...
[eTitle setString:strTitle];
...
and using it like this:
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableString *titleText = [NSMutableString new];
[self getDataFromURL:#"http://somesites.net/panel/services?action=events&num=1"
setTitle:titleText image:_eImage1 description:_eNews1.text];
eTitle1.text = titleText;
}

Calling ViewDidAppear from numerous methods to update NSMutableDictionary data entries

I am fairly new to Objective C and am attempting to develop an app using Xcode5.
I am storing strings (either composed of numbers 1-9 or N/A) in a NSMutableDictionary.
When users get to the "Review your inputed results page" I want them to be able to manually go into a text field, delete the value present and retype their new value if necessary. However, I don't know how to reload this information into the system so that the new values will carry over into the email client, which basically sends the results to whatever email address the user wishes.
Currently, the values are being loaded using ViewDidAppear upon entering the UIView, but I think I need to call it again if, for example, textField1 is updated.
I have methods for all the textFields that are textField(insert correct number here)IsUpdated and inside those I want to store the new value to the NSMutableDictionary (which I believe I can already do).
The issue is I cannot figure out how to get the current version of the dictionary that was loaded upon entering the UIView to update so that the information in ViewDidAppear updates for the email.
Hope that made sense.
As I said, definitely new to Objective C.
Below is the viewDidAppear method.
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:(BOOL)animated];
AppDelegate *app = (AppDelegate *) [[UIApplication sharedApplication] delegate];
NSMutableDictionary *results = [app results];
NSString *firstResult = [results valueForKey:#"first"];
NSString *secondResult = [results valueForKey:#"second"];
NSString *thirdResult = [results valueForKey:#"third"];
if ([firstResult isEqual: #"N/A"]) {
self.Result1.text = results[#"first"];
} else {
int firstResultInt = [firstResult intValue]; firstResultInt++;
[_Result1 setText:[NSString stringWithFormat:#"%i", firstResultInt]];
}
if ([secondResult isEqual: #"N/A"]) {
self.Result2.text = results[#"second"];
} else {
int secondResultInt = [secondResult intValue]; secondResultInt++;
[_Result2 setText:[NSString stringWithFormat:#"%i", secondResultInt]];
}
if ([thirdResult isEqual: #"N/A"]) {
self.Result3.text = results[#"third"];
} else {
int thirdResultInt = [thirdResult intValue]; thirdResultInt++;
[_Result3 setText:[NSString stringWithFormat:#"%i", thirdResultInt]];
}
self.diningResult.text = results[#"dining"];
self.basementResult.text = results[#"basement"];
self.atticResult.text = results[#"attic"];
self.carResult.text = results[#"car"];
self.hallwayResult.text = results[#"hallway"];
self.garageResult.text = results[#"garage"];
self.other1Result.text = results[#"other"];
self.other2Result.text = results[#"other1"];
self.other1Name.text = results[#"other1name"];
self.other2Name.text = results[#"other2name"];
NSMutableString * str = [NSMutableString new];
[str appendString:#"Bedroom: "];
if ([firstResult isEqual: #"N/A"]) {
[str appendString: firstResult];
} else {
int firstResultInt = [firstResult intValue]; firstResultInt++;
NSString *firstResultString = [NSString stringWithFormat:#"%d",firstResultInt];
[str appendString: firstResultString];
}
[str appendString:#"\n"];
[str appendString:#"Living Room: "];
if ([secondResult isEqual: #"N/A"]) {
[str appendString: secondResult];
} else {
int secondResultInt = [secondResult intValue]; secondResultInt++;
NSString *secondResultString = [NSString stringWithFormat:#"%d",secondResultInt];
[str appendString: secondResultString];
}
[str appendString:#"\n"];
[str appendString:#"Kitchen: "];
if ([thirdResult isEqual: #"N/A"]) {
[str appendString: thirdResult];
} else {
int thirdResultInt = [thirdResult intValue]; thirdResultInt++;
NSString *thirdResultString = [NSString stringWithFormat:#"%d",thirdResultInt];
[str appendString: thirdResultString];
}
[str appendString:#"\n"];
[str appendString:#"Dining:"];
[str appendString:self.diningResult.text];
[str appendString:#"\n"];
//Code goes on to do the same with all other fields. all strings led by "str" get transferred over to the email
self.emailString = [NSString stringWithString:str];
}
The code should not call viewDidAppear, it's the responsibility of the framework to call viewDidAppear at the appropriate times. Instead, you should make a separate methods, e.g. UpdateMailContents and UpdateTextFields. Then call those methods from viewDidAppear, and call UpdateMailContents from the textFieldDidEndEditing method of the UITextFieldDelegate protocol.

Split NSString from first whitespace

I have a name textfield in my app, where both the firstname maybe a middle and a lastname is written. Now I want to split these components by the first whitespace, the space between the firstname and the middlename/lastname, so I can put it into my model.
For example:
Textfield Text: John D. Sowers
String 1: John
String 2: D. Sowers.
I have tried using [[self componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] firstObject]; & [[self componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] lastObject];
But these only work if have a name without a middlename. Since it gets the first and the last object, and the middlename is ignored.
So how would I manage to accomplish what I want?
/*fullNameString is an NSString*/
NSRange rangeOfSpace = [fullNameString rangeOfString:#" "];
NSString *first = rangeOfSpace.location == NSNotFound ? fullNameString : [fullNameString substringToIndex:rangeOfSpace.location];
NSString *last = rangeOfSpace.location == NSNotFound ? nil :[fullNameString substringFromIndex:rangeOfSpace.location + 1];
...the conditional assignment (rangeOfSpace.location == NSNotFound ? <<default value>> : <<real first/last name>>) protects against an index out of bounds error.
Well that method is giving you an array with all the words split by white space, so then you can grab the first object as the first name and the rest of the objects as middle/last/etc
NSArray *ar = [self componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString *firstName = [ar firstObject];
NSMutableString *rest = [[NSMutableString alloc] init];
for(int i = 1; i < ar.count; i++)
{
[rest appendString:[ar objectAtIndex:i]];
[rest appendString:#" "];
}
//now first name has the first name
//rest has the rest
There might be easier way to do this, but this is one way..
Hope it helps
Daniel
I think this example below I did, solves your problem.
Remember you can assign values from the array directly, without transforming into string.
Here is an example:
NSString *textField = #"John D. Sowers";
NSArray *fullName = [textField componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#" "]];
if (fullName.count)
{
if (fullName.count > 2)
{
NSLog(#"Array has more than 2 objects");
NSString *name = fullName[0];
NSLog(#"Name:%#",name);
NSString *middleName = fullName[1];
NSLog(#"Middle Name:%#",middleName);
NSString *lastName = fullName[2];
NSLog(#"Last Name:%#",lastName);
}
else if(fullName.count == 2)
{
NSLog(#"Array has 2 objects");
NSString *name = fullName[0];
NSLog(#"Name:%#",name);
NSString *lastName = fullName[1];
NSLog(#"Last Name:%#",lastName);
}
else
{
NSString *name = fullName[0];
}
}
I found this to be most robust:
NSString *fullNameString = #"\n Barnaby Marmaduke \n \n Aloysius ";
NSMutableArray *nameArray = [[fullNameString componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] mutableCopy];
[nameArray removeObject:#""];
NSString *firstName = [nameArray firstObject];
if(nameArray.count)
{
[nameArray removeObjectAtIndex:0];
}
NSString *nameRemainder = [nameArray componentsJoinedByString:#" "];
Bob's your uncle.

IOS Array Testing

Here is my current code:
int i = 1;
NSString * StockOneYahooFinance = [NSString stringWithFormat:#"http://finance.yahoo.com/q/hp?s=S+Historical+Prices"];
NSString * PulledStockOne = [NSString stringWithContentsOfURL:[NSURL URLWithString:StockOneYahooFinance] encoding:1 error:nil];
for (i=1;i=30;i++){
NSString *StartPulling = [[PulledStockOne componentsSeparatedByString:#"nowrap align="] objectAtIndex:i];
NSString *StartOpen = [[StartPulling componentsSeparatedByString:#">"] objectAtIndex:3];
NSString *Open = [[StartOpen componentsSeparatedByString:#"<"] objectAtIndex:0];
NSString *StartClose = [[StartPulling componentsSeparatedByString:#">"] objectAtIndex:9];
NSString *Close = [[StartClose componentsSeparatedByString:#"<"] objectAtIndex:0];
year.text = Close;
i++;
}
But to the point I click the only button on the screen and it does exactly what I want it pulls the stocks open and close price for the day. But my current issue is I want it to pull all of these as an array so how can I do this?
First thing:
for (i=1;i=30;i++){
it should be:
for (i=1;i<=30;i++){
Second one, do not increment 'int i' value on the end of loop because 'for' loop already do this. For quick'n dirty way of debugging add:
NSLog(#"Current iteration: %i", i);
as the first function in 'for' loop to see what's happening there.

Resources