UITextView scrollEnabled = YES not working after set scrollEnabled = NO in iOS8 - ios

I create a demo for checking UITextView scrollEnabled.
It only contains 1 UITextView and 2 button enable and disable scroll
I test on simulator and device iOS 8, if I click the disable scroll button, the UITextView will disable scroll correctly, but after that I
click on enable scroll, the UITextView won't enable scroll
However, I test on device iOS9, the enable and disable scroll work well.
#import "ViewController.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UITextView *myTextView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)enableScrollButtonPressed:(id)sender{
self.myTextView.scrollEnabled = YES;
}
- (IBAction)disableScrollButtonPressed:(id)sender{
self.myTextView.scrollEnabled = NO;
}
#end
Any idea to fix this problem? If someone don't understand my explain please check
my demo project
Any help or suggestion would be great appreciated

The problem is that in iOS 8, contentSize is not adjusted correctly when scrollEnabled is changed. A small adjustment to your enableScrollButtonPressed method will successfully work around the problem.
-(IBAction)enableScrollButtonPressed:(id)sender
{
self.myTextView.scrollEnabled = YES;
self.myTextView.contentSize = [self.myTextView sizeThatFits:self.myTextView.frame.size];
}

Yeah you are right disabling and enabling scroll of textview is not working in iOS8 it may be a bug or anything else, let it be.
We can disable or enable scroll of text view by just changing the ContentSize of textview .
#import "ViewController.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UITextView *myTextView;
#end
#implementation ViewController
-(IBAction)enableScrollButtonPressed:(id)sender{
CGSize scrollableSize = CGSizeMake(self.myTextView.bounds.size.width+20, self.myTextView.bounds.size.height+20);
[self.myTextView setContentSize:scrollableSize];
}
-(IBAction)disableScrollButtonPressed:(id)sender{
[self.myTextView setContentOffset:CGPointMake(0, 0)];
[self performSelector:#selector(StopScroll) withObject:nil afterDelay:0.1];
}
-(void)StopScroll{
CGSize scrollableSize = CGSizeMake(self.myTextView.bounds.size.width, self.myTextView.bounds.size.height/2);
[self.myTextView setContentSize:scrollableSize];
}
#end
I had tested the above code it is working fine for me i'am using xcode 7.2.1 and iOS 8.3. Give it a try and let me know the result

After searching hours i am found one way
-(IBAction)enableScrollButtonPressed:(id)sender{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.myTextView.scrollEnabled = YES;
[self.myTextView setText:self.myTextView.text];
self.myTextView.layoutManager.allowsNonContiguousLayout = false;
});
}
-(IBAction)disableScrollButtonPressed:(id)sender{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.myTextView.scrollEnabled = NO;
});
}
condition for that is you need to scroll first then you it will work perfectly
Means when disable scroll button is tapped textview should be scrolled at some position must not to at default position

Please follow below steps simply
self.myTextView.scrollEnabled = NO;
self.myTextView.userInteractionEnabled = YES;
self.myTextView.scrollEnabled = YES;

you need to layout your views after enabling or disabling scroll view in your view.
use viewWillLayoutSubviews/layoutIfNeeded methods.

change your property as follows.
in your code..
#property (weak, nonatomic) IBOutlet UITextView *myTextView;
change property attribute as follows:
#property (strong, nonatomic) IBOutlet UITextView *myTextView;
then it'll work fine. i checked it.

I tried my code and it worked properly
IBOutlet UITextView *tv;
//---------Enable button action.
-(IBAction)enable:(id)sender
{
tv.scrollEnabled=YES;
}
//---------Disable button action.
-(IBAction)disable:(id)sender
{
tv.scrollEnabled=NO;
}
try your code once more in device.

Try this one
func scrollViewDidScroll(_ scrollView: UIScrollView) {
tableView.setContentOffset(CGPoint.zero, animated: false)
}

Related

How can I change constraint of height with button?

I want to change my calendar height's constraint 124 to zero when calendar button is clicked how can I do that? I want to use button statement but I couldn't at objective c. Thanks.
#property (weak, nonatomic) IBOutlet UIBarButtonItem *calendarButton;
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *heightOfCalendar;`
- (IBAction)calendarAction:(id)sender {
}
you need to set constant property
heightOfCalendar.constant = requiredheight
You can Do like this to change size on each tap
- (IBAction)calendarAction:(id)sender {
sender.selected = !sender.selected;
heightOfCalendar.constant = (sender.selected)?0:124;
}
Doing it with an animation will looks good
(IBAction)calendarAction:(id)sender {
[UIView animateWithDuration:0.5
animations:^{
heightOfCalendar.constant =0;
[self.view layoutIfNeeded];
}];
}
Write this code in your IBAction:
- (IBAction)calendarAction:(id)sender {
self.heightOfCalendar.constant = 0;
}
Also make sure you have your IBAction connection set properly.
And I see a ` symbol at the end of the following statement:
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *heightOfCalendar;`

How to get viewForZoomingInScrollView to work across multiple UIViewControllers in Xcode?

I'm relatively new to Xcode, and am in the process of making an app in Objective C with several viewControllers each with a single UIScrollView containing a single UIImage that can be zoomed and scrolled.
This code works for the first image (dermatomes), but I can't figure out how to tweak the UIView to enable zooming and scrolling on the second image (anatomicPlanes). Currently the second image imports correctly to the second UIScrollView, but when I try to zoom it just jumps down and right and remains static there.
The size of the UIScrollViews were set using Interface Builder, no problems there.
viewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIScrollViewDelegate> {
IBOutlet UIScrollView *dermatomeScrollView;
UIImageView *dermatomesImageView;
IBOutlet UIScrollView *anatomicPlaneScrollView;
UIImageView *anatomicPlanesImageView;
}
#property (strong, nonatomic) IBOutlet UIScrollView *dermatomeScrollView;
#property (strong, nonatomic) IBOutlet UIImageView *dermatomesImageView;
#property (strong, nonatomic) IBOutlet UIImageView *anatomicPlanesImageView;
#property (strong, nonatomic) IBOutlet UIScrollView *anatomicPlaneScrollView;
#end
viewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize dermatomeScrollView, anatomicPlanesImageView, dermatomesImageView, anatomicPlaneScrollView;
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return dermatomesImageView;
}
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *dermatomes = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"dermatomes.jpg"]];
self.dermatomesImageView = dermatomes;
dermatomeScrollView. maximumZoomScale = 1.2;
dermatomeScrollView. minimumZoomScale = 0.4;
dermatomeScrollView. delegate = self;
[dermatomeScrollView addSubview:dermatomesImageView];
dermatomeScrollView.zoomScale = 0.6;
UIImageView *planes = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"anatomic planes.jpg"]];
self.anatomicPlanesImageView = planes;
anatomicPlaneScrollView. maximumZoomScale = 1.2;
anatomicPlaneScrollView. minimumZoomScale = 0.4;
anatomicPlaneScrollView. delegate = self;
[anatomicPlaneScrollView addSubview:anatomicPlanesImageView];
anatomicPlaneScrollView.zoomScale = 0.6;
}
Any help is appreciated!
You need to return the correct view based on the scroll view that is requesting. Every method in the delegate pattern is passed a reference to the originator of the method call, so your delegate implementation can handle it differently. In this case, the originator of the delegate method call is the scroll view:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
if (scrollView == dermatomeScrollView) {
return dermatomesImageView;
}
return anatomicPlanesImageView;
}
If you add more scrollviews, you'll have to extend this method further.

UIDatePicker repositioning to the bottom of the view

I'm building a to-do app where user can select the reminder option. If reminder is enabled, then a UIDatePicker would be enabled. I created the main UI with storyboard. So my initial UI is like this
But after disabling and enabling again the reminder switch, the Datepicker placed on top of the view. I need to position it to the bottom of the view.
My ViewController code is like this
- (IBAction)isReminderSelected:(UISwitch *)sender {
if([_reminderSetField isOn]){
[_reminderSetField.viewForBaselineLayout addSubview: _reminderDatePicker];
}
else {
[_reminderDatePicker removeFromSuperview];}
}
I created the main UI via storyboard. Then initialize the datepicker in the header file....
My *.h file
#property (strong, nonatomic) IBOutlet UISwitch *reminderSetField;
#property (strong, nonatomic) IBOutlet UIDatePicker *reminderDatePicker;
- (IBAction)isReminderSelected:(UISwitch *)sender;
You should set y position of the picker view like
float y = [UIScreen mainScreen].bounds.size.height - _reminderDatePicker.frame.size.height;
[_reminderDatePicker setFrame:CGRectMake(0, y, _reminderDatePicker.frame.size.width, _reminderDatePicker.frame.size.height)];
i think you should try like this
- (IBAction)isReminderSelected:(UISwitch *)sender {
if([_reminderSetField isOn]){
float y = [UIScreen mainScreen].bounds.size.height - _reminderDatePicker.frame.size.height;
[_reminderDatePicker setFrame:CGRectMake(0, y, _reminderDatePicker.frame.size.width, _reminderDatePicker.frame.size.height)];
[yourView addSubView:_reminderDatePicker];
}
else {
[_reminderDatePicker removeFromSuperview];}
}

UIScrollVIew only showing first static subview, delegate of UIPageControl

I am a newbie of IOS development, my problem is I am using UIScrollView and UIPageControl to show guide info to users. I created a xib file related to GuideViewController via setting up File's Owner. I setup the content size and statically add subviews in xib files. But I encountered some strange thing, scrollview only shows the first subview on screen, all following display is just white background (when I scrolling).
Following is the code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSInteger numberOfPages = 2;
self.pageControl.numberOfPages = numberOfPages;
self.pageControl.currentPage = 0;
self.pageScroll.delegate = self;
self.pageScroll.contentSize = CGSizeMake(self.view.frame.size.width * numberOfPages,
self.view.frame.size.height);
self.pageControl.currentPageIndicatorTintColor = [UIColor redColor];
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat pageWidth = self.view.frame.size.width;
int page = floor((scrollView.contentOffset.x - pageWidth/2) / pageWidth) + 1;
self.pageControl.currentPage = page;
}
I googled a lot to find the answer but still stuck here.
I am also confused by this sentence "When a user taps a page control to move to the next or previous page, the control sends the UIControlEventValueChanged event for handling by the delegate" in xcode help. It seems UIPageControl has no delegate attribute,so how I can capture the UIControlEventValueChanged event.
Actually I am developing my main UI on storyboard, but I kind of want separate UI design to make more space for storyboard, so i use xib file for some other part UI, I do not know whether this will cause some problems. Thanks
My solution was this:
Add a IBAction in your header:
- (IBAction)changePage;
Dont forget to set the Outlet and the property for the pageControl:
IBOutlet UIPageControl *pageControl;
#property (nonatomic, retain) IBOutlet UIPageControl* pageControl;
Add a BOOLEAN that the pagecontrol updates:
BOOL pageControlBeingUsed;
Here is my full header:
#interface ViewC : UIViewController <UIScrollViewDelegate> {
IBOutlet UIScrollView *scrollView;
IBOutlet UIPageControl *pageControl;
BOOL pageControlBeingUsed;
}
#property (nonatomic, retain) IBOutlet UIScrollView* scrollView;
#property (nonatomic, retain) IBOutlet UIPageControl* pageControl;
- (IBAction)changePage;
#end
(Don't forget to synthesize the propertys)
The second step you did already with the viewdidLoad method but you didn't connected the Boolean to the method! Try this:
- (void)scrollViewDidScroll:(UIScrollView *)sender {
if (!pageControlBeingUsed) {
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.scrollView.frame.size.width;
int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl.currentPage = page;
}
}
Add at the end this code for the IBAction and that when the pageControl was pressed at a button the site changes.
- (IBAction)changePage {
// update the scroll view to the appropriate page
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * self.pageControl.currentPage;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
[self.scrollView scrollRectToVisible:frame animated:YES];
pageControlBeingUsed = YES;
}
IMPORTANT:
Connect the IBAction with "value changed" option in the xib. and set the delegate of the Controller to itself:
And then it should be like this:
That is all! Hope you fixed your issue. I would be glad if you give my awnser the "tick" if it helped you!
Greetings,
Noah

A few IBOutlets pointing to nil

After a long while I've finally started working with Objective-C again, on my only complete app so far. The goal is to eventually refactor for ARC and possibly storyboards, but for the time being I'm polishing the iOS 4.x target. I am quite rusty, so bar with me if this is a stupid question.
I have a button in my main view that triggers the showAction method. The method is as follows:
- (void)showAbout
{
AboutViewController *aboutView = [[[AboutViewController alloc] init] autorelease];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
aboutView.modalPresentationStyle = UIModalPresentationFormSheet;
}
else
{
aboutView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
}
[self presentModalViewController:aboutView animated:YES];
}
The AboutViewController class has this .h:
#interface AboutViewController : UIViewController <UIActionSheetDelegate, MFMailComposeViewControllerDelegate> {
}
- (IBAction)dismiss:(UIButton *)sender;
- (IBAction)feedback:(UIButton *)sender;
#property (retain) IBOutlet UIButton *dismissButton;
#property (retain) IBOutlet UIButton *feedbackButton;
#property (retain) IBOutlet UIImageView *background;
#property (retain) IBOutlet UITextView *textView;
#end
and everything has been connected properly in the .xib file (the same one for iPhone and iPad). The actions are triggered as expected, and the outlets are accessible, but only on iPhone. When running on iPad, only textView is properly initialized, and all the rest points to nil.
In the .m I have tried this:
#implementation AboutViewController
#synthesize dismissButton = _dismissButton;
#synthesize feedbackButton = _feedbackButton;
#synthesize background = _background;
#synthesize textView = _textView;
// ...
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(#"obj self.dismiss: %#", self.dismissButton);
NSLog(#"frame dismiss: %#", NSStringFromCGRect(self.dismissButton.frame));
}
On iPhone I get this:
2012-02-08 22:51:00.341 myapp[17290:207] obj self.dismiss: <UIButton: 0x70281d0; frame = (180 410; 120 30); opaque = NO; autoresize = LM+W+RM+TM; layer = <CALayer: 0x7028260>>
2012-02-08 22:51:00.342 myapp[17290:207] frame dismiss: {{180, 410}, {120, 30}}
On iPad, instead, I get this:
2012-02-08 22:51:40.428 myapp[17320:207] obj self.dismiss: (null)
2012-02-08 22:51:40.428 myapp[17320:207] frame dismiss: {{0, 0}, {0, 0}}
There is nothing else that happens depending on the UI Idiom, and I'm really confused about this. It's as if on the iPad the outlets for anything other than textView are not set, even though they are correctly linked up in the .xib file. In viewWillAppear, self.textView is working as expected also on iPad. I also tried doing this in viewDidLoad, which should be called before viewWillAppear if I'm not mistaken, and even in the dismiss: method, but they are just never available.
The reason I need to access the buttons' frames is that the about view is relatively complex and fails to reposition its subviews automatically. The only thing I need to do is make the buttons wider on the larger modal view on iPad.
Any hints would be greatly appreciated!
Thanks in advance.
Did you ever have a separate .xibs for iPad and iPhone? If so you might have the same issue I had. That is until #AliSoftware dropped some knowledge on me:
UIView in nib is nil on iPad, and not nil on iPhone
Essentially you need to:
Delete the Build Products Directory
Delete your app from all your simulators
Build and Run
I believe the problem is that a ghost .xib for iPad was hanging around causing issues. Truly wiping the apps clean did the trick. Good luck!

Resources