How to add a shift key to an iOS 8 Custom Keyboard - ios

Right now I have created a basic prototype custom keyboard, however, I do not know how to make a shift key that would capitalize the letters. Right now the letters are all lowercase. Also I wrote this in Objective-C not Swift, but a swift based solution is welcome as well! :) Thank you

Make a key that toggles between whatever images you are using for it. When the key is toggled to shifted, store that in a boolean property.
Then, use this code for each key press:
- (NSString *)stringForAKeyPress:(id)sender {
if (self.shifted) {
return #"A";
} else {
return #"a";
}
}

Related

how to identify UITextField in a better way

I am using xcode8+swift3.
I have multiple UITextField in my controller view. Each UITextField has a outlet connection in code.
I know I can use “tag” to identify UITextField, but it seems I can only use number as tag (I tried with string value for tag field, my Xcode always get stuck, only number as tag works).
But I don’t want to use magic number in my code like:
If (textField.tag == 0) {
}
I am wondering, is there a better way or more descriptive way in code to identify UITextField?
Tag is the correct tool. Just create an enum for them to track.
enum FieldIdentifier: Int {
case name = 0
case age = 1
}
if let fieldIdentifier = FieldIdentifier(rawValue: textField.tag) {
switch fieldIdentifier {
case .name: ...
case .age: ...
}
}
(Note that Larme's comment about using == is also appropriate, and if you already have outlets is better.)

containsObject is returning NO after the app is restarted

I have a UITabelView displaying a list of items(returned from the server), users will be able to select any item and add it to his own section.
Upon selecting an item, I am retrieving the selected item details and saving it to a pList file, the list will then be displaying a small icon informing the user that the item is added to his section. User will be able to remove it from his section by tapping the icon again.
To know if the item is already in his section, i am using
[self.myItemsArray containsObject:item]
Everything is working perfect if the user don't exit the application. The issue is occurring once the app is restarted. When I retrieve the tableview list from the database or from server, all the items will not be shown as on my list and [self.myItemsArray containsObject:item] will return NO for the previous added items.
I was searching for an alternative way, by creating an NSArray of my items id's and will then check if the new array will contains the item id to display the icon.
the new issue is that the id is returned as double from the server and stored as it is. The application is crashing when creating the array:
[self.myItemsArray valueForKey:#"Id"]
myItemsArray is an array of items(item is an NSDictionary containing all the details)
So i am desperate now,could anyone help me by resolving any of the above issues?
I prefer the first one, since containsObject will be more simple, but I don't mind to solve it with the second choice if the first will not work.
You'll need to make sure you have a good isEqual: method defined for your custom class, since that's what NSArray uses to determine containment: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/#//apple_ref/occ/instm/NSArray/containsObject:
Let's say this class has something like a 'key' or 'id' value that is unique for each instance of the class (which in your case is a double type). This will not always be the case, of course; it's often an aggregate of individual properties/ivars that constitutes a unique 'key', but for the purposes of this discussion let's say that such a field exists. Your code might look something like this (all in the .m):
static double const EPSILON = .000000001; // You'll need to be the judge of how "close" values can be to each other but still be distinct
#interface MyObjectClass: NSObject
#property (nonatomic, readonly) double uniqueKey;
#end
#implementation MyObjectClass
// ...
- (BOOL)isEqual:(id)object
{
if (self == object) { return YES; }
if (!object isKindOfClass:[MyObjectClass class]]) { return NO; }
MyObjectClass *myObject = (MyObjectClass *)object;
if (abs(self.uniqueKey - myObject.uniqueKey) < EPSILON) { return YES; }
return NO;
}
//...
#end
Note that you should NOT check for direct equality between two float or double values; see How dangerous is it to compare floating point values? for a good discussion about the pitfalls of working with floating point and double precision values.

How to fix string in objective-c?

I'm having a problem with the correct answer
When the user types in lets say "dog" the answer is right!
But if s/he types in "dog " <--- with a spacebar its wrong,
how do i fix this:
Code:
- (IBAction)btncheck:(id)sender {
if ([_textbox.text isEqualToString:#"q"]) {
_keyboard.hidden = YES;
_textXclear.hidden = YES;
}
else {
// Was not correct. Notify user, or just don't do anything
}
and id like to notify user that the answer was not correct by placing an image, how is that done
You could use the method stringByTrimmingCharactersInSet to get rid of leading or trailing spaces:
NSString *string = [_textbox.text stringByTrimmingCharactersInSet: whitespaceCharacterSet];
if (string isEqualToString: "q")
{
//string is wrong? If so, display an error message.
}
else
{
//string is correct, resign first responder
}
You should do a search on NSString in the Xcode help system and read the NSString class reference. There are tons of useful methods in the NSString class for doing things like this.
I'm confused, because in your previous post I thought that the answer "q" was the correct answer. In your code above, anything but q would be correct.
As far as placing an image, the easiest thing to do is probably to put an image view, with image installed, in your view controller, but set it's hidden property to YES. Then, when you decide the user has entered the correct answer, set the image view's hidden property to NO to reveal it.

Method To Delete 2nd Label, Then First Label, Not Functioning Correctly

I know I am missing something obvious, but I just cannot see it. This method is meant to compare the text of a label to the text of a text box, and then delete the text. So if the 1st label reads "Puppy" and the 2nd label reads "Kittens," and the text box says "Kittens," the method should delete the text of the 2nd label and leave the 1st label's text. If the 2nd label is blank, then the method should delete the text of the 1st label.
But no matter how I mess with the method, either it deletes the 2nd label but not the 1st, deletes both of them, or deletes neither of them. Here's what I've tried
(lblFabric1 is the 1st label, lblFabric2 is the 2nd label, txtType is the text box):
-(IBAction)btnDelete:(id)sender
{
if ((self.lblFabric2.text== self.txtType.text))
{
self.lblFabric2.text = #"";
}
else if ((self.lblFabric2.text != self.txtType.text))
{
self.lblFabric1.text=#"";
}
}
It deletes the 2nd label, but not the 1st label. If I try to set the "Else if" to:
else if ((self.lblFabric2.text==#""))
it gives me an error (""Direct comparison of a string literal has undefined behavior.") Am I just going about this the wrong way? What am I missing?
You should not use == or != for string comparison in Objective C. You need to use the isEqualToString or isEqual method.
if (([self.lblFabric2.text isEqualToString:self.txtType.text]))
When you use == or != you are comparing the pointers where the strings are stored.
To compare NSStrings use:
if ([myString1 isEqualToString:myString2])
Documentation
Compairing String literals using == is not guaranteed to behave as you might expect. Use isEqual: or isEqualToString: instead.
See http://nshipster.com/equality/.
When you are comparing NSStrings with == what you are actually comparing are two memory addresses and that is not what you are really intended for. You want to compare the values of two strings what == operator is not suitable for and thus you are getting the warning
Direct comparison of a string literal has undefined behavior.
To compare the values of NSStrings you should use isEqualToString: method. You could have also use isEqual: method derived from NSObject class but that is not suitable for Unicode comparison. So isEqualToString: is always the safest bet.
After using isEqualToString: your code should look something like:
-(IBAction)btnDelete:(id)sender
{
if ([self.lblFabric2.text isEqualToString:self.txtType.text])
{
self.lblFabric2.text = #"";
}
else
{
self.lblFabric1.text=#"";
}
}

Pass different parameters to an IBAction

My iPhone app has many buttons and I want all the buttons to call the same method, but with different parameters.
For example I want tapping one button to call the method myMethod: with the argument #"foo", and a second button should call the same method but with argument #"bar".
The so called "IBActions" must have one of these signatures:
-(void)action;
-(void)actionWithSender:(id)sender;
-(void)actionWithSender:(id)sender event:(UIEvent*)event;
You cannot add any other parameters. Nevertheless you can use sender (which is button1 or button2 in your case) to get the parameter:
-(void)actionWithSender:(UIButton*)sender {
NSString* parameter;
if (sender.tag == 1) // button1
parameter = #"foo";
else // button2
parameter = #"bar";
...
}
the real reason You cannot add additional parameter is that UIKIT will push params on the stack.
so the only way is to use tags.
A DIRTY way can be to convert a pointer to int and tagging the button with it:
myStruct params;
// fill params:
params.x=....
params.y=....
params.z=....
UIButton * btn = [UIButton......]; // create or use one from XIB
btn.tag = (int)&params;
... in Call back:
-(IBActions) doIt:(id)sender
{
myStruct * paramsPtr = (myStruct*)tag;
int i = paramsPtr->x;
NOTE: params MUST be keep static .. or allocate using malloc (more and more ugly code...).
DO NOT use a local var: it will be allocated on stack so will be removed after exiting from the setup method.
Give your various UIButton instances different tag property values.
In your IBAction method -myMethod:, you might then do something like:
- (void) myMethod:(id)sender {
switch (sender.tag) {
case (firstButtonTag):
doFooStuff;
break;
case (secondButtonTag):
doBarStuff;
break;
// etc.
}
}
The values firstButtonTag and secondButtonTag can be stored in an enum if you want to make this easy to maintain.
You can't pass parameters through an IBAction. What I usually do is give the buttons the unique tag in IB. THe tag is an integer value so I u then use a simple lookup table to convert the tag to some value.
In this case, three buttons but tags 1 to 3:
- (IBAction) buttonPressed: (UIButton*) sender
{
static const NSString* names = { #"Foo", #"Bar", #"Baz" };
id tag = [sender tag];
if (tag >= 1 && tag <= 3) {
NSLog(#"Button pressed is %#", names[tag]);
}
}
(id)Sender is shows that whatever u pass on UIButton click event is directly pass to this method and no matter that what type it is , it take automatically like if you pass button tag then it take button tag as sender.tag etc
As others have mentioned you cannot pass your custom parameter into action method. If you do not like the solution using tags you may also subclass UIButton with your custom class and add your parameter there. (By I wouldn't bother and just use tags)
You don't. The only parameter is the sender object, which you may use to have a different behavior, but what I'd do is define 2 action methods, which simply in turn call the same method with a different parameter, i.e. you'd have:
- (IBAction)button1:(id)sender
{
[self doStuff:kButton1];
}
- (IBAction)button2:(id)sender
{
[self doStuff:kButton2];
}
- (void)doStuff:(ParamType)param;
{
...
}
In defense of that method (no pun intended), I'd add that it makes clearer when you review your UI with Interface Builder to see that different buttons actually have different effects, which is harder to tell if they all call whateverAction:

Resources