xcode ios NSRangeException on creating subviews - ios8

how do I change the code below to fix the pickerView being depreciated?
This code has worked well before and did the job. I havent needed to compile for a while and when I was fixing another problem I bumped into this NSRangeException when it hits the subview. The code used to work with a previous version of IOS. Any thoughts would be appreciated.
Terminating app due to uncaught exception 'NSRangeException', reason:
'-[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
First throw call stack:... etc etc
After more reading I find that the pickerView is depreciated.
Never will understand why Apple can just change code!
-(void)willPresentActionSheet:(UIActionSheet *)actionSheet {
switch ([actionSheet tag] ) {
case 1://date
{
NSDate *d;
UIDatePicker *pickerView = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 50, 100, 116)];
[pickerView setTag:100+[actionSheet tag]];
[pickerView setDatePickerMode:UIDatePickerModeDate];
if( DefDate == #"" || DefDate == Nil ) DefDate = [fun0 GetCurrentDate];
d = [fun0 GetDatefromString:DefDate];
[pickerView setDate:d animated:YES];
[actionSheet addSubview:pickerView];
[pickerView release];
NSArray *subViews = [actionSheet subviews];
**// Line below is where is where it dumps:**
[[subViews objectAtIndex: SelectButtonIndex] setFrame:CGRectMake(20, 266, 280, 46)];
[[subViews objectAtIndex:CancelButtonIndex] setFrame:CGRectMake(20, 317, 280, 46)];
}
break;
}
}
- (IBAction)btnDate:(id)sender {
UIActionSheet *asheet = [[UIActionSheet alloc]
initWithTitle:#"Pick the date of your meal"
delegate:self
cancelButtonTitle:#""
destructiveButtonTitle:nil
otherButtonTitles:#"Select"
, nil];
[asheet setTag:1];
[asheet showInView:[self.view superview]];
[asheet setFrame:CGRectMake(0, 117, 320, 383)];
[asheet release];
}

I've tested it with iOS 8.0 (and running on XCode6.1) and above, and your code and UIActionSheet both looks nice.
It can compile, run and showing me the output.
Here's what I get.
Update:
From iOS 8.0 and above, UIActionSheet is depreciated. Also its stop supporting add subviews too. This means device with iOS 8.0 and above will not show you UIDatePicker as subview of it. If notice, nightmare is not the error line you've specified below the comment but its not showing data picker any more inside action sheet.
From Documentation,
UIActionSheet is not designed to be subclassed, nor should you add
views to its hierarchy. If you need to present a sheet with more
customization than provided by the UIActionSheet API, you can create
your own and present it modally with
presentViewController:animated:completion:.
IMHO,
You should upgrade your app and code to start supporting from iOS 8.0 only. UIActionSheet will be replace by UIAlertController. [Suggested]
If you wish to support back iOS 8 then you've to use a third party action sheet which you can use in place of UIActionSheet in all iOS versions. Here's the one, https://github.com/skywinder/ActionSheetPicker-3.0 [Good Alternative]
If you don't want to use third party and still wants to support all iOS versions, then you can runtime check for iOS versions and based on that you can either show UIActionSheet and UIAlertController. [Not Recommended]
Few links which may help you.
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIAlertController_class/
http://nshipster.com/uialertcontroller/
Add UIPickerView in UIActionSheet from IOS 8 not working
Showing a UIPickerView with UIActionSheet in iOS8 not working

Action Sheet Picker worked great as I was able to chat directly with the developer to get going. I guess It took me a little while to get going understanding it as I dont program in IOS every day, but once I did its awesome! Thank you to Hemang above for all the suggestions!
ACTION SHEET PICKER

Related

iOS 13 - UIPopoverPresentationController sourceview content visible in the arrow

When I am displaying some view in UIPopoverPresentationController and presenting it as popover
popoverCon?.modalPresentationStyle = UIModalPresentationStyle.popover
the content have moved upward toward and a some part is being display in the arrow.
Further I had border around the popover
popoverCon?.view.layer.borderColor = .orange
popoverCon?.view.layer.borderWidth = 1.0;
popoverCon?.view.layer.cornerRadius = 10.0;
popoverCon?.view.layer.masksToBounds = false;
it is not showing toward the part where arrow is but it displays a little of the border line in the tip of the arrow.
This was working fine until iOS 12 but in iOS 13 this issue is coming.
Any suggestions on how I can solve this?
The top of my tableView content was cut off by the arrow. This is how I fixed it in my case (code inserted in my tableViewController Swift file):
override func viewSafeAreaInsetsDidChange() {
if #available(iOS 11.0, *) {
super.viewSafeAreaInsetsDidChange()
self.tableView.contentInset = UIEdgeInsets(top: self.tableView.safeAreaInsets.top, left: 0, bottom: 0, right: 0)
}
}
My solution in Obj-C, for those who need an obj-c solution.
I had previously only popovercontroller, that was creating the error like shown in the question. I renamed it to childController for clarity and created a containing popoverController to make the solution given by #SaintMSent work in my situation of only one view originally. Also used https://stackoverflow.com/a/47076040/2148757 solution and https://useyourloaf.com/blog/self-sizing-child-views/ to resize appropriately since all of my childControllers set the preferred content size frequently.
//Create container popover controller and add child to it
UIViewController* popoverController = [[MyParentPopoverController alloc] init];
[popoverController.view addSubview:childController.view];
[popoverController addChildViewController:childController];
[popoverController setPreferredContentSize:childController.preferredContentSize];
//set popover settings on container
popoverController.modalPresentationStyle = UIModalPresentationPopover;
popoverController.popoverPresentationController.sourceRect = sourceRect;
popoverController.popoverPresentationController.sourceView = buttonView;
popoverController.popoverPresentationController.permittedArrowDirections = direction;
//Fix ios13 'bug' that Apple claims is a feature
UILayoutGuide* guide = popoverController.view.safeAreaLayoutGuide;
childController.view.translatesAutoresizingMaskIntoConstraints = NO;
[childController.view.leadingAnchor constraintEqualToAnchor:guide.leadingAnchor].active = YES;
[childController.view.trailingAnchor constraintEqualToAnchor:guide.trailingAnchor].active = YES;
[childController.view.topAnchor constraintEqualToAnchor:guide.topAnchor].active = YES;
[childController.view.bottomAnchor constraintEqualToAnchor:guide.bottomAnchor].active = YES;
[popoverController.view layoutIfNeeded];
//Show the popover
...
#interface MyParentPopoverController : UIViewController
#end
#implementation MyParentPopoverController
-(void)preferredContentSizeDidChangeForChildContentContainer:(id <UIContentContainer>)container {
[super preferredContentSizeDidChangeForChildContentContainer:container];
[self setPreferredContentSize:container.preferredContentSize];
}
#end
Note: I didn't check for ios11 compatibility because my user base is restricted to not use it.
It is definitely a feature, they want you to use safe area since iOS 11, actually, but it seems now they want to force you to use it
Had the same problem as you, this worked for me
https://useyourloaf.com/blog/safe-area-layout-guide/
Definitely a bug. When you have a situation where you use UIPopoverArrowDirectionAny you will see that the problem only exists when the arrow is at the top or left of the popover and not when the arrow appears at the right or the bottom of the popover. If you make adjustments in your code to compensate it will work if you use UIPopoverArrowDirectionUp or UIPopoverArrowDirectionLeft but will not display correctly using that adjustment when using UIPopoverArrowDirectionAny and the popup appears above or to the right of the target rectangle.
I don't have an 'answer' yet, but I have identified what's going on and why it's so hard to fix.
ios13 UIPopoverViewController showing UITableViewController - Safe Area problems / Missing parts of table
Basically, any UITableView that has headers or footers is going to be broken in iOS 13 unless there's some way to alter the _UITableViewHeaderFooterViewBackground
That is notoriously problematic and doesn't play nicely with Auto-Layout - it's been known about for years, but Apple have never fixed it or made it easier to deal with and more publicly known.
https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=video&cd=1&cad=rja&uact=8&ved=0ahUKEwibouuozfvkAhVCXRUIHVGsBegQtwIIKjAA&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DajsCY8SjJ1Y&usg=AOvVaw3_U_jy9EWH2dJrM8p-XhDQ
https://spin.atomicobject.com/2016/10/12/auto-layout-uitableview/
I'm unable to push my app to the App Store until I get this sorted.. I hope someone can identify how to manipulate this view so that it stops pushing the boundaries of the table out of whack with AutoLayout which causes this safe area intrusion.
Searching on the internet I got help from following link
Twitter
so I had to add safe area and manage my views accordingly
CGFloat topPadding = 0.0;
if (#available(iOS 11.0, *)) {
topPadding = self.view.safeAreaLayoutGuide.layoutFrame.origin.y;
}
Swift:
var topPadding: CGFloat = 0.0
if #available(iOS 11.0, *) {
topPadding = self.view.safeAreaLayoutGuide.layoutFrame.origin.y
}
but I haven't got solution to the border problem of mine yet.
Edit:
Temporarily I did solved the border problem by creating an invisible view on popover and giving it same frame as safe area and drawing its border.
You should use constraints. And also pay attention to topAnchor. It must be safeAreaLayoutGuide.topAnchor. In my case, it works correctly. For example:
[NSLayoutConstraint activateConstraints:#[
[toolbar.leftAnchor constraintEqualToAnchor:self.view.leftAnchor],
[toolbar.rightAnchor constraintEqualToAnchor:self.view.rightAnchor],
[toolbar.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[toolbar.heightAnchor constraintEqualToConstant:50]
]];
Embed the contents of the popover in another view with "safe area relative margins" on. This should have -21,-21 as the origin. Turn off vertical and horizontal auto resizing. Seems to work, although you lose auto-stretching.
Setup your popover's content UIViewController like such:
NSLayoutConstraint.activate([
myContentView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
myContentView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
myContentView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
myContentView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor)
])

UICollectionView iOS8 Wrong Offset

Surprisingly, after updating to iOS8 my app does not behave as in iOS7.
In particular, I made a calendar with UICollectionView. In iOS7 fine, the month cells were displayed correctly. But in iOS8...
I see an offset toward the top, that's the cells are shifted upward...I do not understand, really.... The code is very simple.
- (void)viewDidLoad
{
[super viewDidLoad];
UINib * nib = [UINib nibWithNibName:#"AgendaYearCollectionCell" bundle:[NSBundle mainBundle]];
[self.collectionView registerNib:nib forCellWithReuseIdentifier:agendaYearCellIdentifier];
[self.collectionView setDelegate:self];
[self.collectionView setDataSource:self];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.minimumInteritemSpacing = 0;
layout.minimumLineSpacing = 1;
[self.collectionView setCollectionViewLayout:layout];
}
The collection was not scrollable. If I make it scrollable, I can scroll and see the cells of the first row. But I do not want a scrollable collection.
I think the problem is in the inset. In fact, if I play with:
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(40, 2, 50, 60);
}
I can eventually get the first row again. But how to calculate the value for all the screen/devices? My app is landscape only and only for iPad.
What Apple changed?
Your Collection View has negative top offset. Providing more code could help, however let's try this first.
You called:
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
insetForSectionAtIndex:(NSInteger)section
I would not call this unless you want different insets for different sections. It looks like you have only one section. I would configure it with Flow Layout:
flowLayout.sectionInset = CGSizeMake(40.0, 2.0, 50.0, 60.0);
I recommend to drop iOS 7 support, all devices with iOS 7 can be upgraded to 8.
how to calculate the value for all the screen/devices?
Should be the same offset for any iPad. Even if Apple will ship iPad with bigger screen, your offset will be the same. If you want Universal app with support for iPhone you could put device condition check and assign different numbers depending on the device paradigm.
Also, it could be something on the top. Did you messed with Navigation Bar? It doesn't clear from the picture.

UITextView setText should not jump to top in ios8

Following iOS 8 code is called every second:
- (void)appendString(NSString *)newString toTextView:(UITextView *)textView {
textView.scrollEnabled = NO;
textView.text = [NSString stringWithFormat:#"%#%#%#", textView.text, newString, #"\n"];
textView.scrollEnabled = YES;
[textView scrollRangeToVisible:NSMakeRange(textView.text.length, 0)];
}
The goal is to have the same scrolling down behaviour as the XCode console when the text starts running off the bottom. Unfortunately, setText causes the view to reset to the top before I can scroll down again with scrollRangeToVisible.
This was solved in iOS7 with the above code and it worked, but after upgrading last week to iOS8, that solution no longer seems to work anymore.
I can't figure out how to get this going fluently without the jumping behaviour?
I meet this problem too. You can try this.
textView.layoutManager.allowsNonContiguousLayout = NO;
refrence:http://hayatomo.com/2014/09/26/1307
The following two solutions don't work for me on iOS 8.0.
textView.scrollEnabled = NO;
[textView.setText: text];
textView.scrollEnabled = YES;
and
CGPoint offset = textView.contentOffset;
[textView.setText: text];
[textView setContentOffset:offset];
I setup a delegate to the textview to monitor the scroll event, and noticed that after my operation to restore the offset, the offset is reset to 0 again. So I instead use the main operation queue to make sure my restore operation happens after the "reset to 0" option.
Here's my solution that works for iOS 8.0.
CGPoint offset = self.textView.contentOffset;
self.textView.attributedText = replace;
[[NSOperationQueue mainQueue] addOperationWithBlock: ^{
[self.textView setContentOffset: offset];
}];
Try just to add text to UITextView (without scrollRangeToVisible/scrollEnabled). It seams that hack with scroll enabled/disabled is no more needed in iOS8 SDK. UITextView scrolls automatically.

UITextField - message sent to deallocated instance "UIKBStringWideAttributeValueForKey:"

After enabling Zombie Objects I am able to see the following error when I try to edit a UITextField (textLvl):
2013-01-13 13:27:10.509 testob[18418:907] *** -[NSConcreteMutableAttributedString
_UIKBStringWideAttributeValueForKey:]: message sent to deallocated instance 0x2066a1f0
I have posted the portion of code that is causing the issue below, it seems to specifically be the "textField.text = self.storeText;" part - as when I comment this out the problem goes away.
You may be able to tell I am not the most experienced iOS dev, why would my UITextView deallocate after I've set the text? Help please!
Also, I've never heard of "_UIKBStringWideAttributeValueForKey" before - any ideas?
Thanks all!
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
NSLog(#"Text began editing");
self.storeText = textField.text;
textField.text = #"";
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
if (textField == textLvl){
if ([textField.text isEqualToString:#""]){
textField.text = self.storeText;
NSLog(#"No Text");
}
self.conv = [textField.text intValue];
if (self.conv >= 101){
textField.text = #"100";
UIAlertView *successAlert = [[UIAlertView alloc] initWithTitle:#"Oh no!" message:#"Can't be higher than 100." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[successAlert show]; }
}}
This might be a bug internal to the framework. I suggest you add - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField and set the textfield text to nil and then reset the textfield text.
I think the real answer here is that you're dealing with a UITextField that has been set to handle NSAttributedString rather than NSString. You'll notice if you're dealing with UITextField defined in a .xib, it's top property option is now "Text" with options Plain or Attributed.
If your text field was switched to attributed, you'll find this error happening if you continue to deal with the text field as if it were Plain.
My textfield was in a xib file and it's delegate was hooked up to the files owner. This was causing the crash for me, because the file's owner was NSObject.
I actually wanted to hook up the delegate to the cell, and not files owner.
Use instruments so see the retains/releases:
If you need to see where retains, releases and autoreleases occur for an object use instruments:
Run in instruments, in Allocations set "Record reference counts" on on (you have to stop recording to set the option). Cause the picker to run, stop recording, search for there ivar (datePickerView), drill down and you will be able to see where all retains, releases and autoreleases occurred.

UISplitView crashing after selecting a row

I have a UISPlitViewController, I have a UITableView in my rootView and have a detailView, on select of second row in my rootView, what i am trying to do is: remove the UISplitViewController and add a new UISplitViewController (based on my requirement), so in the portrait mode when i select second row from the popOver, the application crashing? (but works well in landscape mode).
I'm 100% sure I can answer the question, but it would help if you posted some code. What code are you using now that is working for landscape but crashes in portrait?
(I would've written this in a comment, but I need 50 rep for that).
[splitViewController.view removeFromSuperview];
splitViewController = [[UISplitViewController alloc] init];
rootObj = [[HotelsRootViewController alloc] init];
mapObj = [[mapViewController alloc] init];
rootObj.mapObj = mapObj;
UINavigationController *rootNav=[[UINavigationController alloc]initWithRootViewController:rootObj];
UINavigationController *detailNav=[[UINavigationController alloc]initWithRootViewController:mapObj];
[mapObj release];
splitViewController.viewControllers=[NSArray arrayWithObjects:rootNav,detailNav,nil];
splitViewController.delegate=mapObj;
[window addSubview:splitViewController.view];
[window makeKeyAndVisible];
This is what i do on selection of the second row in my rootViewController, im removing the entire splitView and adding a new SplitView (based on my requirement), but if im in landscape mode, the app doesnt crash, when i turn my iPad in Potrait mode, when i click the button in the toolbar and in the popOver when i select the same second row in the rootView, the app is crashing.....hope u understood now....

Resources