I am attempting to use a UISearch bar in my UITableview's tableHeaderView. This searching functionality worked without issues on iOS 6, but since building against the 7.0 SDK I get a crash when tapping the search bar after returning from another view. The first time viewing the searching tableView, the search bar works just as expected. But once I drill into a detail view, the search bar throw an exc-bad-access exception when I tap it. This bad access is not logged by using NSZombies in my scheme. Here is the code to setup the header view:
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 44)];
self.searchController = [[UISearchDisplayController alloc]
initWithSearchBar:self.searchBar contentsController:self];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
self.tableView.tableHeaderView = self.searchBar;
Properties self.searchBar and self.searchController are both declared as strong references. The no memory warnings are being received anywhere. Has something changed with UISearchBar or tableHeaderView in iOS 7? It may also be noteworthy that I am applying an appearance proxy to UISearchBar, but it looks and works correctly on first load.
I was having trouble with UISearchBar crashes in iOS7 until I started setting my UISearchDisplayController as inactive before the UITableViewController is dismissed. Adding the following worked for me, but I don't know if our problems are related:
[_mySearchDisplayController setActive:NO];
Turns out the crash was due to using sectionIndexTitlesForTableView along with a UISearchDisplayController (see this question). This seems to be a bug in the iOS 7 SDK. Instead, I am now using CMIndexBar as a third party replacement. Works just like the native section indexes, never crashes, easily customizable.
Related
This is obviously an extremely "noobish" question. I'm aware that UITextView has a Boolean editable property, (since I'm not entirely illiterate) so the answer to my question seems really straightforward. But...
I create a UITextView programatically like this:
UITextView* input = [[UITextView alloc] initWithFrame: CGRectMake(0, 0, 100, 30)];
input.backgroundColor = [UIColor whiteColor];
input.editable = YES;
input.text = #"Type something here...";
[input setUserInteractionEnabled: YES];
....
[mainView addSubview: input];
But when I run the iPhone simulator with Xcode, clicking on the input field doesn't do anything. I can't input any text, the virtual keyboard doesn't appear, etc.
So, what am I doing wrong here? Why isn't the UITextView object actually editable in the Xcode iPhone emulator?
I just ran your code in the viewDidLoad command of a sample app that I test code in and it works fine. In my case, I have a UIWebView that I added via Interface Builder which your UITextView pops on top of. I click it and the keyboard pops up.
Is it possible that you may be creating some other object that is begin added to the view after your textfield that is covering it up? Any other view objects being added in the .... part of your sample code?
I am currently working on an application that has some ViewController with a button on it that pushes to a UITableViewController with Search Bar and Search Display controller. I have some data in the cells and that gets populated. I have added the following code to hide the search bar and also make it clearcolor when you do see it:
[[self.searchBar.subviews objectAtIndex:0] removeFromSuperView];
[self.searchBar setBackgroundColor:[UIColor clearColor]];
CGRect newBounds = [[self tableView]bounds];
newBounds.origin.y = newBounds.origin.y + searchBar.bounds.size.height;
[[self tableView] setBounds:newBounds];
Now this works when I am using the iOS simulator, but when I run it on my device and begin to scroll, either up or down, it crashes and gives me the following error:
EXC_BREAKPOINT (code = EXC_ARM_BREAKPOINT, subcode = 0xdefe)
I then enabled Zombie Objects to further debug and got this:
-[UIView frame]: message sent to deallocated instance 0x156b1430
When I take off:
[[self.searchBar.subviews objectAtIndex:0] removeFromSuperView];
[self.searchBar setBackgroundColor:[UIColor clearColor]];
and run my application on my device again, it does not crash and works fine.
Anyone have any ideas whats going on and how this is happening? Thanks in advance!
[[self.searchBar.subviews objectAtIndex:0] removeFromSuperView];
//This Line remove search bar from view ,which means it is deallocated at that moment so when you again try to remove it ,,the app crash ..
// So,instead of this try to hide searchbar ,,
Self. searchBar.hidden =YES;
I think UISearchBar has unsafeunretained reference of [self.searchBar.subviews objectAtIndex:0];
And You set the Bounds of UITableView then change frame of UITableView.
It would fire auto resizing and layoutSubviews.
So, UISearchBar's layoutSubviews method access [self.searchBar.subviews objectAtIndex:0].frame
for layout or auto resizing.
It's not recommended that change view in UIControls from SDK.
There is an idea that Setting hidden=YES instead removeFromSuperview.
I was having this same problem. Got to this page, read the words 'zombie objects' in the question and remembered that I'd left zombie objects enabled. After disabling them, the problem went away. Now when I scroll my tableView, there's no crash.
This may be weird, but perhaps it will help someone...
I'm looking to add a Pull to refresh feature to a UIWebView that I have in an app. I've used Pull to refresh in the past on table views, but I'm struggling to find any good tutorials/libraries to help me add it to UIWebViews specifically and this project.
I did get some of the way using PullToRefreshView by chpwn (https://github.com/chpwn/PullToRefreshView) but I can't get it detecting the drag.
Does anyone know a better plug in/library?
For me this post and code worked like a charm
http://sonnyparlin.com/2011/12/pulltorefresh-ios-5-and-arc-tutorial/
I'm new to iOS development, so this may not be the best way… but it worked for me.
I took the controller that was wrapping my WebView and I changed it to a UITableViewController (it was just a UIViewController previously) so that I could take advantage of the refreshControl property of that controller (ios6 and up). I'm not making use of the TableView inside of the UITableViewController (though, it does seem to require one to exist, which I include, but I just don't populate it). I added 2 methods to the controller:
- (void)addPullToRefresh
{
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:#"Pull to Refresh"];
[refreshControl addTarget:self.myWebView action:#selector(reload)
forControlEvents:UIControlEventValueChanged];
self.refreshControl = refreshControl;
}
- (void)stopRefresh
{
[self.refreshControl endRefreshing];
}
I put a call to [self addPullToRefresh]; in viewDidLoad, and I added a call to [self stopRefresh]; in webViewDidFinishLoad:
I got my instructions for how to use the refreshControl property of UITableViewController here.
I have a need to use a custom background for the UINavigationBar in a MFMailComposeViewController. Previously I was using a category on UINavigationBar to achieve this throughout my app, but Apple specifically requests that you do not do this. Additionally this may or may not work in future versions of iOS that are currently under NDA.
I am now using a subclass of UINavigationBar to achieve the look I'm after in the rest of the app, but I can't see any way to use this with the MFMailComposeViewController. Any ideas?
Note: I'm aware of methods to do this in a future version of iOS, but this needs to be built against a current version (4.3) of the SDK.
I just ran across this -- you can dynamically inject the class a view controller uses using object_setClass.
#import <objc/runtime.h>
object_setClass(mailController.navigationBar, [YourNavigationBarSubClass class]);
You can customize the nav bar's titleView with a custom view using the code below. Expanding upon this idea, you may be able to resize the titleView to cover the entire navigation bar and use a custom background in that to simulate a custom navbar background.
The only possible sticky part I can think of is that you need to make sure the titleView sits behind the buttons in the toolbar.
Once you have your MFMailComposerViewController reference, here is the code to customize the titleView:
[self presentModalViewController:controller animated:YES];
UIView *backgroundView = [[UIView alloc] initWithFrame:CGRectMake(//set size to navbar size)];
[backgroundView setBackgroundColor:[UIColor colorWithPatternImage://your custom image ]];
controller.topViewController.navigationItem.titleView = backgroundView ;
[controller release];
The mail composition interface itself is not customizable and must not be modified by your application.
check apple reference for more info...
http://developer.apple.com/library/ios/#documentation/MessageUI/Reference/MFMailComposeViewController_class/Reference/Reference.html
but we can customizable the mail composition as given oin the above answer....
After some hacking and testing, still not manage to customize the button. But this is the closest I can get, by setting the tint color of mail controller.
Try accessing them through mailController.navigationBar.items, which is an array of the bar items.
MFMailComposeViewController *mailController = [[MFMailComposeViewController alloc] init];
mailController.mailComposeDelegate = self;
mailController.navigationBar.tintColor = [UIColor brownColor];
Although it would be nice to get more control over the appearance, I don't think there is a clean method. When you cant change it...hide it:
NSDictionary *attributes = #{NSForegroundColorAttributeName: [UIColor clearColor]};
[[UINavigationBar appearance] setTitleTextAttributes:attributes];
In my code I am using a UISegmentedControl as a "button" with only ONE segment and the momentary property set to YES. In versions of the SDK prior to iOS 4, this was not a problem, but it appears that now iOS 4 requires that there be at least 2 segments. The following code throws an exception:
NSArray *titles = [NSArray arrayWithObject:#"Button Title"];
myButton = [[UISegmentedControl alloc] initWithItems:titles];
and now in Interface Builder you cannot even create a UISegmentedControl with less than 2 segments. It logs the following error when building:
"The number of segments property of a segmented control must be greater than or equal to 2."
I'm kinda stumped. Any work arounds for this? I tried to create a UISegmentedControl with two buttons and then remove one programmatically and that "works" as it doesn't cause the app to crash. I get a button in iOS 3 and nothing in iOS 4. Any ideas?
Have you tried this:
[myButton removeAllSegments];
[myButton insertSegmentWithTitle:#"Press this" atIndex:0 animated:NO];
Really strange. It still works fine for me both in iOS4 simulator and device (this is a real working snippet from my code):
NSArray *laterContent = [NSArray arrayWithObjects: #"Maybe later", nil];
UISegmentedControl *later = [[UISegmentedControl alloc] initWithItems:laterContent];
CGRect frame = CGRectMake( 20,
98,
self.alert.bounds.size.width/2 - 30,
30);
later.frame = frame;
later.selectedSegmentIndex = -1;
[later addTarget:self action:#selector(laterAction:) forControlEvents:UIControlEventValueChanged];
later.segmentedControlStyle = UISegmentedControlStyleBar;
later.tintColor = [UIColor colorWithRed:130.0f/255.0f green:74.0f/255.0f blue:54.0f/255.0f alpha:0.8f];
later.momentary = YES;
later.alpha = 0.9;
It's not exactly a code-related solution but: I hit a similar issue and ended up drawing my own similar looking resources in Photoshop. It was not terribly difficult to do and removed a particular bad "code smell", IMO.
I found if you have a previous project with a single-segment UISegmentedControl, you can open both that project and your new one in Interface Builder and drag (or copy/paste) the single-segment UISegmentedControl to your new view controller. It will work fine in both your app and Interface Builder, just don't change the number of segments from 1 to anything else as it won't let you go back. I'm using Xcode 4.6.2 and iOS 6.
The editor in Interface Builder won't let you change the number of segments to be less than 1, but you can make a segmented control in IB by editing the .xib xml manually.
Right click on the .xib containing the segmented control
Choose Open As -> Source Code from the popup menu.
Find "<segments> which is the beginning of the xml array of segments. The whole thing should look like:
<segments>
<segment title="Segment 1 Title"/>
<segment title="Segment 2 Title"/>
</segments>
Just delete <segment title="Segment 2 Title"/> so there is only one segment element.
Right click the .xib again and choose Open As -> Interface Builder - iOS to go back to interface builder.
You should also probably set the segmented control to "momentary" mode.
I don't get any errors compiling or running this. Of course, this is a hack, and may break things in some circumstances or in a future iOS release.
Well two possibilities:
1) Create a button and the set background image as the single dot of the UISegmentedControl
If your SegmentedControl is a class variable just replace the #property
#property (nonatomic, retain) IBOutlet UIButton *button;
In the viewDidLoad-function add the following
-(void) viewDidLoad
{
[super viewDidLoad];
...
self.button = [UIButton alloc] init];
[self.button setBackgroundImage:[UIImage imageNamed:#"segmentedDot.png"] forState:(UIControlState)UIControlStateNormal];
}
2) Set the amount of segments to three of your UISegmentedControl and afterwards set the width to 20 - now only the dot in the middle will be shown.
Dont forget, if the user interacts with the UISegmentedControl, set the currentElement again to the second segment, else the dot will be in light grey instead of white state.
3) Place a button or a small view over the unwanted second dot of the UISegmentedControl in InterfaceBuilder. Make sure the backgroundcolor is even.
When you are using a button set the state for "user interaction" in attribute inspector to disabled. As type I would chose "custom" since you won't have some borders in your button ;)
Now male again sure, that always the first dot is the active Element.
However I think solution one should be the way you should go, since Apple thought something about it, when they disabled the 1-dot-SegmentedControl. Since you are using the Control as a button the Element you are looking fpr should be a button. ;)
There's no workaround in iOS 4. If you need this functionality, file a bug (enhancement request) at bugreport.apple.com.
You can also use removeSegmentAtIndex:animated:. If you create a segmented control in a storyboard or xib with two segments, you can remove one like this:
[self.sortButton removeSegmentAtIndex:1 animated:NO];