How do I add custom buttons to UIAlertView ??
UIButton *newButton=[[UIButton alloc]init];
[self.alertview addSubview:newButton];
NOTE: dont forget to specify the frame to ur button.
If you only want to customize the button's names, then you can use the "otherButtonTitles" section of the following initializer:
– initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles:
(You can also add buttons with a custom name using the - (NSInteger)addButtonWithTitle:(NSString *)title instance method).
However, if you want to customize more than just the title of the button, then you need to add a subview of your custom button, as show in madhu's sample code.
You will also need to set the frame of your newButton object so as it's positioned where you want it inside the UIAlertView instance. Because the UIAlertView isn't particularly designed for nesting subviews within it (this is a common thing for developers to want to do and struggle with), you may encounter some strange effects that requires fiddling around with your view hierarchy in order to solve. I'm sure there are plenty questions out there that describe some of these strange effects, and I myself have asked about at least one of them!
Related
I have a simple app with a Tool Bar at the bottom. Depending upon the context of what the user is doing, I may want various buttons visible or not in the Tool Bar. So, in my code, I remove the weak modifier for the IBOutlet reference to those buttons, and I remove the non-visible buttons in viewDidLoad. Great.
Now, when the context changes, I add/remove buttons as desired using
toolBar.items?.removeAtIndex(0)
toolBar.items?.insert(playButton, atIndex: 0)
Great, works well. But for aesthetics, I would like to have the button removal/insert animated. Apparently the animated:YES argument from Objective-C days is gone. Do you know, does the API support animation of the button shuffling? Or, if not, how best to accomplish this?
Thanks!
I'm fairly new to Mac development and am slightly confused by the new "storyboard" feature in Xcode 6. What I'm trying to do is segue from one view controller to another in the same window. As of right now, all the different NSViewControllerSegues present the view controller in a new window, be it a modal or just another window. What I'd like to do is just segue within the same window, much in the same way one would on iOS (though an animated transition is not crucial). How would this be achieved?
If you provide a custom segue (subclass of NSStoryboardSegue) you can get the result you are after. There are a few gotchas with this approach though:
the custom segue will use presentViewController:animator so you will need to provide an animator object
because the presented view is not backed by a separate Window object, you may need to provide it with a custom NSView just to catch out mouse events that you don't want to propagate to the underlying NSViewController's view
there's also a Swift-only glitch regarding the custom segue's identifier property you need to watch out for.
As there doesn't seem to be much documentation about this I have made a small demo project with custom segue examples in Swift and Objective-C.
I also have provided some more detail in answer to this question.
(Reviving this as it comes up as first relevant result on Google and I had the same problem but decided against a custom segue)
While custom segues work (at least, the code given in foundry's answer worked under Swift 3; it needs updating for Swift 4), the sheer amount of work involved in writing a custom animator suggests to me that their main use case is custom animations.
The simple solution to changing the content of a window is to create an NSWindowController for your window, and to set its contentViewController to the desired viewController. This is particularly useful if you are following the typical pattern of storyboards and instantiate a new ViewController instance every time you switch.
However.
The NSStoryboard documentation says, quite clearly in macOS, containment (rather than transition) is the more common notion for storyboards which led me to look again at the available tools.
You could use a container view for this task, which adds a NWViewController layer instead of the NSWindowController outlined above. The solution I've gone with is to use an NSTabViewController. In the attributes inspector, set the style to 'unspecified', then select the TabView and set its style to 'tabless'.
To change tabs programatically, you set the selectedTabViewItemIndexof your TabViewController.
This solution reuses the same instance of the ViewControllers for the tab content, so that any data entered in text fields is preserved when the user switches to the other 'tab'.
Simple way with no segues involved to replace the current view controller in the same window:
if let myViewController = self.storyboard?.instantiateController(withIdentifier: "MyViewController") as? MyViewController {
self.view.window?.contentViewController = myViewController
}
I have a view that needs to have its frame manipulated programmatically - it's a kind of document view that wraps to its content which is then scrolled and zoomed around a superview by manipulating the frame origin. Autolayout fights with this at runtime.
Disabling autolayout completely seems a bit harsh because it could reasonably be used to handle layout for the other views. It seems like what I might want is some kind of "null constraint".
I had the same problem. But I have resolved it.
Yes, you can disable auto layout at runtime for a specific UIView, instead of disabling it for the whole xib or storyboard which is set by default in Xcode 4.3 and later.
Set translatesAutoresizingMaskIntoConstraints to YES, before you set the frame of your subview:
self.exampleView.translatesAutoresizingMaskIntoConstraints = YES;
self.exampleView.frame = CGRectMake(20, 20, 50, 50);
I had a similar issue where Autolayout was overriding some of my frame-setting at run time (I had a dynamic view that in some cases pushed a new view controller...pushing and then pressing Back would reset the initial view).
I got around this by putting my manipulation code in viewDidLayoutSubviews of my View Controller. This seems to get called after whatever constraint mojo gets called, but before viewDidAppear, so the user is none the wiser.
Perhaps just setting translatesAutoresizingMaskIntoConstraints to YES (and not adding additional constraints affecting that view) will let you set the frame without fighting the auto layout system.
In iOS 8 you can set an NSLayoutConstraint to be active or not. So if I'm using interface builder, I add all my constraints to an OutletCollection and then activate or deactivate using:
NSLayoutConstraint.deactivateConstraints(self.landscapeConstraintsPad)
NSLayoutConstraint.activateConstraints(self.portraitConstraintsPad)
The particular application I'm using it for here is having different constraints in portrait and landscape mode and I activate/deactivate based on the rotation of the device. It means I can create some complex layout changes all in interface builder for both orientations, and still use auto layout without the verbose auto layout code.
Or you can activate / deactivate using removeConstraints and addConstraints.
I don't know if this will help anyone else, but I wrote a category to make this convenient because I find myself doing this a lot.
UIView+DisableAutolayoutTemporarily.h
#import <UIKit/UIKit.h>
#interface UIView (DisableAutolayoutTemporarily)
// the view as a parameter is a convenience so we don't have to always
// guard against strong-reference cycles
- (void)resizeWithBlock:(void (^)(UIView *view))block;
#end
UIView+DisableAutolayoutTemporarily.m
#import "UIView+DisableAutoResizeTemporarily.h"
#implementation UIView (DisableAutoResizeTemporarily)
- (void)resizeWithBlock:(void (^)(UIView * view))block
{
UIView *superview = self.superview;
[self removeFromSuperview];
[self setTranslatesAutoresizingMaskIntoConstraints:YES];
__weak UIView *weakSelf = self;
block(weakSelf);
[superview addSubview:self];
}
#end
I use it like this:
[cell.argumentLabel resizeWithBlock:^(UIView *view) {
[view setFrame:frame];
}];
Hope it helps.
You can set the translatesAutoresizingMaskIntoConstraints type Boolean, Value Yes in the User Defined Runtime Attributes of the UIView you want in the xib/storyboard.
In my view I had a Label and a Text. The label had pan gesture. The label moves around fine during drag. But when I use the text box keyboard, the label resets its position to the original location defined in auto layout. The issue got resolved when I added the following in swift for the label. I added this in viewWillAppear but it can be added pretty much anywhere you have access to the target field.
self.captionUILabel.translatesAutoresizingMaskIntoConstraints = true
Open project in 4.5
Select storyboard
Open the file inspector
Under Interface Builder Document uncheck 'Use Autolayout'
You can split across multiple storyboards if you want to use autolayout for some views.
For me it worked to create the subview programmatically, in my case the auto layout was messing with a view that I needed to rotate around its center but once I created this view programmatically it worked.
I've encountered a similar scenario, where I joined a project that was initiated with auto-layout, but I needed to make dynamic adjustments to several views. Here is what has worked for me:
Do NOT have views or components laid out in interface builder.
Add your views purely programmatically starting with alloc/init and setting their frames appropriately.
Done.
This happened to me in a project without storyboards or xib files. All 100% code. I had an ad banner at the bottom and wanted the view bounds to stop at the ad banner. The view would resize itself automatically after loading. I tried every resolution on this page but none of them worked.
I ended up just creating a sub view with the shortened height and placed that in into the main view of the controller. Then all my content went inside the sub view. That solved the problem very easily without doing anything that felt like it was going against the grain.
I am thinking if you want a view that is not the normal size that fills the window then you should use a sub view for that.
Instead of disabling autolayout, I would just calculate the new constraint with the frame you are replacing. That appears to me to be the appropriate way. If you are adjusting components that rely on constraints, adjust them accordingly.
For example, if you have a vertical constraint of 0 between two views (myView and otherView), and you have a pan gesture or something that adjusts the height of myView then you can recalculate the constraint with the adjusted values.
self.verticalConstraint.constant = newMyViewYOriginValue - (self.otherView.frame.origin.y + self.otherView.frame.size.height);
[self.myView needsUpdateConstraints];
For those of you who are using auto layout, please check out my solution here. You should be making #IBOutlet's of the constraints you want to adjust and then change their constants.
if it's xib file:
select the .xib file
select the "File's Owner"
show the Utilities
click on: "File Inspector"
Under "Interface Builder Document" disable: "Use Autolayout"
I'm struggling with Cocoa for 2 hours now without success. I want to add a custom view to the toolbar. So, I added a NSToolbar to the window (with IB), and added my view (which works perfectly). IB automatically created a NSToolbarItem.
I followed the instructions from Apple here: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Toolbars/Tasks/AddRemoveToolbarItems.html#//apple_ref/doc/uid/20000755-BBCGJCDJ
The problem is that I don't know what to do now, the view doesn't show although it's label is displayed in the window.
Here's the code I use to draw (very simple, it's for testing purpose)
- (void)drawRect:(NSRect)dirtyRect {
[[NSColor blackColor] set];
[[NSBezierPath bezierPathWithRect:self.bounds] fill];
}
Can someone help me?
Thanks in advance.
I solved the problem.
I put my custom view in the root of the nib. I added a classic NSToolbarItem and created two outlets: one for the custom view and one for the NSToolbarItem. On -(void)awakeFromNib, I called setView: on the NSToolbarItem with the custom view.
According to some ressources on the internet, it is a bug with Interface Builder.
According to an Apple engineer in the discussion at http://www.mail-archive.com/cocoa-dev#lists.apple.com/msg35673.html, there is a bug in Interface Builder whereby "Custom Views" (NSViews created in IB) are not decoded properly when used as the view for an NSToolbarItem, and so do not appear in the toolbar. Other kinds of NSViews, such as NSButtons and NSBoxes, will work just fine as toolbar items: you can create these in Interface Builder and then drag them into the toolbar to make them into toolbar items.
(The discussion in the link above implies that the bug is down to how "Custom Views" are created from the XIB at runtime: using initWithFrame: instead of initWithCoder:. The discussion dates from 2009 but this still hasn't been fixed as of XCode 4.5/OS X 10.8.)
In my case I was using a regular NSView to wrap a set of controls (a volume slider and min/max buttons), rather than implementing a custom NSView subclass. I was able to avoid the problem by using an NSBox as the container instead of an NSView: I made the NSBox transparent, title-less and borderless, so it otherwise acted exactly like a plain NSView wrapper. This was a little more work in IB, but saved me the trouble of wiring up the view to the toolbar item programmatically.
I am reading many posts about UIViewController managing but I can't find the solution to my problem. I am making an iPhone game. I have three screens (menu, game play and scores) constructed into the Interface Builder and from three UIViewController classes. Into the main menu I have two custom buttons that allow to go to the game play screen or to the scores screen. Actually I am using the next method to navigate but when I use it, even it changes the screen and takes me to the game play, I can't see the highlighted state of the custom button. Must I change the views like this? How can I show the custom state of my buttons? How can I show an animation while the views are changing?
- (IBAction)gotoPlayViewController:(id)sender {
//Navigation logic may go here.
PlayViewController *playViewController = [[PlayViewController alloc] initWithNibName:#"PlayViewController" bundle:nil];
self.view = playViewController.view;
[playViewController release];
}
Thanks for readding.
You want to use UINavigationController, don't you?
The UINavigationController class implements a specialized view controller that manages the navigation of hierarchical content. This class is not intended for subclassing. Instead, you use instances of it as-is in situations where you want your application’s user interface to reflect the hierarchical nature of your content. This navigation interface makes it possible to present your data efficiently and also makes it easier for the user to navigate that content.
Here is a nice tutorial.
Here is the class reference.
UINavigationController also provides a very easy way to add the slide transition you want.
Have fun!