I have an application with 2 views.
On the first view, the user enter a login, hits on search button.
The application retrieves through an api information about the login,
is redirected on the second view where it displays information about the login.There is a back button on the second view to go back on the first view to be able to search a different login
In the second view, I treat both cases (Landscape/Portrait)
What happens is the following : first time I enter the login, Portrait and landscape cases are well treated on the result view.
When I go back and search a new login, It will only display the mode in which you entered the second time (if you entered in portrait mode, it will
only display in portrait mode, the same with landscape) Is there something that I should be doing ?
here is the code for the first view :
var login = ""
class FirstViewController: UIViewController {
#IBOutlet weak var Input: UITextField!
#IBAction func sendlogin(_ sender: UIButton) {
if let text = Input.text, !text.isEmpty {
login = text
performSegue(withIdentifier: "callaffiche", sender: self)
return
} else {
return
}
}
here is the code for the second view (I will only post viewDidLoad, the back button creation along its function and the creation of the imageuser as there are many objects. But all of them are created with the same principle ) AfficheElemts calls the creation of every single object( ButtonBackAffiche, ImageAffiche are called within AfficheElements
override func viewDidLoad() {
super.viewDidLoad()
print("ds viewdidload")
let qos = DispatchQoS.userInitiated.qosClass
let queue = DispatchQueue.global(qos: qos)
queue.sync {
self.aut.GetToken(completionHandler: { (hasSucceed) in
if hasSucceed {
print("good")
DispatchQueue.main.async {
self.AfficheElements()
}
} else {
print("bad")
}
})
}
}
func ButtonBackAffiche () {
let button = UIButton()
button.restorationIdentifier = "ReturnToSearch"
button.setTitle("Back", for: .normal)
button.setTitleColor(UIColor.black, for: .normal)
button.isEnabled = true
button.addTarget(self, action: #selector(ReturnToSearch(button:)), for: .touchUpInside)
if UIDevice.current.orientation.isPortrait {
button.frame = CGRect (x:CGFloat(180),y:CGFloat(600),width:50,height:30)
} else {
button.frame = CGRect (x:CGFloat(350),y:CGFloat(360),width:50,height:30)
}
self.view.addSubview(button)
}
func ImageAffiche () {
//Get image (Data) from URL Internet
let strurl = NSURL(string: image_url)!
let dtinternet = NSData(contentsOf:strurl as URL)!
let bongtuyet:UIImageView = UIImageView ()
if UIDevice.current.orientation.isPortrait {
print("portrait ds imageview")
bongtuyet.frame = CGRect (x:10,y:80,width:30,height:30)
} else {
print("landscape ds imageview")
bongtuyet.frame = CGRect (x:CGFloat(200),y:CGFloat(80),width:90,height:120)
}
bongtuyet.image = UIImage(data:dtinternet as Data)
self.view.addSubview(bongtuyet)
}
func ReturnToSearch(button: UIButton) {
performSegue(withIdentifier: "ReturnToSearch", sender: self)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
print("ds viewwilltransition")
if UIDevice.current.orientation.isPortrait {
print("portrait")
} else {
print("landscape")
}
while let subview = self.view.subviews.last {
subview.removeFromSuperview()
}
AfficheElements()
}
One last thing, I have put traces in the code and the creation of the objects, it goes through the right portion of the code but does not display the objects at the right locations.
Thanks #Spads for taking time to help me.
I finally figured it out. I was not calling the function AfficheElements
int the main queue.
DispatchQueue.main.async {
self.AfficheElements()
}
in viewWillTransition solved it.
Related
According to https://developer.dji.com/api-reference/ios-uilib-api/Widgets/PreFlightStatusWidget.html:
"Tapping on status text will toggle between show and hide DUXPreflightChecklistController."
When I tap on the status text in the widget, the DUXPreflightChecklistController is not shown. Also, if I manually show the DUXPreflightChecklistController, there is a close button in the top right corner of the panel but tapping it does not hide the panel.
What is the proper way to configure this panel?
I'm using DJISDK 4.7.1 and DJIUXSDK 4.7.1 with Swift and iOS 12/xCode 10.0.
To provide a bit more detail, I do not want to use the Default Layout but I am using DUXStatusBarViewController. That is embedded in a UIView across the top of my app. I cannot find any properties for that controller that would allow me to hook it up to my instance of DUXPreflightChecklistController, which is also embedded in a UIView.
For: DUXPreflightChecklistController
I'd just solved that
var preflightChecklistController: DUXPreflightChecklistController!
weak var preFlightTableView: UITableView!
private var compassItemIndex: Int = -1
private var storageItemIndex: Int = -1
override func viewDidLoad() {
super.viewDidLoad()
preflightChecklistController = DUXPreflightChecklistController()
addChild(preflightChecklistController)
}
func renderChecklist() {
if let checklistVC = preflightChecklistController {
for subview in checklistVC.view.subviews {
if subview.isKind(of: UITableView.self) {
if let tableView = subview as? UITableView {
self.view.addSubview(tableView)
preFlightTableView = tableView
}
}
}
guard let checklistManager = checklistVC.checklistManager else { return }
let itemList = checklistManager.preFlightChecklistItems
for (index, item) in itemList.enumerated() {
if let _ = item as? DUXStorageCapacityChecklistItem {
storageItemIndex = index
}
if let _ = item as? DUXCompassChecklistItem {
compassItemIndex = index
}
}
preFlightTableView.reloadData()
checklistManager.startCheckingList()
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
renderChecklist()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
guard preFlightTableView != nil else { return }
if let compassCell = preFlightTableView.cellForRow(at: IndexPath(item: compassItemIndex, section: 0)) {
for view in compassCell.subviews {
if let button = view as? UIButton, button.titleLabel?.text == "Calibrate" {
button.addTarget(self, action: #selector(doActionForSpecifiedBTN(sender:)), for: .touchUpInside)
break
}
}
}
if let storageCell = preFlightTableView.cellForRow(at: IndexPath(item: storageItemIndex, section: 0)) {
for view in storageCell.subviews {
if let button = view as? UIButton, button.titleLabel?.text == "Format" {
button.addTarget(self, action: #selector(doActionForSpecifiedBTN(sender:)), for: .touchUpInside)
break
}
}
}
}
#objc func doActionForSpecifiedBTN(sender: UIButton) {
guard let btnTitle = sender.titleLabel else { return }
switch btnTitle.text {
case "Calibrate":
// your func goes here
case "Format":
// your func goes here
default:
break
}
}
I have a simple media player and I'm trying to make it change the artwork image as the songs change. With the code I have now it will display the artwork when you hit play but when I hit the next button to skip to the next item it stays the same unless you hit another button.
How can I make the UIImageView image change as the song media item changes?
import UIKit
import MediaPlayer
class ViewController: UIViewController {
#IBOutlet weak var coverImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
createQueue()
}
func showArt(){
coverImageView.image =
myMediaPlayer.nowPlayingItem?.artwork!.image(at: CGSize.init(width: 500, height: 500))
coverImageView.isUserInteractionEnabled = true
}
#IBAction func playButton(_ sender: UIButton) {
togglePlay(on: sender)
showArt()
}
#IBAction func backButton(_ sender: UIButton) {
back()
}
#IBAction func nextButton(_ sender: UIButton) {
skip()
}
}
My other functions are as followed:
import MediaPlayer
let myMediaPlayer = MPMusicPlayerApplicationController.systemMusicPlayer
let playDrake = MPMediaPropertyPredicate(value: "Drake", forProperty: MPMediaItemPropertyArtist, comparisonType: MPMediaPredicateComparison.equalTo)
let myFilterSet: Set<MPMediaPropertyPredicate> = [playDrake]
func createQueue() {
let drakeQuery = MPMediaQuery(filterPredicates: myFilterSet)
myMediaPlayer.setQueue(with: drakeQuery)
}
func skip() {
myMediaPlayer.skipToNextItem()
}
func back() {
if myMediaPlayer.currentPlaybackTime > 0.05 {
myMediaPlayer.skipToPreviousItem()
} else if myMediaPlayer.currentPlaybackTime < 0.05 {
myMediaPlayer.skipToBeginning()
} else {
//do nothing
}
}
func togglePlay(on: UIButton) {
if myMediaPlayer.playbackState.rawValue == 2 || myMediaPlayer.playbackState.rawValue == 0 {
on.setTitle("Pause", for: UIControlState.normal)
myMediaPlayer.play()
} else if myMediaPlayer.playbackState.rawValue == 1{
on.setTitle("Play", for: UIControlState.normal)
myMediaPlayer.pause()
} else {
// do nothing
}
}
Try loading the image asynchronously
DispatchQueue.global(qos: .background).async {
myMediaPlayer.nowPlayingItem?.artwork!.image(at: CGSize.init(width: 500, height: 500))
}
I wrote an extension that allows me to show a refreshControl on a regular tableView in a UIViewController. The code below works perfectly on the viewDidLoad() and when pull to refresh.
Extension:
extension UITableView
{
func findRefreshControl () -> UIRefreshControl?
{
for view in subviews
{
if view is UIRefreshControl
{
print("The refresh control: \(view)")
return view as? UIRefreshControl
}
}
return nil
}
func addRefreshControlWith(sender: UIViewController, action: Selector, view: UIView)
{
guard findRefreshControl() == nil else { return }
let refreshControl = UIRefreshControl()
refreshControl.addTarget(sender, action: action, for: UIControlEvents.valueChanged)
view.addSubview(refreshControl)
}
func showRefreshControlWith(attributedTitle: String? = nil)
{
findRefreshControl()?.attributedTitle = NSAttributedString(string: attributedTitle!)
findRefreshControl()?.beginRefreshing()
}
func hideRefreshControl ()
{
findRefreshControl()?.endRefreshing()
}
}
Callees in ViewController: (Triggerend by observe events)
private func showLoader()
{
tableView.showRefreshControlWith(attributedTitle: "Loading Profile".localized())
}
private func hideLoader()
{
tableView.hideRefreshControl()
}
Observers:
_ = presenter.profilePictureUploadingPending.skip(first: 1).observeNext { _ in self.showLoader() }
_ = presenter.profilePictureUploaded.skip(first: 1).observeNext { _ in self.hideLoader() }
However, when I enter the UIImagePicker to upload a photo in my app and return back to the viewController it should trigger the the spinning process again until the photo is uploaded successfully.
I debugged my code and it is firing up the methods but the spinner disappeared from the view hierarchy subviews and is not showing up...
I am not sure how i can solve this issue but I really appreciate any help from you guys!
Thanks,
Kevin.
Solved with following solution:
private func showLoader()
{
DispatchQueue.global(qos: .default).async {
DispatchQueue.main.async {
self.tableView.contentOffset.x = 1
self.tableView.contentOffset.y = -81
self.tableView.showRefreshControlWith(attributedTitle: "LOADING_PROFILE".localized())
}
}
}
I have a function which should "toggle" a bar button item by changing between 2 images.
class Buttons {
func ToggleBarButton(button : UIBarButtonItem, name : String, location : BarButtonLocation, isEnabled : Bool, viewController : UIViewController) {
var iconName = name
if (!isEnabled) {
iconName += "EnabledIcon"
} else {
iconName += "DisabledIcon"
}
let newIcon = UIImage(named: iconName)
let newButton = UIBarButtonItem(image: newIcon, style: .Plain, target: self, action: button.action);
switch location {
case BarButtonLocation.Left:
viewController.navigationItem.leftBarButtonItem = newButton;
viewController.navigationItem.leftBarButtonItem?.tintColor = UIColor.blackColor();
case BarButtonLocation.SecondLeft:
viewController.navigationItem.leftBarButtonItems?[1] = newButton
viewController.navigationItem.leftBarButtonItems?[1].tintColor = UIColor.blackColor()
default:
return;
}
}
}
I also have a view controller class, in which there is the action of the bar button item.
class GradesViewController: UIViewController {
var isFilterEnabled = false
var isViewEnabled = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func filterButton_Pressed(sender: UIBarButtonItem) {
Buttons().ToggleBarButton(sender, name : "Filter", location: BarButtonLocation.Left, isEnabled: isFilterEnabled, viewController: self);
isFilterEnabled = !isFilterEnabled;
}
#IBAction func viewButton_Pressed(sender: UIBarButtonItem) {
Buttons().ToggleBarButton(sender, name : "View", location: BarButtonLocation.SecondLeft, isEnabled: isViewEnabled, viewController: self);
isViewEnabled = !isViewEnabled;
}
}
On first press it successfully changes the image to the enabled form, but on second press it doesn't do anything (press event doesn't even fire). I checked, and button.action is correctly identified as "filterButton_Pressed:". What's the problem, or is there an easier way to do this? Thanks for the answer in advance.
Put the break statement after each case and try.
And also remove the semi colons.
I just realized the problem was that I copied the code from the view controller to the button class, and didn't change target: self to target: viewController. But thanks for all the answers anyways...
In my app there is a webView with default website google. I see in some apps on any webpage there is an address bar on top so user can enter new website address any time. How can we do that? Thanks!
Put your web view inside a UINavigationView, then set its headerView to be a UITextField. Something like this:
class WebsiteViewController: UIViewController, UITextFieldDelegate {
var addressField: UITextField? = nil
override public func viewDidLoad() {
super.viewDidLoad()
addressField = ({
let field = UITextField()
field.autocorrectionType = UITextAutocorrectionType.No
field.delegate = self
field.addTarget(self, action: "addressChanged:", forControlEvents: .EditingChanged)
field.addTarget(self, action: "addressEditEnded:", forControlEvents: .EditingDidEnd)
field.sizeToFit()
return field
})()
}
override public func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationItem.titleView = addressField
}
#IBAction func addressChanged(sender: UITextField) {
if let newString = addressField?.text where newString != searchString && newString.characters.count != 1 {
// do any filtering you might want to
}
}
#IBAction func addressEditEnded(sender: UITextField) {
// trigger the page load
}
}
That should cover the essentials.