I've been trying to use UIInterfaceOrientationMask in my Swift code. In Objective-C, I would use it as an enum, and when I needed to use, for example, the portrait mask, I would simply use UIPortraitOrientationMask in my code, like so:
NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
I'm not quite sure what I'm supposed to do with the documentation, and I haven't been able to find anything about a "Raw Option Set" anywhere in the tutorial book or the documentation.
As of Xcode 7, Swift Version 2.0:
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask { return UIInterfaceOrientationMask.Portrait }
Original obsolete answer below:
As of Xcode 6.2 or 6.3, or Swift version 1.2:
override func supportedInterfaceOrientations() -> Int { return Int(UIInterfaceOrientationMask.Portrait.rawValue) }
supportedInterfaceOrientations is defined to return an Int, but UIInterfaceOrientationMask is an enumeration. So, use the rawValue property of the enumeration to find its raw value, which gives a UInt. The Int() function takes the UInt as an input and returns an Int.
Use the '.' format to set / check for a value, like so:
import UIKit
var orientation : UIInterfaceOrientationMask = .Portrait
orientation = .All
if (orientation == .Landscape) {
// do something
}
You can get the same value in Swift like this: UIInterfaceOrientationMask.Portrait
Related
(This is a revised question - including answer - following on from macOS: Take emoji from characterPalette which describes the problems encountered in more detail)
Background/use case
I have an app where, instead of creating and maintaining an icon library, I let users type an emoji as a placeholder graphic. This works beautifully within the context of my app, but I am not happy with the input mechanism I use.
Problem
I would like to simplify this so I open the characterPalette, select an emoji, and display it either as the button's StringValue or in a Label (=non-editable NSTextField).
This does not seem possible. Unlike NSColorPanel or NSFontPanel, the characterPanel is not exposed to the Cocoa framework, so I cannot take its selectedValue, set its action, or catch a notification. The documentation for orderFrontCharacterPalette simply says Opens the character palette which ... is not helpful.
Attempted solutions and problems encountered
I tried to work with making my receiver the firstResponder, but unlike NSTextView, NSTextField cannot process emoji. I found a workaround using an NSTextView with an NSBox in front, making it the firstResponder, and using NSApp.orderFrontCharacterPalette(sender)but found that under various circumstances which all seem to involve an extra drawing call – setting the button's title, showing a label in SystemFont Mini size (regular size worked fine) the CharacterPalette will open (=the system menu now offers 'Hide Emoji & Symbols') without being displayed. (This persists until the application closes, even if you try to open the CharacterPalette through the regular menu/shortcut)
For the partial solution involving NSTextInputClient (the no-show seems to be a persistent bug), see answer below.
The emoji picker needs a minimal implementation of NSTextInputClient. For example a button:
class MyButton: NSButton, NSTextInputClient {
override var acceptsFirstResponder: Bool {
get {
return true
}
}
override func becomeFirstResponder() -> Bool {
return true
}
override func resignFirstResponder() -> Bool {
return true
}
func insertText(_ string: Any, replacementRange: NSRange) {
// this method is called when the user selects an emoji
if let string = string as? String {
self.title = string
}
}
func setMarkedText(_ string: Any, selectedRange: NSRange, replacementRange: NSRange) {
}
func unmarkText() {
}
func selectedRange() -> NSRange {
return NSMakeRange(0, 0)
}
func markedRange() -> NSRange {
return NSMakeRange(NSNotFound, 0)
}
func hasMarkedText() -> Bool {
return false
}
func attributedSubstring(forProposedRange range: NSRange, actualRange: NSRangePointer?) -> NSAttributedString? {
return nil
}
func validAttributesForMarkedText() -> [NSAttributedString.Key] {
return []
}
func firstRect(forCharacterRange range: NSRange, actualRange: NSRangePointer?) -> NSRect {
// the emoji picker uses the returned rect to position itself
var rect = self.bounds
rect.origin.x = NSMidX(rect)
rect.size.width = 0
return self.window!.convertToScreen(self.convert(rect, to:nil))
}
func characterIndex(for point: NSPoint) -> Int {
return 0
}
}
NSTextInputClient needs a NSTextInputContext. NSView returns a context from inputContext if the class conforms to NSTextInputClient unless isEditable is implemented and returns false. A label doesn't return a NSTextInputContext, the solution is to override inputContext:
class MyTextField: NSTextField, NSTextInputClient {
var myInputContext : NSTextInputContext?
override var inputContext: NSTextInputContext? {
get {
if myInputContext == nil {
myInputContext = NSTextInputContext(client:self)
}
return myInputContext
}
}
// and the same methods as the button, set self.stringValue instead of self.title in insertText(_:replacementRange:)
}
Willeke pointed me at NSTextInputClient which has provided the best solution so far. Apple's only example is in ObjectiveC, convoluted, and overly complex for what I was trying to do, so I am reproducing my code here.
Caveat: this is not a full implementation of NSTextInputClient, just enough to capture emoji input
I have created an NSButton subclass:
class TextReceiverButton: NSButton, NSTextInputClient {
//specific methods
func setButtonTitle(_ string: String?){
self.title = string ?? 🦊
}
//NSTextInputClient methods
func insertText(_ string: Any, replacementRange: NSRange) {
let receivedText = string as? String
setButtonTitle(receivedText)
}
func validAttributesForMarkedText() -> [NSAttributedString.Key] {
return [.font, .paragraphStyle, .writingDirection]
}
//Omitted: For anything else that wants a value, I return NSMakeRange(0, 0)/NSRect.zero or 0 as well as false for marked text and nil for attributed substring
}
(If you add the protocol to your class, it will offer stubs for the other methods)
The full set for NSAttributedString.Key is
[.font, .foregroundColor, .glyphInfo, .kern, .ligature, .link, .markedClauseSegment, .obliqueness, .paragraphStyle, .shadow, .spellingState, .strikethroughColor, .strikethroughStyle, .strokeColor, .strokeWidth, .superscript, .textAlternatives, .textEffect, .toolTip, .underlineColor, .underlineStyle, .verticalGlyphForm, .writingDirection]
(I have tested the short form with simple and composite emoji and nothing else seems necessary.)
The button's action is
#IBAction func displayEmojiInButton(_ sender: Any) {
NSApp.orderFrontCharacterPalette(self)
view.window?.makeFirstResponder(textReceiverButton)
}
Problems/Bugs
The NSTextInputClient document says 'you can subclass NSView' and Apple's code turns an NSView into a fully functional (receiving and drawing) text view class (I can't built it, but I assume it worked). So theoretically, you should be able to use the same code for NSTextField, which also ultimately inherits from NSView.
However, it turns out that NSTextField displays the 'CharacterPalette allegedly opens but never displays' bug I talked about earlier; though it does work with NSView. (I have not tested this further).
Furthermore, NSTextInputClient is not a complete replacement for NSTextView: it does not receive input from the keyboard viewer. (See Willecke's answer/comment for explanation/solution to these).
Verdict
NSApp.orderFrontCharacterPalette(self) fails 95% of the time when called from a view in the vincinity of a tab view (in splitView next to TabViewController, embedded in TabViewController), so while this code may be correct, it's also useless a lot of the time, at least under 10.13.
I'm trying to test how my App responds to different AVFoundation configurations. I'm using the techniques described in the WWDC video 'Engineering for Testability.'
I created a protocol to represent the pieces of an AVCaptureDevice that my app uses.
public protocol AVCaptureDeviceProperties: class {
//MARK: Properties I use and need to test
var position: AVCaptureDevice.Position { get }
var focusMode: AVCaptureDevice.FocusMode { get set }
var exposureMode: AVCaptureDevice.ExposureMode { get set }
var whiteBalanceMode: AVCaptureDevice.WhiteBalanceMode { get set }
//MARK: Functions I use use and need to test
func lockForConfiguration() throws
func unlockForConfiguration()
func isFocusModeSupported(_ focusMode: AVCaptureDevice.FocusMode) -> Bool
func isExposureModeSupported(_ exposureMode: AVCaptureDevice.ExposureMode) -> Bool
func isWhiteBalanceModeSupported(_ whiteBalanceMode: AVCaptureDevice.WhiteBalanceMode) -> Bool
}
I have an extension that makes AVCaptureDevice conform to my protocol.
extension AVCaptureDevice: AVCaptureDeviceProperties {
//Don't need anything because AVCaptureDevice already has implementations of all the properties and functions I use.
}
I can now make an object for myself where I can configure all the properties for different test cases. Works great!
However, I need to take it another step further and get a mock AVCaptureDeviceInput object. This object only has one initializer that takes a AVCaptureDevice but I want to be able to mock initialize with my protocol type. So far I have this:
extension AVCaptureDeviceInput {
convenience init?(device: AVCaptureDeviceProperties) throws {
guard let downcast = device as? AVCaptureDevice else {
return nil
}
try self.init(device: downcast)
}
}
However, I will never get a successful initialization with a mock object that conforms to my protocol. How to I solve this problem so I can test?
I'm developing an app with Xcode9 using Swift4 and it was originally intended for just iPads but now needs to run on phones too. I need to lock the phones to Portrait and iPads remain Portrait/Landscape.
I've done this before using the shouldautorotate function and returning true or false depending on the device as below.
override func shouldAutorotate() -> Bool {
return false
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.all
}
However, when I change the orientation it does not fire. Is this another depreciated method and if so how do I restrict the orientation now?
If your view controller is embedded into UINavigationController or UITabBarController, then this shouldAutorotate() is queried from them as this container is the topmost view controller. And after iOS updates it does not ask for contaning view controllers if they need to be rotated or not. Thus you may use your custom subclass and creat it in runtime or provide as custom calss in your storyboard:
import UIKit
class CustomNavigationController: UINavigationController {
override var shouldAutorotate: Bool {
return self.viewControllers.last?.shouldAutorotate ?? true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return self.viewControllers.last?.supportedInterfaceOrientations ?? .all
}
}
After much googling, this worked for me
https://stackoverflow.com/questions/38969419/ios-how-can-enable-or-disable-rotate-on-each-uiviewcontroller
I have a simple question: Why does Bool qualify as AnyObject
According to Apple's documentation:
"AnyObject can represent an instance of any class type.
Bool is a struct
So why does this statement pass?
let bool = true
let explicitBool: Bool = true
if (bool is AnyObject){
print("I'm an object")
}
if (explicitBool is AnyObject){
print("I'm still an object!")
}
Because it's being bridged to an NSNumber instance.
Swift automatically bridges certain native number types, such as Int
and Float, to NSNumber. - Using Swift with Cocoa and Objective-C (Swift 2.2) - Numbers
Try this:
let test = bool as AnyObject
print(String(test.dynamicType))
This behavior is due to the Playground runtime bridging to Objective-C/Cocoa APIs behind-the-scenes. Swift version 3.0-dev (LLVM 8fcf602916, Clang cf0a734990, Swift 000d413a62) on Linux does not reproduce this behavior, with or without Foundation imported
let someBool = true
let someExplicitBool: Bool = true
print(someBool.dynamicType) // Bool
print(someExplicitBool.dynamicType) // Bool
print(someBool is AnyObject) // false
print(someExplicitBool is AnyObject) // fase
Try it online.
I am using https://github.com/mrugrajsinh/MVAutocompletePlaceSearchTextField
To create a custom autocomplete UI for my app when entering addresses. However, I can't seem to conform to the protocol although everything is there. The bridging header and group is correctly handled, since I can access the methods no problem in my VC, but I can't compile since it's not conforming.
The objective C protocols are:
#protocol PlaceSearchTextFieldDelegate;
#interface MVPlaceSearchTextField : MLPAutoCompleteTextField
#property(nonatomic,strong)NSString *strApiKey;
#property(nonatomic,strong)IBOutlet id<PlaceSearchTextFieldDelegate>placeSearchDelegate;
#end
#protocol PlaceSearchTextFieldDelegate <NSObject>
-(void)placeSearch:(MVPlaceSearchTextField*)textField ResponseForSelectedPlace:(GMSPlace*)responseDict;
-(void)placeSearchWillShowResult:(MVPlaceSearchTextField*)textField;
-(void)placeSearchWillHideResult:(MVPlaceSearchTextField*)textField;
-(void)placeSearch:(MVPlaceSearchTextField*)textField ResultCell:(UITableViewCell*)cell withPlaceObject:(PlaceObject*)placeObject atIndex:(NSInteger)index;
#end
My swift code is:
extension AddAddressViewController: PlaceSearchTextFieldDelegate {
//MARK: Placesearch Textfield Delegates
func placeSearch(textField: MVPlaceSearchTextField!, responseForSelectedPlace responseDict: GMSPlace!) {
return
}
func placeSearch(textField: MVPlaceSearchTextField!, resultCell cell: UITableViewCell!, withPlaceObject placeObject: PlaceObject!, atIndex index: Int) {
}
func placeSearchWillHideResult(textField: MVPlaceSearchTextField!) {
}
func placeSearchWillShowResult(textField: MVPlaceSearchTextField!) {
}
}
It's all there. But I get the type AddAddressViewController does not conform to protocol PlaceSearch...
What else am I missing? I have properly subclassed the textfield I'm using, and created an outlet. Also properly delegated it, so it should all hit!
#ifndef Bridging_Header_h
#define Bridging_Header_h
#import <GoogleMaps/GoogleMaps.h>
#import <FBSDKLoginKit/FBSDKLoginKit.h>
#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import "MVPlaceSearchTextField.h"
#endif /* Bridging_Header_h */
EDIT:
Here I used a objective C to swift translator to directly convert the protocol methods. However, now I get a compile error saying that the arguments for the protocols are different with a suggested fix-it of reverting back to lower case...
func placeSearch(textField: MVPlaceSearchTextField, ResponseForSelectedPlace responseDict: GMSPlace) {
self.view.endEditing(true)
NSLog("SELECTED ADDRESS :%#", responseDict)
}
func placeSearchWillShowResult(textField: MVPlaceSearchTextField) {
}
func placeSearchWillHideResult(textField: MVPlaceSearchTextField) {
}
func placeSearch(textField: MVPlaceSearchTextField, ResultCell cell: UITableViewCell, withPlaceObject placeObject: PlaceObject, atIndex index: Int) {
if index % 2 == 0 {
cell.contentView.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
}
else {
cell.contentView.backgroundColor = UIColor.whiteColor()
}
}
Try this code for Swift:
#objc(placeSearch:ResponseForSelectedPlace:) func placeSearch(textField: MVPlaceSearchTextField!, responseForSelectedPlace responseDict: GMSPlace!) {
}
#objc(placeSearch:ResultCell:withPlaceObject:atIndex:) func placeSearch(textField: MVPlaceSearchTextField!, resultCell cell: UITableViewCell!, withPlaceObject placeObject: PlaceObject!, atIndex index: Int) {
}
#objc(placeSearchWillShowResult:) func placeSearchWillShowResult(textField: MVPlaceSearchTextField!) {
}
#objc(placeSearchWillHideResult:) func placeSearchWillHideResult(textField: MVPlaceSearchTextField!) {
}
Have you done this ? In Build Settings, search swift Compiler, install Objective-C Compatibility Header is YES. The Objective-C Bridging Header is your_project/******-bridging-Header.h,such as this, Test/Test-bridging-Header.h,try to build the app to ensure that there is no error in this.
Hey try this one for latest swift 2.0
just download project and open pod file and write pod 'GoogleMaps' and save it.
install pod with terminal and enjoy!!
RKAutoCompletePlaceSearch