iOS Text View Not Updating - objective-c

I've got a UITextView defined by
#property (nonatomic, retain) IBOutlet UITextView *quote;
in my view controller header, and I can set the value by using
quote.text = #"some text";
but the view doens't want to update the value, what can I do

Setting the text should immediately cause the UITextView to render your text under normal conditions.
Are you sure your that:
The UITextView is placed appropriately in your Nib and is visible?
The UITextView is appropriately linked with your outlet in your file owner (aka view controller)?
A quick test to verify the visibility of your UITextView - just place some sample text in it in the nib and verify that it appears on launch. If so, then you know that at least your view is displaying appropriately. At that point, it would have to be related to #2.

Make sure you connected quote to your UITextField in your XIB. Also, make sure that you #synthesize quote; in your .m.

I just bumped into this too and the problem went away as soon as I specified enough height for the content. In Xcode it may still look all right, but AutoLayout decided to do without the TextView if there was no height-constraint on it.
This was probably not your problem back when you asked the question, but it still turned up fairly early in my google search, therefore I post this answer anyway.
Btw: Xcode is still acting a little skiddish when you edit the constraint. It will update the view (and save) if you hit 'Enter' in the Constant-Field, but it will not do so if it loses focus in some other way.
This just to show us how difficult it is to get user interfaces right all the time.

Related

Replacing NSTextField with NSScrollView to get a scrollbar

My OS X app written in Objective-C needs to display a varying NSString* variable theString which can get quite large.
I use Xcode IB to build a nib file which displays theString in a NSTextField* object panel declared inside AppDelegate.h like this:
#property (weak) IBOutlet NSTextField *panel;
Now I can set the contents of panel inside AppDelegate.m like this:
self.panel.stringValue = theString;
This all works fine. But I now want to give my text field a scrollbar. So in place of a "Text Field" I choose a "Text View" from the Object Library, and get its blue line to generate me a new declaration of panel which now looks like this:
#property (weak) IBOutlet NSScrollView *panel;
This now no longer works:
self.panel.stringValue = theString;
raising the error: (!) Property 'stringValue' not found on object of type 'NSScrollView*'
How do I need to fixup this statement?
(Might I just say I find the extensive Apple documentation on the topic byzantine and opaque. Why am I being naive to expect a simple answer to this simple question, as it all seems to imply? I must be missing something obvious -- what is it?)
What you got was a NSTextView wrapped inside a NSScrollView. The scrollView is the thing that makes the scrollbars you want. It basically holds a potentially much larger view inside its viewport and shows only small part of it, that you can shift around with the scroll bars. You need to get (another) reference from your code to the NSTextView inside the scrollView. You can find the NSTextView in the hierarchy in IB and attach to that.
This is in the direction of what you want but I think not quite what you need. The textView is a far more advanced control than a simple textField and probably more than you need. You could instead use a custom view by taking a NSScrollView that comes with a default NSView wrapped inside. Then instead of the NSTextView place your NSTextField on the NSView. The issue with this is that then you need to add some code to auto-resize the NSTextField and NSView based on the content of the textField. Once you got that sorted the scrollView will automatically arrange for the scrollbars that you need.

Setting the Keyboard property in iPad

Ok, I'm in the process of developing my first iPad application. Yea I'm a newbie. I'm running into a number of problems implementing properties even though I'm using the exact same code as I used for the iPhone. I thought the two platforms were (are) the same iOS? For example, I can not set the Keyboard type for a UITextField either directly through Storyboard or programmatically. Here's what I've done:
storyboard
keyboard = number pad
programmatically
header
IBOutlet UITextField *txtValue;
#property (nonatomic, retain) UITextField *txtValue;
implementation
#synthesize txtValue;
txtValue.keyboardType = UIKeyboardTypeNumberPad;
I also tried:
[txtValue setKeyboardType:UIKeyboardTypeNumberPad];
Also there is an active IBOutlet for the UITextField between the ViewController screen and ViewController file in the Connections Inspector and the User Interaction enabled is checked.
There's absolutely nothing wrong with the default keyboard other than the fact that it's not what I want. Any idea what is going on here? Thanks...
I think I know what the answer is and it's pretty dumb. The answer is, there only is one keyboard on an iPad. The property only sets the configuration when it is opened. So if you set the Keyboard to NumberPad, the same keyboard opens up with the numbers showing. Not sure I like this.
That keyboard is not available on the iPad.
If you do not like the standard keyboard, I'd recommend you look into creating your own custom keyboard. Here is a document to help get you started:
http://developer.apple.com/library/ios/#documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/InputViews/InputViews.html#//apple_ref/doc/uid/TP40009542-CH12-SW2
All things considered, a custom iOS keyboard isn't as hard as it sounds. It's just another custom view. The hardest part is making some graphics to make it look the way you want.
If the custom route is not what you're looking for, there are also several "custom" keyboard people have already made. Checkout github or CocoaControls. Here is just one example of a custom number pad someone's made for the iPad:
https://github.com/azu/NumericKeypad
NumberPad is not a supported type on iPad.
(command/apple click on the UIKeyboardTypeNumberPad to see more about it)

What really happens when a UIView becomes hidden?

This may sound like a weird question, but what exactly happens when it becomes hidden. It would be great to see the UIView source code, but that isn't going to happen.
Here why I'm wondering:
I'm trying to add a UIWindow (a transparent one with userinteractionenabled set to NO) above my application to tint the screen. It works perfectly fine until the user tries to share by SMS using Apples MessageUI.framework. When this happens and the MFMessageComposeViewController or MFMailComposeViewController appears, these view controllers won't receive user input. I've tried tons of thing and the only things that worked, allowing the user to interact with the views, was setting the UIWindow (the one I added) to either an alpha of 0 or set hidden to YES. I want to replicate this without hiding the view, which is why I want to know exactly what happens when the UIWindow (which is a subclass of UIView) is hidden.
There is usually only one window in iOS apps. You're better off using just a UIView for this task instead of a UIWindow. UIWindow adds some view hierarchy and event management capabilities to the UIView class. This functionality is interfering with the expected behavior in your app. I think it will just work if you change the class of this view to UIView instead of UIWindow.

When should I use an IBOutlet instead of an IBAction?

I know the differences between IBAction and IBOutlet, but I don't know when I should use one over the other.
For example, I'm trying to make a calculator. I have ten buttons and one label to display a result. Must I create ten IBOutlets in my interface? If not, why not?
An IBOutlet is a connection to an object, and an IBAction is a connection to a method to be invoked as a callback. For example, you might have ten buttons and one label, but you might connect to the label using an IBOutlet (so you can update its value), and a single function - (IBAction)buttonPressed:(id)sender; that is connected to the onTouchUpInside event of each of the ten buttons. The buttonPressed: method's implementation will then need to inspect the sender to figure out what its value is.
You should not need to have an IBOutlet for each button if this is all you need to do.
Ok, IBOutlets and IBActions serve two separate purposes.
IBActions are basically methods that can be connected to UI elements through IB. They provide ways for your object to be notified when something has happened with the UI. They also provide the sender argument when they are called so that you can access the UI Element that sent the message from within the method.
An IBOutlet on the other hand offers a way to get a reference to the UI element within your code at any point, it is used when you need to change aspects of the UI.
For your situation you don't really need to have IBOutlets for the buttons because you don't need to change anything about them, you just need to be notified when they have been pressed.
As a note, if you have that many buttons, and you for some reason needed a way to access them from within your code to change something about them i would not recommend using 10 IBOutlets. Instead, i would use the viewWithTag: method, and set each buttons tag accordingly so that you don't have to go to the trouble of creating IBOutlets for each one.
In your case, I would create one IBOutlet for the label, and one IBAction for the buttons. The IBOutlet for the label would be to update the text when the user pressed a button. Your IBAction would look something like this:
-(IBAction)digitPressed:(UIButton *)sender{
//First you have to check if there is currently any text in the label
//If there is not, the below line of code is performed
NSString *textWithDigit = [[yourLabel.text] stringByAppendingString: sender.titleLabel];
//This line updates the label's text
label.text = textWithDigit;
}
I only put in the code relevant to IBActions and IBOutlets (you need an IBOutlet for the label in order to update the text, and you need the IBAction to change the label's text to the digit pressed); there is much more code needed (code needed to check if the user is currently in the middle of typing a number, code for operations like +, -, *, /), but this was just a start.
Hope this helps!

uitextfield delegate must be file's owner?

I've seen a few references (eg here) in response to folks having trouble getting the keyboard to dismiss in iPhone that say "double check that the delegate is attached to file's owner.
Is this necessarily true? Or just standard practice? Can't I have other objects in my nib, such as a subclass of UIViewController, and make connections to those as I like? I'd hate to have to route everything into the object that happens to be file owner.
That said, I'm having a difficult time getting the keyboard to disappear. I know it's connected to the delegate, because I can set break points and step through the code. I can see the [theTextField resignFirstResponder] get called (and return true), but the keyboard still won't go away.
Any other suggestions?
All of the controls in a particular view are intended to talk to the View Controller that owns the nib file. Even if you have, say, a UISlider that changes the value of a UITextField, this will be handled by a method in your UIViewController subclass that gets fired when the slider's value changes and updates the text in the text field. So 9 times out of 10 your UIViewController will be the nib file's owner.
Typically the text field delegate method you want to define is textFieldShouldReturn, calling resignFirstResponder on the text field, which it sounds like you've done.
Make sure that your outlet for theTextField is connected as well. It can be nil and the runtime will treat [nil resignFirstResponder] as a noop, not as an error.