gpt4 book ai didi

ios - UINavigationBar 约束问题中的奇怪 UITextField 仅在 iOS 10 或更高版本上

转载 作者:行者123 更新时间:2023-11-28 08:20:54 27 4
gpt4 key购买 nike

在我将 iPhone 更新到 iOS 10 后,我注意到 UINavigationBar 中的 UITextField 这个非常奇怪的约束问题出现在我的应用程序中iOS 提示。我认为将我的 Xcode 项目更新为 swift 3 会修复它,但问题仍然存在。出于某种原因,这不是 iOS 9 及更低版本的问题。

Please download my app Tipped... it's free and you will be able to see the issue described below.

1: 当我启动我的应用程序并点击标签栏到 viewController 时,导航栏中出现文本字段约束问题,我得到 this

2: 当我按另一个选项卡栏选项(如主页)点击搜索选项卡栏选项(导航回有问题的页面)时,我得到 this

3: 此外,当我在出现约束问题的搜索页面上点击其中一个分割按钮时。约束问题将再次出现,并且文本字段将过于靠右。

我已尝试使用以下代码来尝试解决问题,但似乎没有任何效果。真的卡在这里任何帮助都会很棒。

override func viewWillAppear(_ animated: Bool) {
// searchTextField.becomeFirstResponder()
print("viewWillAppear: searchPageViewController")
navigationView.setNeedsLayout()
navigationView.updateConstraintsIfNeeded()
searchTextField.updateConstraints()
searchTextField.setNeedsLayout()
}

下面是我遇到问题的 View Controller 的代码。

class SearchPageViewController: UIPageViewController, UISearchBarDelegate, UISearchDisplayDelegate, UIPageViewControllerDataSource, UIPageViewControllerDelegate, UIScrollViewDelegate, UITextFieldDelegate {

//%%% customizeable button attributes
let X_BUFFER:CGFloat = 0.0; //%%% the number of pixels on either side of the segment
let Y_BUFFER:CGFloat = 0.0; //%%% number of pixels on top of the segment
let HEIGHT:CGFloat = 44.0; //%%% height of the segment

//%%% customizeable selector bar attributes (the black bar under the buttons)
let BOUNCE_BUFFER:CGFloat = 10.0; //%%% adds bounce to the selection bar when you scroll
let ANIMATION_SPEED:CGFloat = 0.2; //%%% the number of seconds it takes to complete the animation
let SELECTOR_Y_BUFFER:CGFloat = 40.0; //%%% the y-value of the bar that shows what page you are on (0 is the top)
let SELECTOR_HEIGHT:CGFloat = 4.0; //%%% thickness of the selector bar

let X_OFFSET:CGFloat = 0.0; //%%% for some reason there's a little bit of a glitchy offset. I'm going to look for a better workaround in the future

var navigationView = UIView()
var containerView = UIView()

var buttonText:NSArray = []
var pageScrollView:UIScrollView!
var currentPageIndex:Int!
var selectionBar = UIView()

var buttonOneTap:Bool = false
var buttonTwoTap:Bool = false

fileprivate var _controllerEnum: ControllerEnum = ControllerEnum()
fileprivate var _dict: [UIViewController: ControllerEnum] = [:]

var editView = UIView()
// var delegate: ViewControllerDelegate? = nil
// var userList = NSMutableArray()
// var searchString = String()
// var viewControllerArray:NSMutableArray = NSMutableArray()
var blogSearchCollectionViewController:BlogSearchCollectionViewController!
// var pageViewController: UIPageViewController!
var pageTitles: NSArray!
var pageImages: NSArray!

let searchController = UISearchController(searchResultsController: nil)

@IBOutlet weak var searchBarView: UIView!
@IBOutlet weak var searchTextField: UITextField!
//Stretching the searchTextField full width of navbar
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
widenTextField()
}

func widenTextField() {



let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 8, height: 0))
self.searchTextField.leftView = paddingView
self.searchTextField.leftViewMode = .always

let paddingViewRight = UIView(frame: CGRect(x: 0, y: 0, width: 8, height: 0))
self.searchTextField.rightView = paddingViewRight
self.searchTextField.rightViewMode = .always

searchBarView.frame = CGRect(x: 16, y: 5, width: self.view.frame.width, height: 34)
// var frame:CGRect = self.searchTextField.frame
// frame.size.width = self.view.frame.width
// self.searchTextField.frame = CGRectMake(16, 5, self.view.frame.width, 33)
}

// TextFieldDelegates
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// textField.resignFirstResponder()
handleTap(editView)

if currentPageIndex == 0 {

let vc = self.viewControllerAtIndex(currentPageIndex) as BlogSearchCollectionViewController
// vc.loadUsers(textField.text.lowercaseString)
vc.searchText = textField.text!.lowercased()
vc.loadObjects()
vc.showActivityIndicator()
let viewControllers = NSArray(object: vc)

setViewControllers(viewControllers as? [UIViewController], direction: .forward, animated: false, completion: nil)
} else if currentPageIndex == 1 {

let vc = self.viewControllerAtIndexTwo(currentPageIndex) as PhotoSearchController
vc.search(textField.text!.lowercased())

vc.showActivityIndicator()
let viewControllers = NSArray(object: vc)

setViewControllers(viewControllers as? [UIViewController], direction: .forward, animated: false, completion: nil)
}
return true
}

// var lastTextFieldEdit:String!

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
showEditView()
if let text = textField.text {
if text.characters.count > 0 {
DispatchQueue.main.async{
textField.selectAll(nil)
}
}
}
searchTextField.textAlignment = NSTextAlignment.left

return true
}

func textFieldDidBeginEditing(_ textField: UITextField) {
print(textField)
}

override func viewWillAppear(_ animated: Bool) {
// searchTextField.becomeFirstResponder()
print("viewWillAppear: searchPageViewController")

}

override func viewDidAppear(_ animated: Bool) {
}

override func viewDidLoad() {
super.viewDidLoad()
self.setupSegmentButtons()
self.setupPage()

currentPageIndex = 0

// self.navigationItem.titleView = searchTextField
}

//Mark: SearchBar stuff
func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
// searchController.searchBar.showsCancelButton = true
return true
}


func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool {
searchController.searchBar.showsCancelButton = true
// for subView in searchController.view.subviews {
// if let dimView = subView as? UIView {
// dimView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
// }
// }

return true
}

func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
for subView in searchController.view.subviews {
}
}

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {

print("hithere")
searchController.searchBar.showsCancelButton = true

// searchController.dimsBackgroundDuringPresentation = false

print("searchController.view.subviews1: - \(searchController.searchBar.subviews)")
for subView in searchController.view.subviews {
print("searchController.view.subviews2: - \(searchController.view.subviews)")

if let dimView = subView as? UIView {
dimView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.0)
}
}
// searchController.dismissViewControllerAnimated(true, completion: nil)

if currentPageIndex == 0 {

let vc = self.viewControllerAtIndex(currentPageIndex) as BlogSearchCollectionViewController
// vc.loadUsers(searchBarString.lowercaseString)
let viewControllers = NSArray(object: vc)

setViewControllers(viewControllers as? [UIViewController], direction: .forward, animated: false, completion: nil)
} else if currentPageIndex == 1 {

let vc = self.viewControllerAtIndexTwo(currentPageIndex) as PhotoSearchController
vc.search(searchBarString.lowercased())
let viewControllers = NSArray(object: vc)

setViewControllers(viewControllers as? [UIViewController], direction: .forward, animated: false, completion: nil)
}
}
var searchBarString:String!

func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {

searchController.searchBar.showsCancelButton = true
let uiButton = searchController.searchBar.value(forKey: "cancelButton") as! UIButton
uiButton.setTitle("Cancel", for: UIControlState())
uiButton.setTitleColor(UIColor.black, for: UIControlState())
uiButton.titleLabel!.font = UIFont(name: "Helvetica Neue", size: 17)

}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchBarString = searchText
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}

func setupSegmentButtons() {
navigationView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: HEIGHT))
navigationView.backgroundColor = UIColor.brown

let numControllers = 2

// if buttonText == NSNotFound {
buttonText = NSArray(objects: "BLOGS", "TIPS")
// }

let buttonOne:UIButton = UIButton(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width/2, height: HEIGHT))
let buttonTwo:UIButton = UIButton(frame: CGRect(x: self.view.frame.size.width/2, y: 0, width: self.view.frame.size.width/2, height: HEIGHT))

navigationView.addSubview(buttonOne)
navigationView.addSubview(buttonTwo)

buttonOne.tag = 0
buttonOne.backgroundColor = UIColor.white
buttonOne.addTarget(self, action: #selector(SearchPageViewController.tapSegmentButtonAction(_:)), for: UIControlEvents.touchUpInside)
buttonOne.setTitle(buttonText[0] as? String, for: UIControlState())
buttonOne.setTitleColor(UIColor.black, for: UIControlState())
buttonOne.titleLabel!.font = UIFont(name: "Interstate-Bold", size: 17)!

buttonTwo.tag = 1
buttonTwo.backgroundColor = UIColor.white
buttonTwo.addTarget(self, action: #selector(SearchPageViewController.tapSegmentButtonAction(_:)), for: UIControlEvents.touchUpInside)
buttonTwo.setTitle(buttonText[1] as? String, for: UIControlState())
buttonTwo.setTitleColor(UIColor.black, for: UIControlState())
buttonTwo.titleLabel!.font = UIFont(name: "Interstate-Bold", size: 17)

self.view.addSubview(navigationView)
self.setupSelector()
}

func setupSelector() {
selectionBar = UIView(frame: CGRect(x: X_BUFFER-X_OFFSET, y: SELECTOR_Y_BUFFER,width: (self.view.frame.size.width-2*X_BUFFER)/2, height: SELECTOR_HEIGHT))
selectionBar.backgroundColor = UIColor(red: 251/255, green: 73/255, blue: 90/255, alpha: 1.0)
// selectionBar.alpha = 1
navigationView.addSubview(selectionBar)
}

func setupPage() {

// self.navigationItem.titleView = searchTextField

view.backgroundColor = UIColor.white
//TextFieldStuff
searchTextField.delegate = self
searchTextField.placeholder = "Search for blogs"
searchTextField.textAlignment = NSTextAlignment.center
searchTextField.autocorrectionType = .no

//TextField is editing translucent view
editView.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.6)
editView.frame = CGRect(x: 0, /*self.navigationController!.navigationBar.frame.size.height + 20 +*/ y: HEIGHT, width: self.view.frame.size.width, height: self.view.frame.size.height - (self.navigationController!.navigationBar.frame.size.height + 20 + HEIGHT))
self.view.addSubview(editView)
editView.isHidden = true

//tapGesture
editView.isUserInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(SearchPageViewController.handleTap(_:)))
editView.addGestureRecognizer(tapGesture)

let pageControl = UIPageControl()
pageControl.backgroundColor = UIColor.white

self.pageTitles = NSArray(objects: "Explore", "Today Widget")
self.pageImages = NSArray(objects: "page1", "page2")

//PageViewControllers
delegate = self
dataSource = self

let vc = self.viewControllerAtIndex(0) as BlogSearchCollectionViewController
// vc.loadUsers("")
vc.searchText = ""
vc.loadObjects()

vc.showActivityIndicator()
let viewControllers = NSArray(object: vc)

setViewControllers(viewControllers as? [UIViewController], direction: UIPageViewControllerNavigationDirection.forward, animated: true, completion: nil)
print("pageSetUp:- \(currentPageIndex)")
self.syncScrollView()
}

func handleTap(_ sender : UIView) {
// searchController.resignFirstResponder()
searchTextField.resignFirstResponder()
searchTextField.textAlignment = NSTextAlignment.center

UIView.animate(withDuration: 0.3, animations: { () -> Void in
self.editView.alpha = 0

}, completion: { (success:Bool) -> Void in
if success {
self.editView.isHidden = true
}
})
// UIView.animateWithDuration(0.5, animations: { () -> Void in
// self.editView.alpha = 0
// })
print("Tap Gesture recognized")
}

func showEditView() {

editView.alpha = 0
editView.isHidden = false

UIView.animate(withDuration: 0.3, animations: { () -> Void in
self.editView.alpha = 0.6
})
}

func viewControllerAtIndex(_ index: Int) -> BlogSearchCollectionViewController {

let vc: BlogSearchCollectionViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "BlogSearchCollectionViewController") as! BlogSearchCollectionViewController

return vc
}

func viewControllerAtIndexTwo(_ index: Int) -> PhotoSearchController {
let vc: PhotoSearchController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PhotoSearchController") as! PhotoSearchController
// currentPageIndex = vc.pageIndex

return vc
}

func syncScrollView() {

let x = self.view.subviews
var view:UIView!

for view in x {

if view.isKind(of: UIScrollView.self) {
pageScrollView = view as! UIScrollView
pageScrollView.delegate = self
}
}
}
//%%% when you tap one of the buttons, it shows that page,
//but it also has to animate the other pages to make it feel like you're crossing a 2d expansion,
//so there's a loop that shows every view controller in the array up to the one you selected
//eg: if you're on page 1 and you click tab 3, then it shows you page 2 and then page 3

func tapSegmentButtonAction(_ button:UIButton) {

if buttonOneTap == false && buttonTwoTap == false {

let tempIndex:Int = self.currentPageIndex
//%%% check to see if you're going left -> right or right -> left
// println("buttonTag + tempIndex \(button.tag) \(tempIndex)")
if button.tag > tempIndex {
//%%% scroll through all the objects between the two points
buttonOneTap = true
// var i = tempIndex+1
// for i in stride(from:i, through:(button.tag), by: 1) {
for tempIndex in 0..<button.tag {
// for var i = tempIndex+1; i<=button.tag; i += 1 {
// println(i)

let vc: PhotoSearchController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PhotoSearchController") as! PhotoSearchController
let viewControllers = NSArray(object: vc)

setViewControllers(viewControllers as? [UIViewController] /*[getController(.Debts)!]viewControllerArray.objectAtIndex(i) as! [AnyObject]*/, direction: UIPageViewControllerNavigationDirection.forward, animated: true, completion: { (success:Bool) -> Void in
//%%% if the action finishes scrolling (i.e. the user doesn't stop it in the middle),
//then it updates the page that it's currently on

if success == true {
self.buttonOneTap = false
self.updateCurrentPageIndex(1)
// self.searchController.searchBar.placeholder = "Search for tips"

// let txtField = self.navigationItem.titleView as! UITextField
// txtField.placeholder = "Search for tips"
self.searchTextField.placeholder = "Search for tips"
}
})
}
//%%% this is the same thing but for going right -> left

} else if button.tag < tempIndex {

buttonTwoTap = true
// var i = tempIndex+1
// for i in stride(from:i, through:(button.tag), by: -1) {
// for var i = tempIndex-1; i >= button.tag; i -= 1 {
for tempIndex in (0...button.tag).reversed() {

// println(i)

let vc: BlogSearchCollectionViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "BlogSearchCollectionViewController") as! BlogSearchCollectionViewController
// vc.loadUsers("")
vc.searchText = ""
vc.loadObjects()

vc.showActivityIndicator()
let viewControllers = NSArray(object: vc)

setViewControllers(viewControllers as? [UIViewController] /*[getController(_controllerEnum)!] viewControllerArray.objectAtIndex(i) as! [AnyObject]*/, direction: UIPageViewControllerNavigationDirection.reverse, animated: true, completion: { (success:Bool) -> Void in
if success == true {

self.buttonTwoTap = false
self.updateCurrentPageIndex(0)
// self.searchController.searchBar.placeholder = "Search for blogs"
// let txtField = self.navigationItem.titleView as! UITextField
// txtField.placeholder = "Search for blogs"
self.searchTextField.placeholder = "Search for blogs"
}
})
}
}
}
}

func updateCurrentPageIndex(_ newIndex:Int) {
self.currentPageIndex = newIndex
}
//%%% makes sure the nav bar is always aware of what page you're on
//in reference to the array of view controllers you gave
//%%% method is called when any of the pages moves.
var xFromCenter:CGFloat!
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// println(self.currentPageIndex)

//It extracts the xcoordinate from the center point and instructs the selection bar to move accordingly
xFromCenter = self.view.frame.size.width-scrollView.contentOffset.x
print(xFromCenter)

// if xFromCenter > 0 && currentPageIndex == 0 {
// updateCurrentPageIndex(0)
// }
// println(self.currentPageIndex)


var a = X_BUFFER + selectionBar.frame.size.width
var b = CGFloat(currentPageIndex) - X_OFFSET

let xCoor = selectionBar.frame.size.width * CGFloat(self.currentPageIndex)
// println(xCoor)
//%%% checks to see what page you are on and adjusts the xCoor accordingly.
//i.e. if you're on the second page, it makes sure that the bar starts from the frame.origin.x of the
//second tab instead of the beginning

selectionBar.frame = CGRect(x: xCoor - xFromCenter/2, y: selectionBar.frame.origin.y, width: selectionBar.frame.size.width, height: selectionBar.frame.size.height)
}

// MARK: - Page View Controller Data Source
var vcOne:BlogSearchCollectionViewController!

func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
var index:Int = currentPageIndex

if index == NSNotFound || index == 0 {
return nil
}
// println(currentPageIndex)

index -= 1

let vcOne = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "BlogSearchCollectionViewController") as! BlogSearchCollectionViewController
// currentPageIndex = vc.pageIndex
// println("actaulIndexBlogSearchCollectionViewController: - \(actaulIndex)")

return vcOne
// return getController(_dict[viewController]!.prevIndex())
}

var vcTwo:PhotoSearchController!

func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {

var index:Int = currentPageIndex

if index == NSNotFound {
return nil
}
index += 1

if index == buttonText.count {
return nil
}


vcTwo = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PhotoSearchController") as! PhotoSearchController
// currentPageIndex = vc.pageIndex
// if vc.pageIndex == 1 && index == 0 {
// return vc
// }
// println("actaulIndexPhotoSearchController: - \(actaulIndex)")

return vcTwo
// return getController(_dict[viewController]!.nextIndex())
}

var actaulIndex:Int!

func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {

print("finished: - \(finished)")
print("completed: - \(completed)")

if finished == true && completed == true {
print("currentPageIndex: - \(currentPageIndex)")
if finished == true && completed == true && currentPageIndex == 0 && xFromCenter < 0 {
print("hi")
// searchController.searchBar.placeholder = "Search for tips"
// let txtField = self.navigationItem.titleView as! UITextField
// txtField.placeholder = "Search for tips"
searchTextField.placeholder = "Search for tips"

updateCurrentPageIndex(1)
} else if finished == true && completed == true && currentPageIndex == 1 && xFromCenter > 0 {
print("hi 2")
// searchController.searchBar.placeholder = "Search for blogs"
// let txtField = self.navigationItem.titleView as! UITextField
// txtField.placeholder = "Search for blogs"
searchTextField.placeholder = "Search for blogs"

updateCurrentPageIndex(0)
}
}
}

}

最佳答案

我想通了。在 widen textfield 函数中。我需要更改以下行:

searchBarView.frame = CGRect(x: 16, y: 5, width: self.view.frame.width, height: 34)

searchBarView.frame = CGRect(x: 8, y: 5, width: self.view.frame.width - 16, height: 34)

关于ios - UINavigationBar 约束问题中的奇怪 UITextField 仅在 iOS 10 或更高版本上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41329166/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com