GithubHelp home page GithubHelp logo

slackhq / slacktextviewcontroller Goto Github PK

View Code? Open in Web Editor NEW
8.3K 8.3K 1.1K 15.88 MB

⛔️**DEPRECATED** ⛔️ A drop-in UIViewController subclass with a growing text input view and other useful messaging features

Home Page: https://slack.com/

License: MIT License

Objective-C 98.08% Shell 0.28% Ruby 1.64%

slacktextviewcontroller's Introduction

Deprecation

We are no longer providing support for SlackTextViewController. This project satisfied all of our iOS messaging needs in the past and we are proud to have contributed it to the open-source community. Today, in order to delight our users with a solution that is highly tailored and rapidly iterated-upon, we have shifted focus to our internal projects. Unfortunately, this renders us lacking the capacity to support our past projects in addition to our newer, internal projects. This project has been deprecated as a result.

SlackTextViewController

IMPORTANT NOTICE: Please update to >= 1.9 to avoid any risk of app rejection. More details in #361

License Pod Version Carthage compatible BuddyBuild

A drop-in UIViewController subclass with a growing text input view and other useful messaging features. Meant to be a replacement for UITableViewController & UICollectionViewController.

Demo Gif

This library was historically used in our iOS app. At its inception, the library satisfied our product needs and was flexible enough to be reused by others wanting to build great messaging apps for iOS.

Feature List

Core

Additional

Compatibility

  • Carthage & CocoaPods
  • Objective-C & Swift
  • iOS 7, 8 & 9
  • iPhone & iPad
  • Storyboard
  • UIPopOverController & UITabBarController
  • Container View Controller
  • Auto-Rotation
  • iPad Multitasking (iOS 9 only)
  • Localization

Installation

With CocoaPods:
pod "SlackTextViewController"
With Carthage:
github "slackhq/SlackTextViewController"
Manually:

There are two ways to do this:

  • Copy and drag the Source/ folder to your project.
  • or compile the project located in Builder/SlackTextViewController.xcodeproj to create a SlackTextViewController.framework package. You could also link the library into your project.

How to use

Subclassing

SLKTextViewController is meant to be subclassed, like you would normally do with UITableViewController or UICollectionViewController or UIScrollView. This pattern is a convenient way of extending UIViewController. SlackTextViewController manages a lot behind the scenes while still providing the ability to add custom behaviours. You may override methods, and decide to call super and perform additional logic, or not to call super and override default logic.

Start by creating a new subclass of SLKTextViewController.

In the init overriding method, if you wish to use the UITableView version, call:

Obj-C
[super initWithTableViewStyle:UITableViewStylePlain]
Swift
super.init(tableViewStyle: .Plain)

or the UICollectionView version:

Obj-C
[super initWithCollectionViewLayout:[UICollectionViewFlowLayout new]]
Swift
super.init(collectionViewLayout: UICollectionViewFlowLayout())

or the UIScrollView version:

Obj-C
[super initWithScrollView:self.myStrongScrollView]
Swift
super.init(scrollView: self.myStrongScrollView)

Protocols like UITableViewDelegate and UITableViewDataSource are already setup for you. You will be able to call whatever delegate and data source methods you need for customising your control.

Calling [super init] will call [super initWithTableViewStyle:UITableViewStylePlain] by default.

Storyboard

When using SlackTextViewController with storyboards, instead of overriding the traditional initWithCoder: you will need to override any of the two custom methods below. This approach helps preserving the exact same features from the programatic approach, but also limits the edition of the nib of your SLKTextViewController subclass since it doesn't layout subviews from the nib (subviews are still initialized and layed out programatically).

if you wish to use the UITableView version, call:

Obj-C
+ (UITableViewStyle)tableViewStyleForCoder:(NSCoder *)decoder
{
    return UITableViewStylePlain;
}
Swift
override class func tableViewStyleForCoder(decoder: NSCoder) -> UITableViewStyle {
    return .Plain
}

or the UICollectionView version:

Obj-C
+ (UICollectionViewLayout *)collectionViewLayoutForCoder:(NSCoder *)decoder
{
    return [UICollectionViewFlowLayout new];
}
Swift
override class func collectionViewLayoutForCoder(decoder: NSCoder) -> UICollectionViewLayout {
    return UICollectionViewFlowLayout()
}

Sample Project

Check out the sample project, everything is demo'd there. There are 2 main examples (different targets) for testing the programatic and storyboard approaches, and a Swift example. Most of the features are implemented for you to quickly start using them.

Feel free to contribute!

Features

Growing Text View

Growing

The text view expands automatically when a new line is required, until it reaches its maxNumberOfLinesvalue. You may change this property's value in the textView.

By default, the number of lines is set to best fit each device dimensions:

  • iPhone 4 (<=480pts): 4 lines
  • iPhone 5/6 (>=568pts): 6 lines
  • iPad (>=768pts): 8 lines

On iPhone devices, in landscape orientation, the maximum number of lines is changed to fit the available space.

Inverted Mode

Some layouts may require to show from bottom to top and new subviews are inserted from the bottom. To enable this, you must use the inverted flag property (default is YES/true). This will actually invert the entire ScrollView object. Make sure to apply the same transformation to every subview. In the case of UITableView, the best place for adjusting the transformation is in its data source methods like:

Obj-C
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
    cell.transform = self.tableView.transform;
}
Swift
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        
    if let cell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) {
        cell.transform = self.tableView.transform
    }
}

Autocompletion

We use autocompletion for many things: names, channels, emoji, and more.

Autocompletion

To set up autocompletion in your app, follow these simple steps:

1. Registration

You must first register all the prefixes you'd like to support for autocompletion detection:

Obj-C
[self registerPrefixesForAutoCompletion:@[@"#"]];
Swift
self.registerPrefixesForAutoCompletion(["@", "#"])

2. Processing

Every time a new character is inserted in the text view, the nearest word to the caret will be processed and verified if it contains any of the registered prefixes.

Once the prefix has been detected, didChangeAutoCompletionPrefix:andWord: will be called. This is the perfect place to populate your data source and show/hide the autocompletion view. So you must override it in your subclass, to be able to perform additional tasks. Default returns NO.

Obj-C
- (void)didChangeAutoCompletionPrefix:(NSString *)prefix andWord:(NSString *)word
{
    NSArray *array = [NSArray arrayWithArray:self.channels];
    
    if ([prefix isEqualToString:@"#"] && word.length > 0) {
        self.searchResult = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"self BEGINSWITH[c]", word]];
    }
    
    BOOL show = (self.searchResult.count > 0);
    
    [self showAutoCompletionView:show];
}
Swift
override func didChangeAutoCompletionPrefix(prefix: String, andWord word: String) {
    
    let array: NSArray = self.channels
    
    if prefix == "#" && word.characters.count > 0 {
        self.searchResult = array.filteredArrayUsingPredicate(NSPredicate(format: "self BEGINSWITH[c] %@", word))
    }
    
    let show = (self.searchResult.count > 0)
    
    self.showAutoCompletionView(show)
}

The autocompletion view is a UITableView instance, so you will need to use UITableViewDataSource to populate its cells. You have complete freedom for customizing the cells.

You don't need to call reloadData yourself, since it will be invoked automatically right after calling the showAutoCompletionView method.

3. Layout

The maximum height of the autocompletion view is set to 140 pts by default. You can update this value anytime, so the view automatically adjusts based on the amount of displayed cells.

Obj-C
- (CGFloat)heightForAutoCompletionView
{
    CGFloat cellHeight = 34.0;
    return cellHeight*self.searchResult.count;
}
Swift
override func heightForAutoCompletionView() -> CGFloat {
    let cellHeight:CGFloat = 34
    return cellHeight * CGFloat(self.searchResult.count)
}

4. Confirmation

If the user selects any autocompletion view cell on tableView:didSelectRowAtIndexPath:, you must call acceptAutoCompletionWithString: to commit autocompletion. That method expects a string matching the selected item, that you would like to be inserted in the text view.

Obj-C
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([tableView isEqual:self.autoCompletionView]) {
        
        NSMutableString *item = [self.searchResult[indexPath.row] mutableCopy];
        [item appendString:@" "]; // Adding a space helps dismissing the auto-completion view
        
        [self acceptAutoCompletionWithString:item keepPrefix:YES];
    }
}
Swift
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        
    if tableView.isEqual(self.autoCompletionView) {
        var item = self.searchResult[indexPath.row]
        item += " "  // Adding a space helps dismissing the auto-completion view
            
        self.acceptAutoCompletionWithString(item)
    }
}

The autocompletion view will automatically be dismissed and the chosen string will be inserted in the text view, replacing the detected prefix and word.

You can always call cancelAutoCompletion to exit the autocompletion mode and refresh the UI.

Edit Mode

Edit Mode

To enable edit mode, you simply need to call editText:, and the text input will switch to edit mode, removing both left and right buttons, extending the input bar a bit higher with "Accept" and "Cancel" buttons. Both of this buttons are accessible in the SLKTextInputbar instance for customisation.

To capture the "Accept" or "Cancel" events, you must override the following methods.

Obj-C
- (void)didCommitTextEditing:(id)sender
{
    NSString *message = [self.textView.text copy];
    
    [self.messages removeObjectAtIndex:0];
    [self.messages insertObject:message atIndex:0];
    [self.tableView reloadData];
    
    [super didCommitTextEditing:sender];
}

- (void)didCancelTextEditing:(id)sender
{
    [super didCancelTextEditing:sender];
}
Swift
override func didCommitTextEditing(sender: AnyObject) {
    
    let message:String = self.textView.text
    
    self.messages.removeAtIndex(0)
    self.messages.insert(message, atIndex: 0)
    
    self.tableView!.reloadData()
    
    super.didCommitTextEditing(sender)
}
 
override func didCancelTextEditing(sender: AnyObject) {
        
    super.didCancelTextEditing(sender)
}

Notice that you must call super at some point, so the text input exits the edit mode, re-adjusting the layout and clearing the text view. Use the editing property to know if the editing mode is on.

Markdown Formatting

Markdown Formatting

You can register markdown formatting symbols so they can easily be used to wrap a text selection, with the help of the native contextual menu, aka UIMenuController. This feature doesn't take care of the rendering of the markdown: it's sole purpose is to ease the formatting tools to the user. Optionally, you can enable autoCompleteFormatting so any pending markdown closure symbol can be added automatically after double tapping on the keyboard spacebar, just like the native gesture to add a sentence period. The sentence period is still being added as a fallback.

Markdown Formatting Animated

1. Registration

You must first register the formatting symbol and assign a title string to be used in the menu controller item.

Obj-C
[self.textView registerMarkdownFormattingSymbol:@"*" withTitle:@"Bold"];
Swift
self.textView.registerMarkdownFormattingSymbol("*", withTitle: "Bold")

2. Customisation

Futher more, you can customise some of the behavior for special formatting cases, using the UITextViewDelegate methods. In the following example, we don't present the Quote formatting in the contextual menu when the text selection isn't a paragraph.

Obj-C
- (BOOL)textView:(SLKTextView *)textView shouldOfferFormattingForSymbol:(NSString *)symbol
{
    if ([symbol isEqualToString:@">"]) {
        
        NSRange selection = textView.selectedRange;
        
        // The Quote formatting only applies new paragraphs
        if (selection.location == 0 && selection.length > 0) {
            return YES;
        }
        
        // or older paragraphs too
        NSString *prevString = [textView.text substringWithRange:NSMakeRange(selection.location-1, 1)];
        
        if ([[NSCharacterSet newlineCharacterSet] characterIsMember:[prevString characterAtIndex:0]]) {
            return YES;
        }

        return NO;
    }
    
    return [super textView:textView shouldOfferFormattingForSymbol:symbol];
}

In this other method implementation, we don't want to allow auto-completion for the Quote formatting since it doesn't require a closure.

Obj-C
- (BOOL)textView:(SLKTextView *)textView shouldInsertSuffixForFormattingWithSymbol:(NSString *)symbol prefixRange:(NSRange)prefixRange
{
    if ([symbol isEqualToString:@">"]) {
        return NO;
    }
    
    return [super textView:textView shouldInsertSuffixForFormattingWithSymbol:symbol prefixRange:prefixRange];
}

Typing Indicator

Typing Indicator

Optionally, you can enable a simple typing indicator, which will be displayed right above the text input. It shows the name of the people that are typing, and if more than 2, it will display "Several are typing" message.

To enable the typing indicator, just call:

Obj-C
[self.typingIndicatorView insertUsername:@"John"];
Swift
self.typingIndicatorView?.insertUsername("John")

and the view will automatically be animated on top of the text input. After a default interval of 6 seconds, if the same name hasn't been assigned once more, the view will be dismissed with animation.

You can remove names from the list by calling:

Obj-C
[self.typingIndicatorView removeUsername:@"John"];
Swift
self.typingIndicatorView?.removeUsername("John")

You can also dismiss it by calling:

Obj-C
[self.typingIndicatorView dismissIndicator];
Swift
self.typingIndicatorView?.dismissIndicator()

Panning Gesture

Dismissing the keyboard with a panning gesture is enabled by default with the keyboardPanningEnabled property. You can always disable it if you'd like. You can extend the verticalPanGesture behaviors with the UIGestureRecognizerDelegate methods.

Hideable TextInputbar

Sometimes you may need to hide the text input bar. Very similar to UINavigationViewController's API, simply do:

Obj-C
[self setTextInputbarHidden:YES animated:YES];
Swift
self.setTextInputbarHidden(true, animated: true)

Shake Gesture

Shake Gesture

A shake gesture to clear text is enabled by default with the undoShakingEnabled property.

You can optionally override willRequestUndo, to implement your UI to ask the users if he would like to clean the text view's text. If there is not text entered, the method will not be called.

If you don't override willRequestUndo and undoShakingEnabled is set to YES/true, a system alert will be shown.

External Keyboard

There a few basic key commands enabled by default:

  • cmd + z -> undo
  • shift + cmd + z -> redo
  • return key -> calls didPressRightButton:, or didCommitTextEditing: if in edit mode
  • shift/cmd + return key -> line break
  • escape key -> exits edit mode, or auto-completion mode, or dismisses the keyboard
  • up & down arrows -> vertical cursor movement

To add additional key commands, simply override keyCommands and append super's array.

Obj-C
- (NSArray *)keyCommands
{
    NSMutableArray *commands = [NSMutableArray arrayWithArray:[super keyCommands]];
    
    // Edit last message
    [commands addObject:[UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow
                                           modifierFlags:0
                                                   action:@selector(editLastMessage:)]];
    
    return commands;
}
Swift
override var keyCommands: [UIKeyCommand]? {
        
    var commands = super.keyCommands
        
    // Edit last message
    let command = UIKeyCommand(input: UIKeyInputUpArrow, modifierFlags: .Command, action: "editLastMessage:")
    commands?.append(command)
        
    return commands
}

There are also a set of useful flags for keyboard special detections such as isExternalKeyboardDetected, isKeyboardUndocked, typingSuggestionEnabled and isTrackpadEnabled (iOS 9 only)

Dynamic Type

Dynamic Type is enabled by default with the dynamicTypeEnabled property. You can always disable it if you'd like, but the text input bar would still adjust to best fit the font size of the text view.

Dynamic-Type

Xcode Templates

Template

We have prepared a set of useful Xcode templates so you can quickly start using SlackTextViewController.

To install them, open up your terminal and type:

sh ./SlackTextViewController/File\ Templates/install.sh

These templates are also available in Alcatraz.

slacktextviewcontroller's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

slacktextviewcontroller's Issues

Consider Changing UIButton Type

The Left/Right Buttons are currently:

_leftButton = [UIButton buttonWithType:UIButtonTypeSystem]; and _rightButton = [UIButton buttonWithType:UIButtonTypeSystem];.

However, when setting an image to the button (I am doing the left one), it actually just turns it into a colored box, as explained here: http://stackoverflow.com/questions/18133465/setting-uibutton-image-results-in-blue-button-in-ios-7

Changing the UIButton type to UIButtonTypeCustom fixes the issue. I can submit a PR for this; I just haven't done extensive testing.

Edit: This disables the automatic tint coloring.

Incorrect Calculation of Text Input Field Distance from Bottom

When presenting the SlackTextViewController with the keyboard already up, I do this:

- (void)viewWillLayoutSubviews;
{
    [super viewWillLayoutSubviews];
    [self.textView becomeFirstResponder];
}

However, this causes the Text Input Bar to be miscalculated when positioned. I have a Tab Bar in my application, but I hide the tab bar when I push on the message view. It's not technically "hidden" though, so the appropriateKeyboardHeight: assumes it's lower than it should be.

I've fixed it by adding in the additional check:

CGFloat keyboardHeight = 0.0;
CGFloat tabBarHeight = ([self.tabBarController.tabBar isHidden] || self.hidesBottomBarWhenPushed) ? 0.0 : CGRectGetHeight(self.tabBarController.tabBar.frame);

Checking self.hidesBottomBarWhenPushed as well as if the bar is hidden.

Thanks!

Text input bar is hidden after the keyboard is appeared.

In - (BOOL)detectExternalKeyboardInNotification:(NSNotification *)notification, the following line of code returns YES even there is no external keyboard:

return (maxKeyboardHeight > CGRectGetHeight(self.view.bounds));

Due to floating point error, maxKeyboardHeight may be greater than the view's height even in the cases that they should be equal. The result of this error is that the text input bar is not shifted up after the keyboard is appeared. The user cannot see the text input bar.

I propose the following fix:
return (floor(maxKeyboardHeight) > CGRectGetHeight(self.view.bounds));

Tap gesture shouldn't cancel touches from being passed through

Right now the tap gesture is preventing collectionView:didSelectItemAtIndexPath from being called

The default value is YES

_singleTapGesture.cancelsTouchesInView = NO;

Also, should this gesture be exposed so that we can more easily customize the gesture (like disabling it, changing it to a double tap, etc)?

init triggers viewDidLoad before subclass init can run

The commonInit method touches the view, which triggers viewDidLoad to fire before a subclass can finish it's init. In our case we can't run the viewDidLoad logic without the values provided to the initializer, which we don't have because it fires prematurely.

All view manipulation logic should be in viewDidLoad, never in the init path.

Reuse Slack input bar

Hey,

I am trying to use the input bar only but it's hard to isolate this component from all the code.

Any clue ?

Thanks

shouldScrollToBottomAfterKeyboardShows doesnt work

As far as I can tell, the problem is in -[SLKTextViewController willShowOrHideKeyboard:]. It is calling scrollToBottomIfNeeded before it updates the keyboard status causing it to decide that it does not need to scroll to the bottom.

Issues with custom fonts

I've been playing around with this great controller and loving it so far but I've had some problems with getting it to behave while using a slightly smaller custom font. I'm not sure if this is an issue or just not supported.

After a couple of experiments with various fonts (both custom and system) I can get it to barely work by making some fairly unintuitive changes to [SLKTextView intrinsicContentSize], [SLKTextInputBar intrinsicContentSize] and textContainerInset. I'm guessing these are currently finely tuned to a system font size of 15? Most of the time a smaller custom font actually does the unexpected and makes the text view look bigger.

I've also observed #58 when the text view was slightly smaller than the text + container insets.

Are custom fonts supported or do we need to fork and do some bigger changes? Any tips on where the changes need to be made?

Examples lack Collection View example

The current set of example projects lack a collection view sample and the readme seems to have insufficient information on how to make this mode work.

View stuttering while interactively dismissing the keyboard

This is on an iPhone 6+ with 8.1

  1. Grab the sample messenger app
  2. Focus the input field
  3. Begin dragging the keyboard down & slightly up (enabling the interactive dismissal, and only going back & forth ~100px)

You'll notice that the view begins to stutter (sometimes, pretty badly) UNTIL it reaches the lower 3rd of the phone screen. It doesn't seem too bad in the messenger app. The app I'm building looks dramatically worse (collection view, custom layout, more of a complex controller).

  1. Extend your pan to the lower part of the screen. Completely smooth.

From observing this I see that the content/cells going behind the input field while dragging those first few x points. Once you reach a certain point the cells stop moving. For some reason that is making things go a little crazy.

Example from the app I'm working on: https://www.dropbox.com/s/skvtvgd6x7c0bt6/interactive-glitch.m4v?dl=0

Circular dependency with Cocoapods

Cocoapods throws an error describing:

[!] There is a circular dependency between SlackTextViewController/Additions and SlackTextViewController/Additions

I've tried removing all other pods to be sure it's happening in this repository alone and the error persisted. From the error message, I assume it's an issue concerning Cocoapods and I'll report it to them too, but I'd like to leave it registered here.

Cocoapods version: 0.35.0.rc1

Right button appears on the left side!!!

I just implemented everything as the docs and the examples, everything is fine except that the right button appears on the left side i don't know what's the problem.. i reviewed every line of my code and couldn't find anything.
Please advice..

Using SlackTextViewController as child controller causes external keyboard execution.

So, if you use this as a child controller and the text field is not at the bottom of the screen, it causes an issue. I did some debugging and it seems like it is getting flagged as a external keyboard. To recreate:

  1. Create a UIVIewController
  2. Add another UIViewController to the buttom
  3. On top of the UIIVewController, add the SlackTextViewController.

Result:

The text view will never slide up.

Keyboard does not appear in the simulator

Just FYI, the keyboard does not appear in the simulators (just blank white space). Xcode 6, tested iPhone and iPad on 7.1 and 8.0.

Tested iPad Air real device running 8.0 and the keyboard does appear.

TextView should not hide on "Pan Back" Gesture

Hey guys, love the control.

On iOS 7/8 when you do a "pan to go back" from the left side of the screen, the text input view slowly hides, because it gets a notification that the keyboard is going to hide. However, the TextView should not hide in such cases, á la iMessage.

I can do this myself by overriding:

- (void)willShowOrHideKeyboard:(NSNotification *)notification;
{
    if (self.isHiding) {
        return;
    }
    [super willShowOrHideKeyboard:notification];
}

And I set self.isHiding = YES in viewWillDisappear and self.isHiding = NO in viewDidAppear.

However, this requires making willShowOrHideKeyboard: public, which isn't good. Perhaps this could be implemented internally, or have a Flag somewhere that could be switched to stop it?

(Also, I think iOS 7 makes this harder because the View lifecycle events are fired in the wrong order).

Thanks!

input bar bugs

Sorry, it's me again.
Latest version 1.2.4

iPad 2 iOS 7.0.4
iPad 2 (simulator) iOS 7.1

The input bar start in the right position at the bottom on the view controller, when start editing it just jump at the very top. On the simulator things start going even more nuts with the whole controller going offscreen when switching the hardware keyboard on/off.
ios simulator screen shot 15 oct 2014 11 22 50

On iOS 8.0.2 appears to work fine on both simulator and device apart from one little glitch.

The inputbar has the predictive keyboard on. If you then set another textfield as first responder (which does not have a predictive keyboard) then the input bar doesn't slide down to cover that space.
ios simulator screen shot 15 oct 2014 11 38 38

I didn't have a look at the implementation so I may say something really stupid here, but won't be more reliable to add the input bar as accessory view of the input bar when the textview start editing and then when the keyboard disappear re add it to the view controller view?

You should not call self.view in the initialization method.

Thanks for sharing this library.

This is a common sense, You should put that code(commonInit) in viewDidLoad

- (instancetype)initWithBodySelfie:(EOTBodySelfie *)bodySelfie {
// 1
    self = [self initWithTableViewStyle:UITableViewStylePlain];
// 2
    if (!self) {
        return nil;
    }
    self.title = NSLocalizedString(@"BODYSELFIE", nil);
....

    return self;
}

- (void)viewDidLoad {
// 3
    [super viewDidLoad];
    [self setupTableView];
    [self setupNavigationBarButtonItems];
...
}

Normal should be 1, 2, 3.
However, it is 1, 3, 2.

UIRefreshControl at the top with inverted=YES?

Not a bug, just a question that I'm hoping you guys know the answer to? So I'm using SlackTextViewController, inverted set to YES. How can this be combined with a UIRefreshControl still at the top? Right now it's at the bottom, which makes sense since the table is inverted.

dequeueReusableCellWithIdentifier broken with Storyboard Prototypes and SLKVC

When I change my UITableViewController subclass to subclass SlackTextViewController my cells no longer load properly.

Previously I was using: MessageTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"MCell"];

It worked fine while the class subclassed UITableViewController.

After changing to use SLK, (and registering the class for the reuse) it does still return a cell, but it isn't loading properly. The outlets are all nil and even the non outlet views aren't showing up at all.

Did I miss a setup step somewhere? I had assumed it was basically drop in. I did include the
+ (UITableViewStyle)tableViewStyleForCoder:(NSCoder *)decoder
method.

How to get typed in message text

I'm trying to get the text typed into the text view when the 'Send' button is pressed.

When I access self.textView.text even when there is text typed into the field it returns an empty string.

Am I accessing the text correctly?

Storyboard support

I'd like to be able to assign the tableview as an IBOutlet from a storyboard, so I can also use prototype cells for example.

A bigger problem however is that I'm not calling any of the init methods when the controller is instantiated from the storyboard, so it would be handy to be able to call tableViewWithStyle: and commonInit from within my initWithCoder: method. Or that SlackTextViewController would implement the initWithCoder: method?

App crashes due to scrollViewProxy set to nil. Release 1.3.3

I am subclassing SlkTextViewController correctly. But I keep on getting crash where the app crashes in SLKViewController viewdidLoad => setupViewConstraints as the scrollViewProxy is nil. I can see that its getting set to _tableView correctly in init, but then when loadView gets called its back to nil and then ends up crashing the app. Not sure why its happening. Attached is crash log.

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[**NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]'
* First throw call stack:
(
0 CoreFoundation 0x01b71946 __exceptionPreprocess + 182
1 libobjc.A.dylib 0x017faa97 objc_exception_throw + 44
2 CoreFoundation 0x01a69af3 -[__NSPlaceholderDictionary initWithObjects:forKeys:count:] + 451
3 CoreFoundation 0x01a7dc5b +[NSDictionary dictionaryWithObjects:forKeys:count:] + 75
4 PepperKitExample 0x001a6836 -[SLKTextViewController setupViewConstraints] + 294
5 PepperKitExample 0x00199308 -[SLKTextViewController viewDidLoad] + 88
6 PepperKitExample 0x001c4f35 -[PKChatSessionViewController viewDidLoad] + 69
7 UIKit 0x0207c2a4 -[UIViewController loadViewIfRequired] + 771
8 UIKit 0x0207c595 -[UIViewController view] + 35
9 UIKit 0x020bd534 -[UINavigationController preferredContentSize] + 161
10 UIKit 0x0205744d -[UIPresentationController preferredContentSizeDidChangeForChildContentContainer:] + 122
11 UIKit 0x02054922 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke + 156
12 UIKit 0x020887ab __40+[UIViewController _scheduleTransition:]_block_invoke + 18
13 UIKit 0x01f4e0ce ___afterCACommitHandler_block_invoke + 15
14 UIKit 0x01f4e079 _applyBlockToCFArrayCopiedToStack + 415
15 UIKit 0x01f4de8e _afterCACommitHandler + 545
16 CoreFoundation 0x01a949de __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION
+ 30
17 CoreFoundation 0x01a94920 __CFRunLoopDoObservers + 400
18 CoreFoundation 0x01a8a35a __CFRunLoopRun + 1226
19 CoreFoundation 0x01a89bcb CFRunLoopRunSpecific + 443
20 CoreFoundation 0x01a899fb CFRunLoopRunInMode + 123
21 GraphicsServices 0x0591924f GSEventRunModal + 192
22 GraphicsServices 0x0591908c GSEventRun + 104
23 UIKit 0x01f248b6 UIApplicationMain + 1526
24 PepperKitExample 0x000bae9d main + 141
25 libdyld.dylib 0x03309ac9 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Display bugs

Not sure in which release this started to happen, somewhere in the last week I think. Probably after the changes to add storyboard support.

screen shot 2014-10-16 at 11 34 38

Weird grey bar at the bottom. Also, the "typing" messages don't show up anymore, I guess it's hidden by that bar somehow?

Placeholder text off center vertically (slightly)

Hi.

I noticed that when you first bring up a screen with the placeholder label in use, the placeholder is off vertically by a couple of pts. I'm using a 17pt font on the textview and label. Before I type anything in the textview, the frame of the label is set to x: 0.000000, y: 0.000000, h: 34.000000, w: 359.000000. After I type something in the textview and clear it, the frame of the label becomes x: 0.000000, y: 2.500000, h: 34.000000, w: 359.000000.

I know this is minor, but is there any way we could get a fix for the initial frame of the placeholder label? Before it adjusts itself, it's off center vertically by just a bit, but it's noticeable.

Thanks for the great code!

placeholder drawing doesn't take into account text container inset

the implementation in SAMTextView (https://github.com/soffes/SAMTextView) does and it is a simple drop in:

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];

    // Draw placeholder if necessary
    if (self.text.length == 0 && self.attributedPlaceholder) {
        CGRect placeholderRect = [self placeholderRectForBounds:self.bounds];
        [self.attributedPlaceholder drawInRect:placeholderRect];
    }
}


#pragma mark - Placeholder

- (CGRect)placeholderRectForBounds:(CGRect)bounds {
    CGRect rect = UIEdgeInsetsInsetRect(bounds, self.contentInset);

    if ([self respondsToSelector:@selector(textContainer)]) {
        rect = UIEdgeInsetsInsetRect(rect, self.textContainerInset);
        CGFloat padding = self.textContainer.lineFragmentPadding;
        rect.origin.x += padding;
        rect.size.width -= padding * 2.0f;
    } else {
        if (self.contentInset.left == 0.0f) {
            rect.origin.x += 8.0f;
        }
        rect.origin.y += 8.0f;
    }

    return rect;
}

EXC_BAD_INSTRUCTION

Hi guys,
great library!
I've a problem when the dealloc is called.

I use SlackTextViewController in a PageController. It is not the first controller i show (it is the third), so only the init method is called and it's live in the viewcontrollers array of the PageController.

When i push the PageController in my navigation stack and press back, the dealloc is called and cause a crash on SLKTextViewController *controller property of SLKTextInputbar.

screen shot 2014-11-26 at 17 54 54

I don't know if it could be the problem, but it crash when, in the dealloc, the controller calls cacheTextToDisk: with self.textView.text as parameter. self.textView returns self.textInputbar.textView and self.textInputbar doesn't exist yet, because the loadView is not already called.

Thanks guys!

Interactive dismiss mode not working on iOS7

I ran into your code because I was trying to solve the same problem. Unfortunately interactive dismiss mode doesn't work on iOS7. The problem is you're relying on inputAccessoryView's superview to change its frame as the keyboard is animating, but that doesn't happen on iOS7.

On iOS7, your superview doesn't move (and neither do any of its subviews). What happens is the superview gets added to a separate window, and then its layer is animated (I can see that if I try monitoring its frame, because I get the notification once and then it contains a CASpringAnimation on position).

That makes things difficult because you can't directly track the layer's position while it's animating.

I tried using CADisplayLink but I can't synchronise it properly so the input view is always lagging behind the keyboard as it moves.

Some problems when type Chinese

When type a set of Chinese and select Chinese form predictive typing , the textView does not scroll to bottom finally.

like this :
2014-12-10 17 05 07

iOS 7 Swipe back gesture not work

Found a bug, iOS 7 Swipe back gesture not work, I tested on iOS 8, not work either.
step:
parentViewController --> push to SlackTextViewController sub viewController, swipe back to parentViewController not work.

not works properly with UITabBarController

SlackTextViewController is awesome!
I try to use it in my project like this:

UITabBarController *tab = [[UITabBarController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[MessageViewController new]];
[tab setViewControllers:@[nav]];
self.window.rootViewController = tab;

The problem is the input bar not scroll with the keyboard.

Another problem is when i push the MessageViewController with hidesBottomBarWhenPushed = YES, the input bar can not begin edit.

Pod issue

Guys, in cocoa pods latest version is 1.3.3, How i can get latest version of this cool library with latest changes? And dont copy files to project directly

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.