How to create a custom software key UITextField/NSTextField - ios

I want to create a custom NSTextField/UITextField like this for entering a software key (pardon my paint skills).
Does anybody have any suggestions as to how I should go about this?
My lazy solution would be to give it a placeholder string with spaces and dashes in between, and as they type just mask those dashes into their string. But I wanted to see if anybody else had some input-- or if I should just go with your standard separate text fields

-(void)viewDidLoad
{
UITextField *firstPart = [[UITextField alloc] initWithFrame: YOUR_FRAME];
firstPart.placeholder = #"-";
firstPart.textAlignment = NSTextAlignmentCenter;
[self.view addSubview: firstPart];
// Create others
}
-(IBAction)unlockBtnPressed:(id)sender
{
NSString *softwareKey = [NSString stringWithFormat: #"%# - %# - %#", firstPart.text, secondPart.text, thirdPart.text];
}

Related

iOS: The proper way to display Images and long texts with scroll functionality

I'm developing an app for a news website, i'm displaying the news articles using UITableView where each cell is an article title, when a user clicks on a cell (i.e an article), another view opens (using segue), now in this view i want to put the following:
The article's Image at the top.
The article's date under the image.
The article's description under the date. (Which could be very long)
The ability for the user to scroll the entire view. (not only the description)
NOTE: I have tried so many ways, i can't seem to know the proper way to implement this structure.
The modern solution is actually relatively simple: compose the whole thing as an attributed string and put it into a UITextView. The text view will automatically deal with the fact that the description may be very long, that all content should scroll together, etc.
E.g.
NSAttributedString *imageString = [NSAttributedString attributedStringWithAttachment:
[[NSTextAttachment new] setImage:[UIImage imageNamed:#"whatever.png"]]];
... and use the natural means for composition of attributed strings and for setting things like font and colour on your other bits of text. Then just textView.attributedString = compoundString;.
Elaborated example:
- (void)setStory:(Story *)story
{
NSAttributedString *image = [story imageString];
NSAttributedString *date = [story dateString];
NSAttributedString *body = [story bodyString];
NSMutableAttributedString *wholeStory = [NSMutableAttributedString new];
// TODO: can you be sure image, date and body are all non-nil?
NSArray *allComponents = #[image, date, body];
for(NSAttributedString *component in allComponents)
{
[wholeStory appendAttributedString:component];
if(component != [allComponents lastObject])
[[wholeStory mutableString] appendString:#"\n\n"];
}
self.textView.attributedString = wholeStory;
}
... elsewhere, in the Story object ...
- (UIImage *)image
{
// ...something...
}
- (NSString *)dateText
{
// ...something, probably using NSDateFormatter unless it's returned
// from a server or wherever already formatted...
}
- (NSString *)bodyText
{
// ... something ...
}
- (NSAttributedString *)imageString
{
return [NSAttributedString attributedStringWithAttachment:
[[NSTextAttachment new] setImage:[self image]]];
}
- (NSAttributedString *)dateString
{
return [[NSAttributedString alloc]
initWithString:[self dateText]
attributes:
#{
NSFontAttributeName: [UIFont preferredFontForTextStyle: UIFontTextStyleSubheadline],
... etc ...
}];
}
- (NSAttributedString *)bodyString
{
return [[NSAttributedString alloc]
initWithString:[self bodyText]
attributes:
#{
NSFontAttributeName: [UIFont preferredFontForTextStyle: UIFontTextStyleBody],
... etc ...
}];
}
Check out the NSAttributedString UIKit Additions documentation for lists of the various attributes you can set other than NSFontAttributeName. Note that I've gone with the iOS 7+ way of asking for fonts by purpose rather than a specific size or font. That means that users who have turned up their default font size will get larger text in your app.
I have created a pod to programmatically add constraints. There is a special category for scrollViews, because they are so complicated to use with auto layout.
Here is the link to the project
There is an example app you can take a look at, but the things you would have to do would be
initialize your views (the image, date label and description label).
add the scrollView
add the subviews of the scrollView
UIScrollView *scrollView = [[UIScrollView alloc] init];
[self.view addSubview:scrollView];
[scrollView addConstraintsToFillHorizontal];
[scrollView addConstraintsToFillVertical];
[scrollView addConstraintsToAlignVerticalAllViews:#[image, dateLabel, descriptionLabel]];
This should be pretty simple to implement, but if you need more help, just let me know and I could provide you with some more sample code.
Good luck with your project!
Another way would be to display each article as a HTML string in a UIWebView.
NSURL *url = [NSURL URLWithString:self.articleController.url];
NSString *html = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:NULL];
[self.articleView.webView loadHTMLString:html baseURL:baseURL];

Displaying Array in Text Label

I'm still sort of new to Xcode, so please be patient with me. Anyway, I'm having a bit of trouble trying to display the whole contents of an array in a UILabel. I'm able to display it by simply using the code
wordList.text = [NSString stringWithFormat:#"List of Words:\n %#", listA];
However upon running, the label ends up displaying a parenthesis and the words on their own lines, as well as quotation marks around the words, and the ending quotation mark and a comma in the line between each word. Example:
List of Words:
(
"apple
",
"banana
",
"etc.
While I do want the words to be displayed in their own lines, I do not want the parenthesis and the closing quotation mark and comma being displayed in a separate line. I would also prefer removing the parenthesis, quotation marks, and commas all together, but I wouldn't mind too much if I'm unable to.
Could anyone please explain why its being displayed as such, and to help me correctly display each word of an array in its own line in a UILabel?
Use this:
NSArray *listOfWords = #[#"One", #"Two", #"Three"];
NSString * stringToDisplay = [listOfWords componentsJoinedByString:#"\n"];
wordList.text = stringToDisplay;
Will Display:
One
Two
Three
The parentheses, quotation marks, and commas are being added because providing an array as an argument to the format specifier %# causes the -(NSString *)description method to be sent to the array. NSArray overrides NSObject's implementation of description and returns a string that represents the contents of the array, formatted as a property list. (As opposed to just returning a string with the array's memory address.) Hence, the extra characters.
You Can use this Code
NSArray *listOfWords = [NSArray arrayWithObjects:
#"one.",
#"two.",
nil];
for (NSString *stringToDisplay in matters)
{
//frame, setting
labelFrame.origin.x = 20.0f;
UILabel *stringToDisplayLabel = [[UILabel alloc] initWithFrame:labelFrame];
stringToDisplayLabel.backgroundColor = [UIColor clearColor];
stringToDisplayLabel.font = [UIFont boldSystemFontOfSize:12.0f];
stringToDisplayLabel.lineBreakMode = NSLineBreakByWordWrapping;
stringToDisplayLabel.numberOfLines = 0;
stringToDisplayLabel.textColor = [UIColor whiteColor];
stringToDisplayLabel.textAlignment = NSTextAlignmentLeft;
//set up text
stringToDisplayLabel.text = stringToDisplay;
//edit frame
[stringToDisplayLabel sizeToFit];
labelFrame.origin.y += stringToDisplayLabel.frame.size.height + 10.0f;
[self.view addSubview:stringToDisplayLabel];
[matterLabel release];
}

Change size of text in UITextView based on content of NSString

I am trying to load a UITextView with content from instances of a NSManagedObject subclass (verses in a Bible reader app).
My UITextView is loaded by iterating through the verses in a selected chapter and appending each consecutive verse.
NSArray *selectedVerses = [[Store sharedStore] versesForBookName:selectedBook
ChapterNumber:selectedChapterNum];
displayString = #"";
for (Verse *v in selectedVerses) {
NSMutableString *addedString =
[NSMutableString stringWithFormat:#"%d %#", [v versenum], [v verse]];
displayString = [NSMutableString stringWithFormat:#"%# %#", addedString, displayString];
}
NSString *title = [NSString stringWithFormat:#"%# %#", selectedBook, selectedChapter];
[self setTitle:title];
[[self readerTextView] setNeedsDisplay];
[[self readerTextView] setText:displayString];
The above code generates the correct view, but only allows for one size of text for the entire UITextView.
I would like to have the verse number that precedes each verse to be a smaller size font than its verse, but have not found a way to make it work. I've been reading through the documentation, and it seems that this should be possible with TextKit and CoreText through the use of attributed strings, but I can't seem to get this to compile.
I do not want to load the view as a UIWebView.
Any suggestions for this are greatly appreciated.
You're looking for NSAttributedString and NSMutableAttributedString. You should read Introduction to Attributed String Programming Guide. They're generally like normal strings, but additionally contain attributes with ranges to which they apply. One more method that would be helpful to you is:
[self readerTextView].attributedText = yourAttributedString;
If you have some specific problems with attributed strings, please post your code.

Is there an option to implicitly localise labels in Interfacebuilder

Somewhere in a blog post I stumbled upon a strings file which looked like this:
// de.lproj/Localizable.strings
"This is the title" = "Das ist der Titel"
To me this looked like the actual labels in Interface builder were processed by the compiler so that no explicit translations using NSLocalizedString(#"SOME_IDENTIFIER", #""); would be necessary any more.
My question now, is whether there is some kind of shortcut or do I need to localise all my individual labels on my view e.g. in the awakeFromNib method.
I have figured out a way to semi-automate the process so that I don't have to do this:
label1.text = NSLocalizedString(#"label1_key", #"");
label2.text = NSLocalizedString(#"label2_key", #"");
....
labeln.text = NSLocalizedString(#"labeln_key", #"");
So for all labels which should be localised I set their text to __KeyForLabelX in IB. Then in the viewWillAppear method of the viewcontroller I loop through the items on the view and set the text to the localized value:
for (UIView *view in self.view){
if([view isMemberOfClass:[UILabel class]]){
UILabel *l = (UILabel *)view;
BOOL shouldTranslate = [l.text rangeOfString:#"__"].location != NSNotFound;
NSString *key = [l.text stringByReplacingOccurrencesOfString:#"__" withString:#"TranslationPrefix"];
if (shouldTranslate){
l.text = NSLocalizedString(key, #"");
}
}
}
My .strings file then look like this:
"TranslationPrefixKeyForLabelX" = "Translation of Label X";
Update: To further adapt the mechanism you could also check for other UIViews like UIButtons, UITextFields (including prompt text) etc.

UILabel not getting what I write to it

Tricky to write the subject to this. I guess this is a basic question but I can't seem to find the answer.
The code itself shows what I wanna do and the UILabel don't show anything, the first line I add to it works fine, but not when I try to write out the array:
-(IBAction)getSongHistory:(id)sender {
[historyLabel setText:#"test write\n test write another line"];
NSArray *pastMusicArray = [pastSongs getHistory];
for(int t=2; t<[pastMusicArray count]; t++) {
NSString *tempRow = [pastMusicArray objectAtIndex:t];
//NSLog(#"%#", tempRow);
[historyLabel setText:tempRow];
[historyLabel setText:#"\n"];
}
}
The NSLog do put out the right stuff.
What is gong on here, that I am not seeing?
Seems to me that the problem is that you are setting the full text each time and the last setText: is with #"\n" which is an invisible string. Try appending instead of setting the text. Something like:
historyLabel.text = [NSString stringWithFormat:#"%#%#", historyLabel.text,#"TextToAppend"];
This will append #"TextToAppend" to the current text value in the label.
Update: Notice I'm using the text property rather than the setter.
historyLabel.text = #"Some Text";
is equivalent to
[historyLabel setText:#"Some Text"];
Using \n in a string should be fine, try to set numberOfLines property of the label to 0, which allow any number of lines in it.
This is the solution for my own problem. Hope that it can help someone else.
NSArray *pastMusicArray = [pastSongs getHistory];
musicHistory = [[NSMutableString alloc] init];
historyLabel.numberOfLines = 0;
for(int t=2; t<[pastMusicArray count]; t++) {
[musicHistory appendString:[[pastMusicArray objectAtIndex:t] capitalizedString]];
[musicHistory appendString:#"\n"];
}
historyLabel.text = musicHistory;

Resources