I want to display a prompt to get a user's username and password.
I am doing this by displaying a UIAlertView and adding UITextFields as subviews to it.
Recently I moved my project over to XCode 4.2 and I updated all my project settings. My base SDK is set to iOS 5.0 and my deployment target is set to 4.0.
I then noticed that it was only being built for armv7 architectures and so I changed that to include armv6 as well since I would like to support the iPhone 3G as well.
After doing this I noticed that the UIAlertView wasn't moving up as before and now it was being covered by the keyboard when it was displayed. I read in the Apple documentation that you shouldn't subclass UIAlertViews (http://developer.apple.com/library/ios/#documentation/uikit/reference/UIAlertView_Class/UIAlertView/UIAlertView.html) and so I changed the way I was doing things. This didn't solve the problem.
I have noticed that I can get it to work on my phone (an iPhone 4, so armv7 architecture) by setting the Build Setting - "Build active architecture only" to YES.
I suspect that the problem is something to do with trying to build for armv6 (and indeed removing this from the architectures I am trying to build for gives me alerts which move up correctly).
I suppose I should get to my question now... I'm struggling to understand why this is behaving the way it is. I read somewhere (can't find the link now) that you don't need to move the alert up manually when adding a text field to a UIAlertView in iOS 4 and above. Since I am building for at least iOS 4 shouldn't this work on both architectures?
Also, how can I get it to build for armv6 and still have alerts which move up correctly?
Edit: Maybe I was wrong but I have noticed that I have 2 instances of my phone which I can deploy the app to. Selecting the first one and building gives me an app where the UIAlertViews don't move up when they should, but selecting the second one makes it work properly. Would post a screenshot, but I'm a new user and so I don't have the permissions necessary yet...
Oki,
I've managed to come up with a solution which works and gets the UIAlertView to be in the correct position, but I'm still not entirely sure what the root cause of the problem is.
I solved it by responding to the UIAlertViewDelegate method willPresentAlertView: and doing the following
- (void) willPresentAlertView: (UIAlertView *) alertView {
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
if (keyWindow.center.y - alertView.center.y < 0.001f) {
CGPoint center = [alertView center];
center.y = center.y - 108.0f;
[alertView setCenter:center];
}
}
It checks whether the UIAlertView is in the center of the screen and moves it up if it is (i.e. if the OS hasn't already calculated the correct position of it). Note: You would need to add a check for which specific orientation the device is in and then adjust the amount the alert is moved up accordingly if you wanted this to work for both portrait and landscape orientations.
Related
With macOS 11 Apple has introduced a new NSToolbarItem called NSSearchToolbarItem that automatically resizes to accommodate typing when the focus switches to the toolbar item.
Here Apple says this is backwards compatible with older versions of macOS: https://developer.apple.com/wwdc20/10104 (minute 11:50)
However launching my app with a NSSearchToolbarItem from interface builder on macOS 10.13 (High Sierra), crashes my app with the following Application Specific Information:
*** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '***
-[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (NSSearchToolbarItem) for key (NS.objects); the class may be
defined in source code or a library that is not linked' terminating
with uncaught exception of type NSException
Launching it on 10.15 works fine. I haven't been able to test 10.14 yet.
Update 6 July 21 by Thomas Tempelmann
It turns out that this was a bug with older Xcode 12 versions and is now fixed in Xcode 12.5.1.
I had opened a bounty, because I had a seemingly related issue with the improper sizing of NSSegmentedControls inside the toolbar when running on High Sierra, but it turns out that this is a separate issue (which can be fixed by manually resetting the toolbar's minSize and maxSize to the control's frame.size).
Therefore, the solution is to use Xcode 12.5.1 or later.
Adding the item in storyboard without any code works properly, I have just tested. So probably you have done something wrong in the code. Or it is fixed in the latest XCode.
What I have found thus far is that this works only on Catalina, even on Mojave it crashes. According to #ThomasTempelmann it is better in XCode 12.5.1, but I haven't tested that yet.
There are two ways to solve this:
1. Use Xcode 12.5.1 or later
Build the app with Xcode 12.5.1 or later, wnhich appears to have fixed the compatibility with pre-10.14 systems.
2. Add the NSSearchToolbarItem in code
If you want to still be able to open the project with older Xcode versions (ie. Xcode 11 and earlier), you cannot place the new NSSearchToolbarItem into the storyboard, or older Xcode versions will refuse to open it.
In this case, you'd keep using the classic NSToolbarItem with an NSSearchField control inside it. The challenge is to replace it with an NSSearchToolbarItem when running macOS 11 or later.
I've tried several methods, such as explicitly removing the classic search toolbar item from the toolbar and then adding the new one, and implementing the delegate function to provide it. While that worked, it caused trouble when letting the user customize the toolbar: Then the dialog would keep showing the old search item along with the new one. The only way to resolve this was to access private functions (_setAllowedItems and _setDefaultItems), but I wasn't happy with that.
I finally found this fairly solution:
Create a new custom class, let's name it SmartSearchToolbarItem, and make it a subclass of NSToolbarItem.
In the storyboard, change the class of the Search Field from NSToolbarItem to SmartSearchToolbarItem.
Add the following code to the SmartSearchToolbarItem implementation:
#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101600
#interface NSSearchToolbarItem : NSObject
- (instancetype)initWithItemIdentifier:(NSToolbarItemIdentifier)itemIdentifier;
#end
#endif
#implementation SmartSearchToolbarItem
-(instancetype)initWithItemIdentifier:(NSToolbarItemIdentifier)itemIdentifier
{
self = [super initWithItemIdentifier:itemIdentifier]; // this is necessary even if we won't use it, or we'll crash in Big Sur
Class cls = NSClassFromString(#"NSSearchToolbarItem");
if (cls) {
self = (id) [[cls alloc] initWithItemIdentifier:itemIdentifier];
}
return self;
}
Not only will this automagically replace the classic search item with the new one in Big Sur and later, it will even – and that's the part I don't really understand – still work with connected IBActions and IBOutlets. So, there's no need to copy and properties in code.
Fixing Segmented Controls
And if you happen to have segmented controls in your toolbar, then you'll also need this code to adjust their sizes as placement, as they have different widths on Big Sur vs. earlier macOS systems (10.15 and 10.14 will be fine, but if you also support 10.13, you will need this definitely):
- (void)fixSegmentedToolbarItemWidths // call this from `viewWillAppear`
{
if (#available(macOS 10.14, *)) {
// no need to set the sizes here
} else {
BOOL didChange = NO;
for (NSToolbarItem *item in self.view.window.toolbar.items) {
NSControl *control = (NSControl*)item.view;
if ([control isKindOfClass:NSSegmentedControl.class]) {
[control sizeToFit];
NSRect frame = control.frame;
const int padding = 2;
item.minSize = NSMakeSize(frame.size.width+padding, item.minSize.height);
item.maxSize = item.minSize;
didChange = YES;
}
}
if (didChange) {
[self.view.window.toolbar validateVisibleItems];
}
}
}
Sample code
Github page
I just released a game to the app store and realized I completely forgot to lock it to portrait only. I need to submit an updated version that does just that. At this point, is it enough to just go to general > deployment info and uncheck everything but Portrait and then submit this as a new build? Or do I also need to do something to the code? Please note that it's a swift app.
Simple.
Here's how you do it.
This works for both objective c and swift.
1. Open your project and go do your build settings.
Scroll down to the tab that says Deployment Info.
3. From there you can see a section called Device Orientation, This is where you need to be. Select an orientation like so.
4 Build the project and you are done!
Go to your info.plist file, Supported interface orientations, delete the keys you don't need.
There are two different plist keys for iOS in info.plist for orientation,
Supported Device Orientations
Supported Device Orientations (iPad)
Both of these must have the appropriate key value pairs in the plist.
The basic answer is: yes, that should be sufficient.
However:
Some elements of your application might not adapt well. I know I had problems with the UIImagePickerController for a landscape-only app. So watch out for functionality that you yourself haven't written and how that interacts with the restriction.
If you have code related to orientation (pushing a certain mode etc) it's probably worth testing.
You should make the change and test it before submitting. I think there may be ways of holding the release with Apple until you've had the portrait only one approved.
I'm having an issue in MKMapView in iOS 8.x.x. Application works fine iOS 7.x.x but not in iOS 8.x.x. On device it shows only annotations but no map behind.
I tried to forcefully Reset my Device as well but no luck.
I added these 2 Values in info.plist as well as it was a requirement for iOS 8 and onwards
<key>NSLocationAlwaysUsageDescription</key>
<string>Location is required to find out where you are</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location is required to find out where you are</string>
and added this lines of code in my Viewdidload.
// Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)])
{
[self.locationManager requestWhenInUseAuthorization];
//[self.locationManager requestAlwaysAuthorization];
self.myMapView.showsUserLocation = YES;
}
By adding these 2 values in info.plist and the above lines of code, I'm able to get the User's Location and annotation in showing on map for user's location but Map is Blank.
Similar to this post:
MKMapView showing blank screen in iOS 8
Had the very same thing on IOS8.3 both sim and device.
Solved by running the system Maps App (it displayed empty grid as well) for a minute till it downloaded maps. After that my MKMapView started rendering as normal.
try add the delegate methods: - (void)mapViewWillStartLoadingMap:(MKMapView *)mapView;
- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView;
- (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error;
and check the solution for you error message.
also check this solution i don't got rid of the grind but at least i got rid of the didFail error.
but seems to be an issue of iOS8 because on iOS8.3 works fine the same code.
Blimey, this Sandboxing makes me despair: I have an app that's been released on Apple's store (so, in theory, it's gone through review...), it's a slide show player - nothing too fancy - the user can drag and drop images onto an NSTableView or select through NSOpenPanel. Anyway, I thought I'd use it myself so I recompiled a copy onto my laptop and all of a sudden I'm not allowed security bookmarking:
QuickSlide(1412) deny mach-lookup com.apple.scopedbookmarksagent.xpc
The above appears whenever I drag and drop images or select them through the NSOpenPanel.
I have the following entitlements:
The code I'm using to generate the bookmarks is:
-(NSData*)genSec:(NSURL*)aURL
{
NSError *error;
NSData *secData = [aURL bookmarkDataWithOptions:(NSURLBookmarkCreationWithSecurityScope | NSURLBookmarkCreationSecurityScopeAllowOnlyReadAccess | NSURLBookmarkCreationPreferFileIDResolution)
includingResourceValuesForKeys:nil relativeToURL:nil error:&error];
if (error) {
[self setReport: [NSString stringWithFormat:#"Can't access %# due to SandBoxing",aURL]];
return nil;
}
return secData;
}
Sure enough, the report method is also fired along with the Console logging.
It's never done this before in the months I did of development. I've also tried it on my dev Mac Pro crate, tried code-signing with different or no signing, and even downloaded it from the App Store (tried twice with 2 different accounts); all with the same result. I've also used the very handy Receigen app to check the entitlements in the compiled bundle. I'm running 10.7.5. The only thing that stops it from throwing errors is if I un-check the 'enable sandboxing' option in Xcode and compile.
Argghhh. Can someone point out the blindingly obvious mistake that somehow has slipped through 2 beta-testers, me, and an App Store reviewer...?!!!!
It has to be something obvious doesn't it?
UPDATE: I got a colleague to download a fresh copy to his laptop and there was no problem with sandboxing. I'd still appreciate it if anyone can shed some light on what's happening to my installs...
Todd.
Sure enough it seems from your entitlements that it is something obivous. You need to add this one as well:
com.apple.security.files.bookmarks.app-scope
I don't know why it was working before and now isn't, but I'm positive you need to declare this entitlement for security scoped bookmarks to work.
I have upgraded my xcode to 4.5 every thing is fine until I have added to my previous solution (which I had already developed it using xcode 4.3) new UIView which has a UIImageview control I have noticed that UIImage control location in xib differ than it's location when i run my app on ios5 devices
Any Idea how to solve this issue?
I'm not sure that i've understand your question correctly.
Try to hide device's statusbar.
You can do it in a current target settings or programmatically:
[UIApplication sharedApplication] setStatusBarHidden...