iOS-app: Arbeta med MultiComponent Picker



Den här bloggen handlar om att skapa en iOS-app som visar konvertering från en enhet till en annan. Den beskriver hur en Mutlicomponent Picker fungerar, varningar etc.

För att få en grundlig inblick, vänligen läs . Detta är den andra bloggen i iOS-appserien.





Om du är en erfaren utvecklare som är nyfiken på hur MultiComponent-plockaren fungerar, har du kommit till rätt blogg. I den här bloggen kommer jag att prata om hur vi kan utöka vår konverteringsapp med mer funktionalitet genom att implementera en multikomponentväljare, och hur vi kan utföra exceptionell hantering med varningar.

Iförra bloggen,vi har sett det när vi skriver något i textfältet dyker tangentbordet upp. Värdet som ska konverteras skrivs i textfältet och då ser vi att tangentbordet inte försvinner.



För att lösa detta problem måste vi lägga till en knapp som täcker hela vyn. När användaren vidrör någonstans i bakgrunden bör tangentbordet försvinna.

Nu ska vi fortsätta och göra det. Dra en knapp, ställ in typen av knapp som anpassad och textfärg som tydlig färg från attributinspektören.

Attribut Inspektör



och välj Redigerare> Ordna> Skicka till baksida

och ändra storlek på knappen så att den passar hela vyn.

Den här knappen fungerar nu som en osynlig bakgrundsknapp som du klickar på för att tangentbordet ska försvinna. Låt oss skriva IBAction för samma, välj assistentredigerarläge och kontroll + dra till ViewController.h. Ställ in anslutningen till åtgärd och namn till bakgrundsknappen och klicka på anslut.

View controller-koden ser ut så här nu.

#import @interface ViewController: UIViewController @property (strong, nonatomic) IBOutlet UITextField * ValueTextField @property (strong, nonatomic) IBOutlet UIPickerView * picker2 @property (strong, nonatomic) NSArray * data @property (strong, nonatomic) - (IBAction) Konvertera: (UIButton *) avsändare - (IBAction) backgroundButton: (id) avsändare @end

Byt till ViewController.m och skriv sedan följande kod.

länkat listprogram i c
- (IBAction) backgroundButton: (id) avsändare {[_ValueTextField resignFirstResponder] [_picker2 resignFirstResponder] [_ResultLabel resignFirstResponder]}

Här ber koden alla andra objekt att ge första responder-status när en beröring detekteras. Kör nu appen och se. Du kommer att kunna upptäcka att tangentbordet försvinner när du rör vid bakgrunden. Nu för att tangentbordet ska gå när du är klar med att skriva, anropa backgroundButton-metoden i plockaren didselectRow (). Så metodkoden kommer att vara som följer.

- (ogiltigt) pickerView: (UIPickerView *) pickerView didSelectRow: (NSInteger) rad iComponent: (NSInteger) komponent {selectedValue = _data [rad] [självbakgrundButton: 0]}

Nu kan du arbeta med förskönhetsdelen av appen, som att lägga till en bakgrund och kanske till och med ge en snygg knappbild. Men i min kommer jag att ställa in en bakgrundsbild.
För att göra det, hitta en lämplig bild först duh! Lägg sedan till den i mappen Images.xcassets och ändra bilden från 1x till 2x skärm i universal.

Kör appen och se om den fungerar bra.

Om jag byter enhet till iPhone 5s.

Och kör appen.

Här kan vi se att allt fungerar bra som förväntat. Tänk nu om jag ville lägga till en bakgrund till min knapp och göra utseendet mer som en knapp? För att göra det skulle jag först lägga till en IBOutlet för konverteringsknappen till ViewController.h

@property (stark, icke-atomisk) IBOutlet UIButton * konvertera

och lägg sedan till följande kod i viewDidLoad () -metoden

self.convert.backgroundColor = [UIColor colorWithRed: 0.4 green: 0.8 blue: 1.0 alpha: 1.0] [_convert setTitleColor: [UIColor whiteColor] forState: UIControlStateNormal]

Låt oss köra vår app och se om det är så vi gillar det.

OK bra! Du måste ha märkt att jag också har ändrat positionerna för resultatetiketten, orsaken till ändringen är något jag kommer att förklara senare.

Vi vet att vår app konverterar från Celsius till Fahrenheit och bara vice versa. Så vad sägs om att lägga till några fler funktioner eller enheter att konvertera? För att göra det måste vi lägga till ytterligare en komponent i UIPickerView som ger lämpligt val när en enhet väljs i den första komponenten i plockaren.

För att göra en plockare uppdelad i två komponenter måste vi lägga till en ny NSArray-data2, som kommer att innehålla data för den andra komponenten. Definiera också två konstanter som representerar våra två komponenter. Här deklareras den vänstra komponenten 0 och den högra komponenten deklareras 1 för enkelhetens programmering.

Din ViewController.h-fil ser ut

konvertera sträng till datumformat i java
#import # definiera data1comp 0 # definiera data2comp 1 @interface ViewController: UIViewController @property (stark, nonatomic) IBOutlet UITextField * ValueTextField @property (stark, nonatomic) IBOutlet UIPickerView * picker2 @property (stark, nonatomic) NSAr stark, nonatomic) NSArray * data2 @property (stark, nonatomic) IBOutlet UILabel * ResultLabel @property (strong, nonatomic) IBOutlet UIButton * convert - (IBAction) Convert: (UIButton *) avsändare - (IBAction) backgroundButton: (id) avsändare @slutet

Definiera nu arraydata2 i ViewDidLoad () -metoden. Nu när vi har båda datakällorna måste vi kunna skriva kod för plockaren på ett sådant sätt att när vi väljer ett objekt från den första komponenten i plockaren ska den andra komponenten automatiskt ändras till motsvarande värde. Den andra komponenten är beroende av valet av den första.
För detta måste vi definiera en ordlista som lagrar nycklar och värden. Nycklarna innehåller data som motsvarar den första komponenten i plockaren och värdena innehåller den data som motsvarar den andra komponenten i plockaren.

- (void) viewDidLoad {[super viewDidLoad] // Gör ytterligare inställningar efter att du har laddat vyn, vanligtvis från en nib. _data1 = [NSArray arrayWithObjects: @ 'Celsius', @ 'Fahrenheit', @ 'Meter', @ 'Centimeter', nul] data2 = [NSArray arrayWithObjects: @ 'Centimeter', @ 'Meter', @ 'Fahrenheit', @ 'Celsius', nil] dictionary = [NSDictionary dictionaryWithObjectsAndKeys: @ 'Celcius', @ 'Farenheit', @ 'Farenheit', @ 'Celcius', @ 'Meter', @ 'Centimeter', @ 'Centimeter', @ 'Meter ', nil] self.view.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed: (@' bg2.png ')]]}

Nu måste vi ändra datakällan och delegera metoder för den aktuella väljaren till följande, så att vi har data fylld i båda komponenterna.

- (NSInteger) numberOfComponentsInPickerView: (UIPickerView *) pickerView {return 2} - (NSInteger) pickerView: (UIPickerView *) pickerView numberOfRowsInComponent: (NSInteger) component {if (component == data1comp) {return [} [self.data2 count]} - (NSString *) pickerView: (UIPickerView *) pickerView titleForRow: (NSInteger) row forComponent: (NSInteger) component {if (component == data1comp) {return [self.data1 objectAtIndex: row]} returnera [self.data2 objectAtIndex: row]} - (void) pickerView: (UIPickerView *) pickerView didSelectRow: (NSInteger) row inComponent: (NSInteger) component {[self backgroundButton: 0] if (component == data1comp) {NSString * data11 = [_ data1 objectAtIndex: rad] NSArray * a = [ordbok objektForKey: data11] secondrow = [self.data2 indexOfObject: a] [_picker2 selectRow: secondrow inComponent: data2comp animated: YES] [_picker2 reloadComponent: data2comp] vald = rad}}

Här i vår didSelectRow () -metod får vi det valda värdet för den första komponenten, sedan skickar vi det som argument till metoden objectForKey () i ordboken och får motsvarande värde för nyckeln. För att hitta motsvarande position för värdet i den andra matrisen, dvs. data2, använder vi metoden indexOfObject () och lagrar resultatet i ett heltal.
Vi skickar sedan detta heltal till plockningsmetoden selectRow: row inComponent: component () -metoden. Och ladda om komponenten i plockaren med reloadComponent ().
När vi väl har gjort detta, när vi väljer ett objekt från den första komponenten, kommer motsvarande objekt att väljas i den andra komponenten i plockaren.

Koden för didSelectRow ()

- (void) pickerView: (UIPickerView *) pickerView didSelectRow: (NSInteger) row inComponent: (NSInteger) component {[self backgroundButton: 0] if (component == data1comp) {NSString * data11 = [_ data1 objectAtIndex: row] NSArray * a = [ordbokobjektForKey: data11] secondrow = [self.data2 indexOfObject: a] [_picker2 selectRow: secondrow inComponent: data2comp animated: YES] [_picker2 reloadComponent: data2comp] selectedValue = data11 selectedRow = row}}

Kör nu appen och se om plockaren fungerar som förväntat.

Voila! det fungerar!

Så låt oss fortsätta att koda vår konvertera-knapp. Den tidigare plockaren hade bara två värden som matchade dvs Celsius och Fahrenheit och sedan beräknades resultatet. Men nu har vi fyra värden Celsius, Fahrenheit, Meter och Centimeter. Så jag har använt ett switch-uttalande som beräknar värdet baserat på vald radvariabel.

- (IBAction) Konvertera: (UIButton *) avsändare {float val = [_ ValueTextField.text floatValue] NSLog (@ 'value% f', val) switch (selectedRow) {case 0: // Celsius to Fahrenheit res = (val * 1.8) + 32 break case 1: // Fahrenheit to Celsius res = (val-32) /1.8 break case 2: // Meter to Centimeter res = val * 100 break case 3: // Centimeter to Meter res = val * 0.01 break standard: res = 0.0} NSString * final = [NSString stringWithFormat: @ '%. 02f', res] _ResultLabel.text = final}

om du kör appen kan vi se att allt fungerar bra.

Nu kan vi söka efter undantag som kan förekomma i vår app. Det finns till exempel inget värde i textrutan. Eller så försöker vi konvertera från Celsius till Meter eller Centimeter, vilket faktiskt inte är möjligt. Dessa typer av situationer kallas som undantag och vi måste undvika det genom att skriva kod för att hantera sådana fel.

Låt oss lösa den första typen av fel som kan uppstå när vi kör vår applikation. Det vill säga, vi saknar att skriva vårt värde för att konverteras i textfältet. För detta scenario måste vi varna våra användare om att ange värdet och sedan fortsätta.

Vi kan använda UIAlertView för detta. Vi kan skriva en metod som heter showAlertWithMessage (NSString *) meddelande. I den här metoden kan vi deklarera en alertView och sedan slutligen visa den med metoden show (). Koden för metoden kommer att vara som följer.

- (ogiltigt) showAlertWithMessage: (NSString *) meddelande {UIAlertView * alertView = [[UIAlertView alloc] initWithTitle: @ 'Error' meddelande: meddelande delegat: självavbrytButtonTitle: noll annatButtonTitles: @ 'Okej', noll] alertView.tag = 100 _ResultLabel.text=@'Inget resultat '[alertView show]}

Nu måste den här metoden när användaren klickar på konvertera-knappen kallas som konvertering. Konvertering bör inte göras utan att ange värdet. Så i metoddefinitionen för konvertering måste vi kontrollera om längden på textfältet är större än eller lika med noll eller inte. Om det är då gör omvandlingen, annars visa varningen. Därför skulle konverteringsknappskoden vara som:

- (IBAction) Konvertera: (UIButton *) avsändare {if ([_ ValueTextField.text length)<= 0) { [self showAlertWithMessage:@' Please enter the value'] } else { float res=0.0 float val=[_ValueTextField.text floatValue] NSLog(@'value %f',val) switch(selectedRow) { case 0:// Celsius to Fahrenheit res=(val*1.8)+32break case 1: // Fahrenheit to Celsius res=(val-32)/1.8break case 2: // meter to centimeter res= val*100 break case 3://centimeter to meter res=val*0.01 break default: res=0.0 } NSString *final= [NSString stringWithFormat:@'%.02f',res] _ResultLabel.text = final } }

Kör nu appen och försök att klicka på konvertera-knappen utan att ange värden i textfältet.

Den andra typen av undantag som kan uppstå är om värdet i den första komponenten inte matchar värdet i den andra komponenten i UIPickerView. För detta kontrollerar vi om det aktuella valda komponentradvärdet för den andra komponenten är lika med värdet för radvärdet som returneras av metoden didSelectRow (). Om villkoret inte matchar är omvandlingen inte möjlig och om värdena matchar kan omvandlingen göras.

Vi kan implementera denna logik enligt följande,

- (IBAction) Konvertera: (UIButton *) avsändare {if ([_ ValueTextField.text length)<= 0) { [self showAlertWithMessage:@' Please enter the value'] } else { _ResultLabel.textColor= [UIColor blackColor] float res=0.0 NSInteger n =[_picker2 selectedRowInComponent:data2comp] if(n==secondrow) { float val=[_ValueTextField.text floatValue] NSLog(@'value %f',val) switch(selectedRow) { case 0:// Celsius to Fahrenheit res=(val*1.8)+32break case 1: // Fahrenheit to Celsius res=(val-32)/1.8break case 2: // meter to centimeter res= val*100 break case 3://centimeter to meter res=val*0.01 break default: res=0.0 } NSString *final= [NSString stringWithFormat:@'%.02f',res] _ResultLabel.text = final } else { // code for displaying error. _ResultLabel.textColor= [UIColor redColor] _ResultLabel.text = @'Result cannot be calculated' } }

Kör nu appen och se genom att ändra värdet i den andra komponenten efter att du gjort valet i den första komponenten.

Du kan se felmeddelandet att resultatet inte kan beräknas. Du kommer att märka att felmeddelandet skrevs ut i samma resultatetikett och att meddelandet är långt. Så det är därför etiketten flyttades ner från den tidigare orienteringen.

Så vår konverteringsapp är komplett. Du kan lägga till mer funktionalitet i appen enligt ditt val och göra den vackrare enligt din kreativitet.

Har du en fråga till oss? Nämn dem i kommentarfältet så återkommer vi till dig.

Relaterade inlägg: