I create a new macOS app in XCode.
I add the entitlement com.apple.security.files.user-selected.read-write with value YES (to allow usage of NSSavePanel)
In AppDelegate.m, I implement applicationDidFinishLaunching as follows:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSSavePanel* nssavepanel = [NSSavePanel savePanel];
NSButton* nsbutton = [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 50, 20)];
[nsbutton setTitle:#"Button title"];
[nssavepanel setAccessoryView:[[NSView alloc] initWithFrame:NSMakeRect(0, 0, 200, 80)]];
[[nssavepanel accessoryView] addSubview:nsbutton];
[nssavepanel beginWithCompletionHandler:^(NSModalResponse result) {}];
}
When I start the application, I see a panel with a button.
On macOS 10.15.3, I can click the button in the acceessory view.
On macOS 11.0 Beta (20A4300b), I cannot click the button -- the whole accessory view seems to be disabled. (If I use runModal or beginSheetModalForWindow instead of beginWithCompletionHandler, the accessory view works as expected.) Is this a bug? Am I doing something wrong here?
Related
For an app targeted at both iOS 7 and iOS 8, I'm using two ViewControllers which should have the following characteristics:
ViewController 1 (VC1) is in Portrait Mode
VC1 created ViewController 2 (VC2) which is in Landscape mode
VC2 has a translucent background so that VC1's contents are visible
I've referred to IOS 7: Transparent Viewcontroller Background over another Viewcontroller with different Orientation behaviour but the solution provided does not work. On iOS 8, I can either get landscape orientation or transparency for VC2 but not both
Here's what I'm doing:
self.view.backgroundColor = [UIColor clearColor];
UILabel* label = [[UILabel alloc] initWithFrame:self.view.frame];
label.text = #" I'M VC1";
[self.view addSubview:label];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
LandscapeViewController* lvc = [[LandscapeViewController alloc] init];
self.modalPresentationStyle = UIModalPresentationOverCurrentContext;
//Uncomment this line for transparency but loses orientation
//lvc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:lvc animated:YES completion:nil];
});
Any idea what's wrong and how can I make it work?
When I addSubview: nothing shows up. I set text and color to see it. Also if I manually add the view to the custom view in the UI bulder in xcode it shows up just fine with the text and color.
.m file
- (void)displayString:(NSString *)title {
NSRect frame = NSMakeRect(10, 10, 200, 17);
NSTextfield *newfield = [[NSTextField alloc] initWithFrame:frame];
[newfield setBezeled:NO];
[newfield setDrawsBackground:NO];
[newfield setEditable:NO];
[newfield setSelectable:NO];
[newfield setStringValue:title];
[newfield setTextColor:[NSColor blueColor]];
[test addSubview:newfield];
if([test.subviews containsObject:newfield]){
NSLog(#"view there"); // i get this message
}
if([newfield isHidden]){
NSLog(#"view hidden"); //i dont get this message
}
NSLog(#"view set");
}
test is a NSView (Custom view is what xcode calls it) that I have properly linked in.
So when I create the text field and add it to the NSView manually and then run that same code by adding text and color all works fine, this issue arrises when I try programmatically setting the view. Also I made sure it wasn't my creating of the view, as I have tried creating the view in the builder and not placing it in the NSView and then trying addSubview: but that also does not work. Let me know if you need more code.
DEVELOPMENT:
If the nsview (custom view) has an element already in it (manually added and can be anything) and I add the text field it works (I get both views in the nsview)? The subview is tested for and there, just cant see it.
You have to call initWithFrame: instead of just init
- (void)displayString:(NSString *)title {
NSRect frame = NSMakeRect(10, 10, 200, 200);
NSTextField *newfield = [[NSTextField alloc] initWithFrame:frame];
[newfield setStringValue:title];
[newfield setTextColor:[NSColor blueColor]];
[test addSubview:newfield];
NSLog(#"view set");
}
What type of view is test? Also you need to do a:
newfield.frame = CGRectMake(x,y,width,height)
in order to specify the look of the view
Turns out I set the view too early. I was under the impression that whatever you do to the view after its been set will be reflected on the view, but that seemed to be the issue. After altering the view to be exactly they way I want then set the view of the NSStatuditem.
so I get
[newfield setStringValue:title];
[newfield setTextColor:[NSColor blueColor]];
[test addSubview:newfield];
[statusItem setView:test];//this is the key, setting it after he changes.
I am learning iOS. I m using Xcode 4.3.2 , and i have created a button, and in the callback, i have used the following code.
1) Created single view application
2) creating a new view -> newV
3) creating a button but;
4) adding but as a subview of newV.
5) adding newV as a subview of main view.
-(IBAction) submitButtonPressed:(id)sender
{
NSLog (#" Submit Button is pressed ");
UIView *newV = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
newV.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
UIButton *but = [[UIButton alloc] init];
[but setTitle:#"SubView" forState:UIControlStateNormal];
[newV addSubview:but];
[self.view addSubview:newV];
}
But the problem i get is, only the view viewV is shown, but button is not shown. How to resolve this issue ?
When you created the button, you didn't provide a frame. Try using:
UIButton* but = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, buttonWidth, buttonHeight)];
When you created the button, it was of zero size, so you couldn't see it.
Try adding the button after adding in the view newV.
I am using an applicationMusicPlayer and when i try to change the volume appear the visual notification, as shown in the picture.
Here the code I am using:
[MPMusicPlayerController applicationMusicPlayer] setVolume:newVolune];
Anyone knows how to hide this notification?
I don't know where the docs says so, but if you add a MPVolumeView view to your app the system volume overlay goes away. Even if it is not visible:
- (void) viewDidLoad
{
[super viewDidLoad];
MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame: CGRectZero];
[self.view addSubview: volumeView];
[volumeView release];
...
}
You can use the hardware volume buttons, the setVolume method or directly interact with the control (if visible) that the overlay doesn't show up.
For iOS6 I had to set an image with alpha 0 and non-zero size to the MPVolumeView's image fields in order to get the default volume change notification to disappear.
// hide the hardware volume slider
UIImage *thumb = [[UIImage alloc] initWithCIImage:[UIImage imageNamed:#"volumeHider"].CIImage scale:0.0 orientation:UIImageOrientationUp];
MPVolumeView *hwVolume = [[MPVolumeView alloc] initWithFrame:self.frame];
[hwVolume setUserInteractionEnabled:NO];
hwVolume.showsRouteButton = NO;
[hwVolume setVolumeThumbImage:thumb forState:UIControlStateNormal];
[hwVolume setMinimumVolumeSliderImage:thumb forState:UIControlStateNormal];
[hwVolume setMaximumVolumeSliderImage:thumb forState:UIControlStateNormal];
[self addSubview:hwVolume];
This made the MPVolumeView be "visible" on the screen, but invisible to the user.
I encountered the same issue recently. Instead of adding the MPVolumeView to current view controller's view, I add it to the application's window once at the start of the app:
CGRect rect = CGRectMake(-500, -500, 0, 0);
MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:rect];
[self.window addSubview:volumeView];
This works in both iOS 7 and 8.
Swift 3
You can hide the System MPVolumeView using
override func viewDidLoad() {
super.viewDidLoad()
let volumeView = MPVolumeView(frame: CGRect.zero)
self.view.addSubview(volumeView)
}
I had success with this in iOS 6. Although it wouldn't perform well. It caused quite a bit of lag when sliding the thumbImage. I did have to take out the last 2 lines of code in order for this to work.
[volumeView release];
...
For me, on iOS 7, none of above solutions worked. Here is how I did it:
_volume = [[MPVolumeView alloc] initWithFrame: CGRectMake(-100,-100,16,16)];
_volume.showsRouteButton = NO;
_volume.userInteractionEnabled = NO;
[self.view addSubview:_volume];
[_volume release];
That is, simply set MPVolumeView's frame to an off-screen location such as (-100,-100).
I have this code set to run on my app launch:
NSRect rect = NSMakeRect(0, 0, 200, 50); //The location of the window
NSWindow *win = [[NSWindow alloc] initWithContentRect:rect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
[win setOpaque:NO];
[win setLevel:NSFloatingWindowLevel];
//[win setBackgroundColor:[NSColor clearColor]];
//or
NSView *myView = [[NSView alloc] initWithFrame: NSMakeRect(0, 0, 200, 50)];
NSButton *myButton = [[NSButton alloc] initWithFrame:NSMakeRect(10, 5, 180, 40)];
[myView addSubview: myButton];
[win setHidesOnDeactivate:NO];
[win setContentView: myView];
[win orderFront: nil];
It works as expected (displays a button in the bottom left hand corner of the screen) for about a second, then it disappears. Why is it disappearing? Memory management, or something else, and how do I fix it?
First, it is extremely odd to be building user interface without simply using Interface Builder. Can be done and there are a handful of reasons to do so, but they are pretty few and far between.
Next, that code, by itself, isn't enough to say what has gone wrong. Creating a UI programmatically begs a whole series of questions; gc or not? ... how is your run loop configured? ... do you have a properly configured app wrapper?
As Abizem said, the most obvious guess would be that you have GC enabled and you haven't rooted the window in some global variable somewhere, directly or indirectly. It "just works" in a standard Cocoa application because NSWindow instances are rooted via the Cocoa application infrastructure (the Windows menu, specifically).
Are you working with Garbage Collection?
Do you have an iVar that is holding on to win? It could be that it is being garbage collected out from under you.