I have a TableView that contains a list of names for the cell text taken from an NSArray called arryData. In the didSelectRowAtIndexPath, I have:
NextViewController *nextController = [[NextViewController alloc] initWithNibName:#"NextViewController" bundle:nil];
[self.navigationController pushViewController:nextController animated:YES];
[nextController changeProductText:[arryData objectAtIndex:indexPath.row]];
In the NextViewController I have:
- (IBAction) changeProductText:(NSString *)str{
NSLog(#"whosthere%#", str);
self.title = str;
if ( [str isEqualToString: #"Row 1 Name"]) {
lblProductTxt.image = [UIImage imageNamed:#"row1name.png"];
job.text = #"Sr. Minister & Elder";
NSLog(#"Row 1 Name");
emailaddress = #"Row1Email#att.net";
}
...
}
When I click on the Row 1 name, my console shows "whosthererow1name" and the other NSLog fires off Row 1 Name, however the image doesn't show up, and neither does the text. I have this built using IB and XIB file. I made sure that the Class matched up and that the IBOutlet for both the UILabel and UIImageView were connected. They were.
Why would this not be working?
UPDATE:
Just tested this on a 6.1 device and 7.0 device. 6.1 it works fine, 7.0 it shows no image.
The reason this doesn't work is because the label and the image view will be null at the time you call changeProductText: since nextController's view hasn't been loaded yet. What I don't understand is why it worked in iOS 6. Are you sure you did it exactly this way in iOS 6? The way to do this is to pass a string (and anything else you want) to a property you create in nextController, and populate the UI elements in viewDidLoad.
Is the UIImageView actually initialized and on the screen somewhere? Does the image file actually exist? Make sure that both the UIImageView and the UIImage you are creating are not nil by setting a breakpoint at the point of assignment in the code.
Related
I have a project in Xcode 5 that I'm migrating to Xcode 7. I have an array of custom UIViewControllers that come with XIBs. I take each object in the array and pass it through, like this
- (void) createViewForObject:(NSObject *)object
{
if ([object isKindOfClass:[CustomViewController class]])
{
CustomViewController *cvc = (CustomViewController*)object;
//If I create a view controller from within the function,
//it successfully adds, as demonstrated below.
//But I'm not able to add the view of the object
//that was passed in from outside
OtherCustomViewController *otherCvc = //initialization here
UITableViewCell* cell= [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CustomViewControllerCell"];
[cvc.view frameResizeToHeight:[gtf getHeight]];
[cvc.view frameMoveToPosition:CGPointMake(340, 0)];
cell.frame=cvc.view.frame;
otherCvc.view.frame = cvc.view.frame;
[cell frameResizeToHeight:MAX(MAX(50, textSize.height+10),cell.frame.size.height)+11]; //just a resizing helper method
//This is code that successfully adds the other custom view controller that was created within this method to the cell, but I want to use the other custom view controller (the one that was passed in from outside) so I can keep references to certain properties.
// [cell addSubview:otherCvc.view];
// [self addChildViewController:otherCvc];
// [otherCvc didMoveToParentViewController:self];
//This is the code that doesn't work that I want to work
[self addChildViewController:cvc];
cvc.view.frame = cell.frame;
[cell.contentView addSubview:cvc.view];
[cvc didMoveToParentViewController:self];
//I'm also able to add the custom view that was passed in from outside directly to the main view with the code below, so the views do exist.
//They're just not getting added to the cell.
//[self.view addSubview:cvc.view];
}
}
I'm able to access all the properties of this custom view controller, but it won't let me add the view as a subview to the cell, even though it did allow this in Xcode 5. (the Xcode 5 was post ARC, BTW). What's also interesting is that I'm able to add the view controller subviews to the main view (to self.view)
Any ideas on what I can do?
I have a UISegmentedControl in a UITableView Table row. The selection fires, and the new segment is highlighted. The problem is, the old segment remains selected.
If I close and reopen the popover that contains the table, the correct segment index is displayed.
I'm running XCode 6.1 and testing on iOS 7.1 simulator.
Assistance appreciated.
UITableViewCell *segmentCell = [tableView dequeueReusableCellWithIdentifier:segmentCellIdentifier];
if (segmentCell == nil) {
segmentCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:segmentCellIdentifier];
}
segmentCell.backgroundColor = [UIColor clearColor];
segmentCell.backgroundView = nil;
NSArray *segmentItems = [NSArray arrayWithObjects: NSLocalizedString(#"settingsBackgroundCork", #"Cork - Select cork background theme"), NSLocalizedString(#"settingsBackgroundDark", #"Dark - Select dark background theme"), NSLocalizedString(#"settingsBackgroundLight", #"Light - Select light background theme"), nil];
self.backgroundSegmentedControl = [[UISegmentedControl alloc] initWithItems: segmentItems];
[self.backgroundSegmentedControl addTarget:self action:#selector(backgroundControlChanged:) forControlEvents: UIControlEventValueChanged];
self.backgroundSegmentedControl.frame = CGRectMake(10, 6, 300, 32);
NSInteger background = [[NSUserDefaults standardUserDefaults] integerForKey:kUserDefaultsBackgroundSelection];
self.backgroundSegmentedControl.selectedSegmentIndex = background;
self.backgroundSegmentedControl.momentary = NO;
[segmentCell.contentView addSubview:self.backgroundSegmentedControl];
cellToReturn = segmentCell;
Here is the method that gets called on segment selection:
- (void)backgroundControlChanged:(UISegmentedControl *)control
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setInteger:control.selectedSegmentIndex forKey:kUserDefaultsBackgroundSelection];
self.backgroundSegmentedControl.selectedSegmentIndex = control.selectedSegmentIndex;
[self.backgroundSegmentedControl setNeedsDisplay];
[[NSNotificationCenter defaultCenter] postNotificationName:kPageBackgroundShouldChangeNotification object:nil];
}
Strange bug - I never saw this before. Two suggestions:
Try setting the selectedSegmentIndex again in the handler, and
Try calling setNeedsDisplay on the control there as well.
momentary is NO by default, so you should not need to set it.
Also, in the selectedSegmentIndex documentation it says:
The default value is UISegmentedControlNoSegment (no segment selected) until the user touches a segment. Set this property to -1 to turn off the current selection.
Maybe you want to try this last thing as well.
I was able to fix this issue by moving my call to setSelectedSegmentIndex to inside the setNeedsLayout function, instead of calling it right after creation of the UISegmentedControl. Of course I also had to create a variable to keep track of which segment should be selected.
Had the same issue. Resolved it by removing the previous instance of the segmentedControl from the superview before adding the new instance.
Adding the below-mentioned 3 lines of code to remove previous segmentedControl before adding the new instance of segmentedControl to the parent view.
self.backgroundSegmentedControl.tag = 101
if let foundView2 = segmentCell.contentView.viewWithTag(101) {
foundView2.removeFromSuperview()
}
[segmentCell.contentView addSubview:self.backgroundSegmentedControl];
I'm updating an old iOS project that uses XIB files but want to convert to Storyboard. I created my Storyboard, connected it with the appropriate ViewControllers, removed any references that I can find to the XIB files, and set the Main Interface of the project to use my Storyboard.
However, when I run my app it still shows the XIB files instead of using the Storyboard; as if there's something still referencing them. The only one that shows the Storyboard is the initial scene/ViewController (and it's most likely because it's a newly created ViewController).
I've looked at other solutions online but to no avail. I tried:
Cleaning the project
Deleting DerivedData folder
Restarting Xcode and my computer
Updated MyApplication-info.plist
Removed references to ViewControllers from XIB files
Tried removing XIB files from project (it'll show a black screen because file is missing)
The original project target iOS 5.1, the new 6.0, and I'm using Xcode 5. Is there anything that I might be missing?
Edit: I'm not programmatically segueing to the other controllers; I have the Storyboard take care of that. The only thing I do in the first ViewController is send a string text to the next one:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NextViewController * nextController;
if ([[segue identifier] isEqualToString:#"SegueToNext"])
{
nextController = [segue destinationViewController];
[nextController initWithTitle:#"New"];
}
}
Edit: This is the code for the ViewController that is showing the XIB file instead of the Storyboard. As you can see, there are no calls related to loading/pushing new controllers or anything that should relate to the XIB.
#import "NextViewController.h"
#interface NextViewController ()
#end
#implementation NextViewController
-(id) initWithTitle:(NSString *) title
{
self = [super init];
if (self)
{
self.title = title;
// Load the dictionary
self.dictionary = [NSDictionary dictionaryWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"NewDictionary"
ofType:#"plist"]];
}
return self;
}
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// Render new slide
[self renderOpening];
}
-(void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
-(void) renderOpening
{
// 1st slide
NSLog(#"renderOpening");
// Initial settings for opening slide; all are UIOutlets (UIButton, UIImageView)
back.hidden = YES;
diagram.hidden = YES;
next.hidden = NO;
text.hidden = NO;
avatar.hidden = NO;
avatar.image = [[UIImage imageNamed:#"avatar"]
rescaleImageToSize:CGSizeMake(150, 150)];
text.text = #"Hello World";
}
#end
Within your appDelegate class file, remove any code that directs the app to launch to your old initial xib. (From within the didFinishLaunching' method) You don't need to replace it with any code to start the storyboard as this selects this from the 'Development Info' section - see below.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Then click on your project and under the tab of 'General' within the 'Development Info' section, make sure your storyboard is selected as the main interface - see picture below.
Also, if you select the view controller from the storyboard that you want the app to initially start with and select it. Then go to the RHS utilities area and make sure the 'Initial Scene [ ] Is Initial View Controller bock is selected, please see picture.
I hope this helps,
Cheers
Jim
In the ViewController that I was segueing to, I called a custom function which returned a reference to a newly created object of the ViewController class itself:
-(id) initWithTitle:(NSString *) title
{
self = [super init];
if (self)
{
self.title = title;
// Load the dictionary
self.dictionary = [NSDictionary dictionaryWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"NewDictionary"
ofType:#"plist"]];
}
return self;
}
It was left there from the old code, and I completely overlooked it. It was no longer needed now that I was using Storyboard. So instead of seeing the ViewController that I was segueing into, it was showing the old XIB file. Deleting the XIB file from the project showed an empty, black view, and removing the code [super init] showed the correct Storyboard ViewController.
Although I got it working, I'm still not certain as to why it was showing the old XIB file, even though I removed references to it.
I tried a few things myself, but couldnt really get the handle around it.
I wanna do two things:
First the user can press one of three buttons - They all link to the same ViewController, but when User Presses the first button three labels change accordingly in this second ViewController. And then the user can enter some data which will be displayed in the third view, also accordingly on which button was pressed in the first view.
I tried it with IF Statements, e.g. (IF ViewController.button1waspressed == True) and it didnt really work. I also tried it with tags e.g. (Button1.tag = 1)
Could someone give me a short example on how this could work?
FirstViewController.m
- (IBAction)switch:(id)sender;
{
SecondViewController *second =[[SecondViewController alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:second animated:YES];
SecondViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
if (sender == self.button1) {
NSString *greeting = [[NSString alloc] initWithFormat:#"Randomtext"];
self.label.text = greeting;
}
}
The problem is obvious in this one, SecondViewController cant see the property from the first one. (And yes I imported the FirstViewController and vice versa)
Your buttons should all directly call IBActions (methods defined like so):
- (IBAction)doSomething:(id)sender;
Defining them as IBActions exposes them to be connected with the blue connection lines in interface builder. Once you've hooked them up and the method is being called, you can simply use an equality check on the sender parameter, which the calling button will automatically set as itself.
if (sender == self.myButton) {
// do something
}
Here I'm assuming that you've got a property called myButton in your ViewController, which would be an IBOutlet:
#property (nonatomic, retain) IBoutlet UIButton *myButton;
This exposes that property to be connected with the blue connection lines in interface builder, so your ViewController will know exactly which button you're talking about when you say myButton.
I am writing a SplitView iPad app. Inside the DetailViewController, there's a little view that contains a UITableView and a UISearchBar and its controller. This view does not represent the whole screen space reserved for the DetailViewController. Actually, it uses just half of it. There's an UIImageView on the other half.
And this is where trouble comes in: every time I use the search bar, the displaycontroller (I assume) dims everything present inside the DetailViewController, including the image view. That is not consistent with what someone would expect when running the app. Is there any way to set the frame to be dimmed? Or at least disable dimming for good?
Thanks in advance.
You are correct that it is the UISearchDisplayController that is managing the "dimming" effect that you're seeing.
What the UISearchDisplayController is doing is adding a UIControl as a subview to the view of the searchContentsController (a property of UISearchDisplayController), which is likely your detail-view controller. This UIControl is just an alpha'd view with a gray background. It seems to have a touch-up-inside event handler that ends searching when tapped.
To constrain the dimming effect to your sub-view of the detail-view, you need to do three things. (I'm assuming your detail-view-controller is defined via a xib. If not, these steps can be done in code too.)
1) add a new UIViewController to your detail-view-controller xib. Attach this new view-controller to an IBOutlet of your detail-view-controller. In my example I call this "_searchAreaViewController". This is important, even if you wont ever access the view controller (but remember, you'll have to release it at some point)
#interface DetailViewController : UIViewController <UIPopoverControllerDelegate, UISplitViewControllerDelegate, UITableViewDelegate, UITableViewDataSource> {
UIPopoverController *popoverController;
UIToolbar *toolbar;
id detailItem;
UILabel *detailDescriptionLabel;
IBOutlet UIViewController* _searchAreaViewController;
}
2) make the containing view for your search area the view of this new view-controller. To do this, use Interface Builder to set a new referencing outlet for this view by dragging the outlet to the searchAreaViewController and selecting the "view" outlet. You must have a containing view - it should be a subview of your detail-view, and it should contain the UISearchBar and likely your UITableView.
3) make the searchContentsController property of the UISearchDisplayController refer to this new view controller instead of the detail-view-controller. This can only be done via Interface Builder as the property is read-only (IB has some magic to make this work?) If you need to do this step via code you'll have to subclass the UISearchDisplayController and return the correct value from a property override of "searchContentsController".
I made a sample app to demonstrate this and the only line of code I had to add to the SplitView template was the one listed in step 1 above. Everything else was just adding the views/controllers and connecting them properly in IB.
good luck!
iOS 8+
[[UIView appearanceWhenContainedInInstancesOfClasses:#[NSClassFromString(#"UISearchDisplayControllerContainerView")]] setHidden:YES];
iOS 7
[View appearanceWhenContainedIn:NSClassFromString(#"UISearchDisplayControllerContainerView"), nil] setHidden:YES];
I know, that UISearchDisplayController is deprecated for now, but if you still need to use it, you can solve your issue with one line of code perfectly. Add it to viewDidLoad method.
Could you clarify what you mean by "use the search bar" and "dims everything present"? I interpret what you wrote in such a way that the keyboard pops up when you are about to enter text in the text field of the search bar. And that at this point the detail view is dimmed out, preventing user interaction.
The cause is that the search bar implements a modal dialog which prevents user interaction with the view as long as the keyboard is shown. Unfortunately, there doesn't seem to be any way to configure the search bar to prevent this behavior. On the other hand I am not sure that the user won't expect this behavior since search bars are modal consistently and behave like this in general under iOS.
I have tried two work-arounds:
1.) There is a property of the UIViewController called modalPresentationStyle which produces exactly the behavior you describe if it has the value UIModalPresentationFormSheet ("All uncovered areas are dimmed to prevent the user from interacting with them.", see the Apple documentation). But setting this property to a different values does not change the result (at least for me it didn't work).
2.) You would need to write your own non-modal search bar replacement since a standard UITextField is non-modal and thus does not dim out any other UI elements. This approach works, but you might need a little more work to make it look like a "regular" search bar. But, again, since this search bar behaves differently from the modal normal search bars in iOS this might not really be what the users expect.
I know I am late and this is a horrible idea here, but 'setHidden:No' did not work for me.
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
BOOL hasBeenremoved = NO;
hasBeenremoved = [[[[NSThread mainThread] threadDictionary] objectForKey:#"hasBeenremoved"] boolValue];
if (hasBeenremoved)
{
UIView* dimmingView = nil;
dimmingView = [[[NSThread mainThread] threadDictionary] objectForKey:#"dimmingView"];
UIView* dimmingViewSuperView = nil;
dimmingViewSuperView = [[[NSThread mainThread] threadDictionary] objectForKey:#"dimmingViewSuperView"];
[dimmingViewSuperView addSubview:dimmingView];
[[[NSThread mainThread] threadDictionary] setObject:#NO forKey:#"hasBeenremoved"];
}
if ([searchText length] == 0 || [searchText isEqualToString:#""] )
{
[searchBar becomeFirstResponder];
[[[self primarySearchDisplayController] searchResultsTableView] reloadData];
[[[self primarySearchDisplayController] searchResultsTableView] setHidden:NO];
for( UIView *subview in self.view.subviews )
{
if([subview isMemberOfClass:[UIControl class]] ||
([[[subview class] description] isEqualToString:#"UISearchDisplayControllerContainerView"]))
{
for(UIView *subView2 in subview.subviews)
{
for(UIView *subView3 in subView2.subviews)
{
if (subView3.alpha < 1)
{
if ([[[subView3 class] description] isEqualToString:#"_UISearchDisplayControllerDimmingView"])
{
[[[NSThread mainThread] threadDictionary] setObject:subView3 forKey:#"dimmingView"];
[[[NSThread mainThread] threadDictionary] setObject:subView3.superview forKey:#"dimmingViewSuperView"];
[[[NSThread mainThread] threadDictionary] setObject:#YES forKey:#"hasBeenremoved"];
[subView3 removeFromSuperview];
}
}
}
}
}
}
}
}