Monday, 9 September 2013

Setting the title of multiple pin annotations

Setting the title of multiple pin annotations

Here is Question 3 of 3:
My app is a map view were the user can enter an address which will put a
purple pin on the map for the HQ. Secondly, the user can enter any
address, which will put as many red pins on the map as required. It is
easy to set a title and subtitle for the purple "HQ" pin, but how can the
user set a title for each individual red pin? I would like the user to be
able to enter a name as the title and an ID number as the subtitle for
each pin. Someone suggested to use UIAlertView (thank you) to do this, but
I would like to use a modal view because it can hold more textfields. How
can this be done?
Here is my code:
FieldMapController.m
#import "FieldMapController.h"
#import "CustomAnnotation.h"
#define HQ_latitude @"headquarters_latitude"
#define HQ_longitude @"headquarters_longitude"
#define HQ_coordinates @"headquarters_coordinates"
#import "PinSelectionViewController.h"
@interface FieldMapController ()
@end
@implementation FieldMapController
@synthesize mapView;
@synthesize searchBar;
@synthesize geocoder = _geocoder;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle
*)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
//ACCESS SAVED DATA FROM NSUSERDEFAULTS
-(void)viewWillAppear:(BOOL)animated{
NSUserDefaults *uDefaults = [NSUserDefaults standardUserDefaults];
if ([uDefaults boolForKey:@"headquarters_coordinates"])
{
CLLocationCoordinate2D savedCoordinate;
savedCoordinate.latitude = [uDefaults
doubleForKey:@"headquarters_latitude"];
savedCoordinate.longitude = [uDefaults
doubleForKey:@"headquarters_longitude"];
NSLog(@"Your HQ is at coordinates %f and
%f",savedCoordinate.latitude, savedCoordinate.longitude);
CustomAnnotation *annHq =[[CustomAnnotation alloc] init];
annHq.title=@"HQ";
annHq.subtitle=@"";
annHq.coordinate= savedCoordinate;
[mapView addAnnotation:annHq];
MKCoordinateRegion viewRegion = {{0.0, 0.0}, {0.0, 0.0}};
viewRegion.center.latitude = savedCoordinate.latitude;
viewRegion.center.longitude = savedCoordinate.longitude;
viewRegion.span.longitudeDelta = 0.5f;
viewRegion.span.latitudeDelta = 0.5f;
[self.mapView setRegion:viewRegion animated:YES];
[self.mapView setDelegate:self];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.mapView.delegate = self;
self.searchBar.delegate = self;
//SEARCH BAR TOOLBAR WITH "DONE" AND "CANCEL" BUTTON
UIToolbar* searchToolbar = [[UIToolbar
alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
searchToolbar.barStyle = UIBarStyleBlackTranslucent;
searchToolbar.items = [NSArray arrayWithObjects:
[[UIBarButtonItem alloc]initWithTitle:@"Cancel"
style:UIBarButtonItemStyleBordered target:self
action:@selector(cancelSearchBar)],
[[UIBarButtonItem
alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil action:nil],
nil];
[searchToolbar sizeToFit];
searchBar.inputAccessoryView = searchToolbar;
}
//WHEN PUSHING THE "CANCEL" BUTTON IN THE SEARCH BAR
-(void)cancelSearchBar
{
[searchBar resignFirstResponder];
searchBar.text = @"";
}
//PREPARE SEGUE FOR THE PIN SELECTOR VIEW
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:@"ShowPinChoicesSegue"])
{
PinSelectionViewController *pinVC = [segue
destinationViewController];
CustomAnnotation *selectedAnnotation = (CustomAnnotation *)sender;
pinVC.currentPinType = selectedAnnotation.pinType;
pinVC.delegate = self;
}
}
//WHAT HAPPENS WHEN THE "SEARCH" BUTTON AT THE SEARCH BAR KEYBOARD IS TAPPED
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
//Forward Geocoder
if (!self.geocoder)
{
self.geocoder = [[CLGeocoder alloc] init];
}
NSString *address = [NSString stringWithFormat:@"%@",
self.searchBar.text];
[self.geocoder geocodeAddressString:address
completionHandler:^(NSArray *placemarks, NSError *error) {
if ([placemarks count] > 0)
{
CLPlacemark *placemark = [placemarks objectAtIndex:0];
CLLocation *location = placemark.location;
CLLocationCoordinate2D coordinate = location.coordinate;
//Display Coordinates in Console
NSLog (@"%f %f", coordinate.latitude, coordinate.longitude);
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.01;
span.longitudeDelta = 0.01;
region.span = span;
region.center = coordinate;
//Create Annotation with Callout Bubble that displays "No
Information"
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
[annotation setCoordinate:coordinate];
[annotation setTitle:@"No Information"];
[[self mapView] addAnnotation:annotation];
[self.mapView setRegion:region animated:TRUE];
[self.mapView regionThatFits:region];
//Dismiss the Search Bar Keyboard
[self.searchBar resignFirstResponder];
//Delete text in Search Bar
self.searchBar.text = @"";
}
}];
}
//CUSTOM ANNOTATION VIEW
- (MKAnnotationView *)mapView:(MKMapView *)mapView
viewForAnnotation:(id<MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
{
return nil;
}
if ([annotation isKindOfClass:[CustomAnnotation class]])
{
MKPinAnnotationView *annotationView =
(MKPinAnnotationView *)[self.mapView
dequeueReusableAnnotationViewWithIdentifier:((CustomAnnotation
*)annotation).annotationViewImageName];
if(annotationView == nil)
{
MKPinAnnotationView *customPinView =
[[MKPinAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:((CustomAnnotation
*)annotation).annotationViewImageName];
if([[customPinView.annotation title] isEqualToString:@"HQ"])
{
//The pin for the HQ should be purple
customPinView.pinColor = MKPinAnnotationColorPurple;
}
else
{
//All other new pins should be "red" by default
customPinView.image = [UIImage
imageNamed:((CustomAnnotation
*)annotation).annotationViewImageName];
}
customPinView.canShowCallout = YES;
customPinView.animatesDrop = YES;
//Right Callout Accessory Button
UIButton *rightButton = [UIButton
buttonWithType:UIButtonTypeDetailDisclosure];
customPinView.rightCalloutAccessoryView = rightButton;
return customPinView;
}
else
{
annotationView.annotation = annotation;
}
return annotationView;
}
return nil;
}
//SHOW ACCESSORY VIEW WHEN BUTTON ON CALLOUT BUBBLE IS TAPPED
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView
*)view calloutAccessoryControlTapped:(UIControl *)control
{
if (![view.annotation isKindOfClass:[CustomAnnotation class]])
return;
CustomAnnotation *customAnnotation = (CustomAnnotation *)view.annotation;
if (control.tag == 0)
{
[self performSegueWithIdentifier:@"ShowPinChoicesSegue"
sender:customAnnotation];
}
else
{
[self onRightCalloutAccessoryViewTouched:control];
}
}
-(void)mapView:(MKMapView *)mapView
didSelectAnnotationView:(MKAnnotationView *)view
{
if(![view.annotation isKindOfClass:[CustomAnnotation class]])
return;
if (!view.rightCalloutAccessoryView)
{
UIButton *rightViewButton = [[UIButton alloc]
initWithFrame:CGRectMake(0.0, 0.0, 48.0, 32.0)];
[rightViewButton addTarget:self
action:@selector(onRightCalloutAccessoryViewtouched:)
forControlEvents:UIControlEventTouchUpInside];
rightViewButton.tag = 1;
view.rightCalloutAccessoryView = rightViewButton;
}
}
-(void)onRightCalloutAccessoryViewTouched:(id)sender
{
CustomAnnotation *selectedAnnotation = (CustomAnnotation
*)[mapView.selectedAnnotations objectAtIndex:0];
[self performSegueWithIdentifier:@"ShowPinChoicesSegue"
sender:selectedAnnotation];
}
- (void)viewDidUnload
{
self.mapView = nil;
self.searchBar = nil;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
//BUTTON TO SELECT NEW HQ
- (IBAction)selectHq:(UIBarButtonItem *)sender
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Select
Headquarters"
message:@"Enter Address"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Ok", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[[alert textFieldAtIndex:0] setKeyboardType:UIKeyboardTypeDefault];
[alert show];
}
//REMOVING ALL PINS EXCEPT USER LOCATION
- (IBAction)resetPins:(UIBarButtonItem *)sender
{
id userLocation = [mapView userLocation];
NSMutableArray *pins = [[NSMutableArray alloc] initWithArray:[mapView
annotations]];
if ( userLocation != nil )
{
[pins removeObject:userLocation]; //avoid removing user location
}
[mapView removeAnnotations:pins];
pins = nil;
[[NSUserDefaults standardUserDefaults]
removeObjectForKey:HQ_coordinates];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:HQ_longitude];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:HQ_latitude];
}
//ALERT VIEW TO ENTER ADDRESS OF HQ
- (void)alertView:(UIAlertView *)alertView
clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != alertView.cancelButtonIndex)
{
UITextField *field = [alertView textFieldAtIndex:0];
field.placeholder = @"Enter HQ Address";
if (!self.geocoder)
{
self.geocoder = [[CLGeocoder alloc] init];
}
NSString *hqAddress = [NSString stringWithFormat:@"%@", field.text];
[self.geocoder geocodeAddressString:hqAddress
completionHandler:^(NSArray *placemarks, NSError *error) {
if ([placemarks count] > 0)
{
CLPlacemark *placemark = [placemarks objectAtIndex:0];
CLLocation *location = placemark.location;
CLLocationCoordinate2D hqCoordinate = location.coordinate;
NSLog (@"Your new HQ is at coordinates %f and %f",
hqCoordinate.latitude, hqCoordinate.longitude);
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.01;
span.longitudeDelta = 0.01;
region.span = span;
region.center = hqCoordinate;
MKPointAnnotation *hqAnnotation = [[MKPointAnnotation
alloc] init];
[hqAnnotation setCoordinate:hqCoordinate];
[hqAnnotation setTitle:@"HQ"];
[[self mapView] addAnnotation:hqAnnotation];
[self.mapView setRegion:region animated:TRUE];
[self.mapView regionThatFits:region];
//Save to NSUserDefaults
NSUserDefaults *uDefaults = [NSUserDefaults
standardUserDefaults];
[uDefaults setDouble:hqCoordinate.latitude
forKey:HQ_latitude];
[uDefaults setDouble:hqCoordinate.longitude
forKey:HQ_longitude];
[uDefaults setBool:YES forKey:HQ_coordinates];
[uDefaults synchronize];
}
}];
}
else
{
//any actions for "Cancel"
}
}
//DEFINES WHAT SELECTING THE NEW PIN COLOR DOES
-(void)userDidSelectPinType:(AnnotationPinType)aPinType
{
CustomAnnotation *selectedAnnotation = (CustomAnnotation
*)[mapView.selectedAnnotations objectAtIndex:0];
selectedAnnotation.pinType = aPinType;
[mapView removeAnnotation:selectedAnnotation];
[mapView addAnnotation:selectedAnnotation];
[self.navigationController dismissViewControllerAnimated:YES
completion:nil];
}
@end
CustomAnnotation.m
#import "CustomAnnotation.h"
#import <CoreLocation/CoreLocation.h>
@implementation CustomAnnotation
@synthesize title, subtitle, coordinate;
@synthesize pinType;
-(id) initWithCoordinate:(CLLocationCoordinate2D)aCoordinate
title:(NSString *)aTitle subtitle:(NSString *)aSubtitle
{
if ((self = [super init]))
{
self.title = aTitle;
self.coordinate = aCoordinate;
self.subtitle = aSubtitle;
}
return self;
}
- (NSString *)annotationViewImageName
{
switch (self.pinType)
{
case 0:
return @"Red_Pin.png";
break;
case 1:
return @"Green_Pin.png";
break;
case 2:
return @"Purple_Pin.png";
break;
default:
break;
}
}
- (NSString *)title
{
return title;
}
- (NSString *)subtitle
{
return subtitle;
}
@end
PinSelectionViewController.m
#import "PinSelectionViewController.h"
@interface PinSelectionViewController ()
@end
@implementation PinSelectionViewController
@synthesize delegate;
@synthesize currentPinType;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (void)tableView:(UITableView *) tableView
willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath
*)indexPath
{
if(indexPath.row ==currentPinType)
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.delegate userDidSelectPinType:indexPath.row];
}
@end
PinSelectionDelegateProtocol.h
#import <Foundation/Foundation.h>
typedef enum
{
RED_PIN,
GREEN_PIN,
PURPLE_PIN
} AnnotationPinType;
@protocol PinSelectionDelegate <NSObject>
@required
-(void)userDidSelectPinType:(AnnotationPinType)aPinType;
@end

Sencha Touch audio handling works fine on desktop browser, works randomly on mobile browser

Sencha Touch audio handling works fine on desktop browser, works randomly
on mobile browser

I am building an application that uses the Sencha Touch carousel and each
item in the carousel is a container. Each container has an image, an audio
file and a button to pause / play the audio file. I found some good sample
code for handling the audio play/pause behavior with a button (really I
would like the image to handle the play/pause if you could help me figure
that out that would be even better than a button!) but it does not seem to
want to work on my iPhone or iPad. I've even tried the Chrome browser to
see if it is just Safari but maybe it is just the way mobile devices
handle a large request for audio files. I have about 30 m4a files that are
between 30 - 60 seconds in length so it's not that crazy of a request I
feel like.
Here is my carousel code (and the first item) with the handler built-in:
Ext.define('MyApp.view.BrocadeGuide', {
extend: 'Ext.carousel.Carousel',
alias: 'widget.brocadeguide',
config: {
items: [
{
xtype: 'container',
items: [
{
xtype: 'audio',
hidden: true,
autoPause: false,
enableControls: true,
url: 'http://pureispoor.com/ninja/audio/Deer.m4a'
},
{
xtype: 'button',
handler: function(button, event) {
var container = this.getParent(),
// use ComponentQuery to get the audio component
(using its xtype)
audio = container.down('audio');
audio.toggle();
this.setText(audio.isPlaying() ? 'Pause' : 'Play');
},
margin: '0 5% 0 5%',
padding: '15 0 15 0',
top: '35px',
ui: 'confirm-round',
width: '90%',
text: 'Play'
},
{
xtype: 'image',
height: '100%',
itemId: 'myimg21',
src: 'http://pureispoor.com/ninja/photos/Deer.jpg'
}
]
},
Any ideas on what might be causing mobile devices the trouble? I am trying
to debug so I have the audio controls un-hidden for the first five in my
list if you want to see my app live: Immortal Ninja

Avoid tkinter GUI lock when using ttk.Progressbar

Avoid tkinter GUI lock when using ttk.Progressbar

I'm trying to write a GUI for something long running and cant seem to
figure out how to avoid locking the GUI thread. I want to use
ttk.Progressbar but I cant seem to update the bar value and have the
window update the GUI. I've tried putting the update handling in its own
function and updating it directly but neither worked. Updating the value
in a handler is what I'd prefer to do since this script would do some
downloading, then processing, then uploading and three separate bars would
look nicest.
from Tkinter import *
import time, ttk
class SampleApp(Frame):
def __init__(self,master):
Frame.__init__(self,master)
self.pack()
self.prog = ttk.Progressbar(self, orient = 'horizontal', length =
200, mode = 'determinate')
self.prog.pack()
self.button = Button(self,text='start',command=self.start)
self.button.pack()
def start(self):
self.current = 0
self.prog["value"] = 0
self.max = 10
self.prog["maximum"] = self.max
self.main_prog()
def handler(self):
self.prog['value'] += 1
def main_prog(self):
for x in range(10):
time.sleep(2)
self.handler()
root = Tk()
app = SampleApp(master = root)
app.mainloop()

SecKeyEncrypt kSecPaddingNone

SecKeyEncrypt kSecPaddingNone

I've been experiencing some frustration when trying to use SecKeyEncrypt()
with kSecPaddingNone. After much investigation, I've found a workaround,
but I want to know what's going on. At the moment, I don't have the code
available, but I will be able to post it later today. I'm really not
convinced that the problem lies in my code, though: I tend to believe that
I'm just plain old doing something fundamentally wrong. (That is, I
believe my code is right, but that what I'm trying to do is wrong.)
My problem is this: I'd like to encrypt a large block of data using a
symmetric key, and then encrypt that key using a different public key.
Using CryptoExercise as a template, I've fairly easily got a bunch of code
that does that. I generate a symmetric key for AES128, use it to encrypt
my large buffer. My unit tests have no trouble with that.
But then my unit tests create a public/private key pair, attempt to
encrypt the symmetric key with the public key, decrypt it with the private
key, and then decrypt the large buffer. Note that I've made some
simplifying assumptions based on the restricted domain of my problem set:
I'm always using AES128 to encrypt the large buffer, so the key is always
16 bytes, and I'm always using a 1024-bit public/private key pair, so I
encrypt the AES key by creating a 128-byte buffer, filling it with random
data, and then embedding the AES key into that buffer.
Finally, since I've got a fixed set of buffer sizes, I'm using
kSecPaddingNone when I call `SecKeyEncrypt() . My assumption was that I
could rely on my method of filling the buffer and knowledge of the buffer
sizes.
What I saw when I started running my tests was frustrating: about 80% of
the time, they work just fine. But the other 20%, SecKeyEncrypt() fails
with an OSStatus of -50, bad parameter. I spent quite a bit of time
looking for stack corruption, heap corruption, premature deallocation,
etc., but that was fruitless.
Then I started looking at the public/private key pair operations on just
plain old buffers, i.e. I made a new unit test which tried to
encrypt/decrypt buffers that I created and filled manually. At this point,
I found my clues: if I sent, for example, a zero buffer, then
SecKeyEncrypt fell into an infinite loop. If I sent a buffer filled with
just ones, then it worked fine. And if I filled the buffer with ones, and
then replaced the first byte with zero, I got back into an infinite loop.
Various other patterns led me to my workaround, which is presently to
insert the AES key after the first byte and to always set the first byte
to one, but I'm heartily confused. From the documentation for
SecKeyEncrypt():
Typically, kSecPaddingPKCS1 is used, which addsPKCS1padding before
encryption. If you specifykSecPaddingNone`, the data is encrypted as-is.
The way I read that, the contents of the plaintext buffer should not
affect the execution of the encryption algorithm, and yet, my unit tests
seem to indicate that it is happening, and that the first byte of the
buffer is somehow crucial to the operation. And my workaround seems to
pass my unit tests 100% of the time.
Does anybody with more experience here have anything that'd help me
understand what's going on? Am I misinterpreting the documentation? Am I
trying to do something that I shouldn't be? Did I oversimplify?
I can post the code later tonight, once I have access to it again, if
anybody thinks it'll help.

android.os.networkonmainthreadexception inside a new Thread

android.os.networkonmainthreadexception inside a new Thread

I am aware that you can't do network operations in the main thread, since
Android 3.0. So, i made my call inside a new Thread:
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
user=login.getText().toString();
password=pass.getText().toString();
params.add(new BasicNameValuePair("user", user));
params.add(new BasicNameValuePair("pass", password));
Thread thread=new Thread(){
public void run(){
try {
response=CustomHttpClient.executeHttpPost(urlogin,
params);<---Throws exception here
response=response.replaceAll("\\s+","");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(response.equals("ok")){
Intent home=new Intent(c, HomeActivity.class);
home.putExtra("username", user);
startActivity(home);
Toast toast=Toast.makeText(c,
getString(R.string.welcome), Toast.LENGTH_LONG);
toast.show();
}else{
if(response.equals("fallo")){
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast toast=Toast.makeText(c,
R.string.nologin, Toast.LENGTH_LONG);
toast.show();
login.setText("");
pass.setText("");
}
});
}else if(response.equals("nologin")){
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast toast=Toast.makeText(c,
R.string.nouser, Toast.LENGTH_LONG);
toast.show();
login.setText("");
pass.setText("");
}
});
}
}
}
};
thread.run();
}
});
But, I receive that exception despite im NOT on main thread (or at least i
think that...)
Anybody can help? Thank you.

Java 7 resize a JFrame (my GUI): the componentListener is not getting fired

Java 7 resize a JFrame (my GUI): the componentListener is not getting fired

I've Googled around and could not find an answer:
I have a JFrame as a GUI and set a componentListener like
this.addComponentListener(new CL(this, logger));
In the componentListener I have the componentResized, etc...
public void componentResized(ComponentEvent e) { if (e.getSource() == gui)
{ here I do the code } }
Everything is working fine under Java 6, but under Java 7, the Jframe is
being resized but is not being repainted: the component listener is not
getting called
I tried some alternatives from StackOverflow in the way of coding, but no
way to make it work.
When I minimize the GUI window and restore it, then "componentResized" is
being called.
Anyone an idea what's going on and why it works under Java 6 and not Java 7.

Merging two arrays without changing key values php

Merging two arrays without changing key values php

I have two arrays in php as shown in the code
<?php
$a=array('0'=>array('500'=>'1','502'=>'2'));
$b=array('0'=>array('503'=>'3','504'=>'5'));
print_r(array_merge($a[0],$b[0]));
?>
I need to merge two arrays. array_merge function successfully merged two
of them but key value gets changed. I need the following output
Array
(
[0]=>Array(
[500] => 1
[502] => 2
[503] => 3
[504] => 5
)
)
What function can I use in php so that the following output is obtained
without changing key values?