Writing better Swift code - swift

The title is on how to write better Swift code but, my real question is really what is better if I create a function, then call it when the button is clicked vs I write what I want to happen once the button is clicked .
Eg.
var thing = 0
func hi(){
// Do something
thing++
}
#IBAction func somethingHi(sender: AnyObject) {
println(hi)
}
vs
var thing = 0
#IBAction func othersomethingHI(sender: AnyObject) {
thing++
println(thing)
}
I know both do the same thing but, is one "better" written than the other?

If an IBAction does something that you might want to do at some other time then it should call a function that performs that action, so that "others" can effect the same thing without duplicating code. If not, implement it solely in the action.

If you're code is short and won't be reused, you can just put it inside the #IBAction func function.

Related

Value of type 'NSButton' has no member 'Clicked' | Xcode error with button

I'm making a browser using Swift and made a refresh button, I don't know much about any coding but most about Lua. Used a tutorial for most of this, I've done everything neccessary at this point and have an image button. Keep getting this error: Value of type 'NSButton' has no member 'clicked'I need to use Swift 5 for this- Here's the code:
#IBAction func didrefreshButtonTapped (_ sender: NSButton) {
if sender.clicked == 0 {
webView.reload()
}else {
webView.reload()
}
}
```
FIGURED IT OUT DON'T NEED THIS TO BE ANSWERED! I just assigned the button in FirstResponder to reload.

Why text field can not be refresh in a method?

I try to refresh a text field to provide information. But i realize i can not update this display till the code ends. I tried to make it async but no success. Can someone to explain me with a simple example?
I show you this simple code. The text field named txtLog only show "Nothing else" when count of i (100000) is ended. Why?
#IBAction func elimineDoublons(_ sender: Any) {
DispatchQueue.main.async {
self.txtLog.stringValue="Nothing else"
}
for i in 0...100000{
print(i)
}
}
Can you explain me or show me a simple example? Please...
PS: Sorry for my english, i'm french...
You get this behaviour because your for loop is running in the main queue: #IBAction functions are always running in the main queue. So, you are blocking the queue in which you want to run self.txtLog.stringValue="Nothing else". The UI is always updated in the main thread, so GCD (Grand Central Dispatch) waits for the end of your loop before running this code.
Keep in mind that UI components can only be properly manipulated on the main thread.
Therefore, the for loop must be running in a background queue. For instance, replace your code by this one:
#IBAction func elimineDoublons(_ sender: Any) {
txtLog.stringValue = "Nothing else"
DispatchQueue.global(qos: .background).async(elimineDoublons)
}
private func elimineDoublons() {
for i in 0...100000 {
print(i)
}
}
Note that we have defined two functions with the same name, but their signatures are not the same, this is why it works correctly. Do not change the signatures, it may not compile anymore.

Utilizing Mission Control

recently I've gotten into trying to utilize the DJI Mobile SDK as a little side project of mine. I've been working in Swift utilizing the samples provided by DJI on their Github but I've been having an issue utilizing the missionControl and honestly I'm not even sure if missionControl is the best way to go about doing it.
Goal: Simply what I'm trying to achieve is that I just want the drone to fly up to a specified height and take video footage of what is below it. I'm not even concerned with horizontal motion right now, just vertical motion.
What I've Done: Utilizing their sample, I've gotten the drone to record video footage, but I am unable to get it to truly fly. My first approach was to use flightController and I've succeeded in getting it to take off and land, but I do not believe their is a method such as goToLocation() or something of the sort. This is the functioning methods that do take off and landing.
#IBAction func takeOffPressed(_ sender: Any) {
if let aircraft = DJISDKManager.product() as? DJIAircraft {
aircraft.flightController?.startTakeoff(completion: nil)
}else{
self.showAlertViewWithTitle(title:"Action", withMessage: "Product Connection Not Found")
}
}
#IBAction func landPressed(_ sender: Any) {
if let aircraft = DJISDKManager.product() as? DJIAircraft {
aircraft.flightController?.startLanding(completion: nil)
}else{
self.showAlertViewWithTitle(title:"Action", withMessage: "Product Connection Not Found")
}
}
Although I got the drone to takeOff, that is not truly flight so instead I started looking into the missionControl class where there seems to be missions to achieve the functionality that I want, however my code seems to not be correct because it does not cause the drone to perform any action. If there is someone here more experienced with the DJI SDK, I would appreciate any help that you may be able to give. My non functioning code is below.
#IBAction func doMission(_ sender: Any) {
var elements = [DJIMissionControlTimelineElement]()
elements.append(DJITakeOffAction())
elements.append(DJIGoToAction(altitude: 1)!)
elements.append(DJIGoHomeAction())
DJISDKManager.missionControl()?.scheduleElements(elements)
DJISDKManager.missionControl()?.startTimeline()
}
The timeline mission needs a few adjustments, including the altitude of the go to action and the addition of a DJIRecordVideoAction to record video for your desired duration. Try the modified code below:
#IBAction func doMission(_ sender: Any) {
var elements = [DJIMissionControlTimelineElement]()
elements.append(DJITakeOffAction())
elements.append(DJIGoToAction(altitude: 5)!)
elements.append(DJIRecordVideoAction(duration: 10)!) // this assumes a desired duration of 10 seconds
elements.append(DJIGoHomeAction())
DJISDKManager.missionControl()?.scheduleElements(elements)
DJISDKManager.missionControl()?.startTimeline()
}
You can also make use of DJIMissionControl addListener:toTimelineProgressWithBlock: method to add additional diagnostics to your code as it will be called for each timeline event including start and finish of all elements.

Change value of type Bool by using string

I am making a little game, by improving my Swift language, so I am not familiar with all the functions of Swift. That's why I am asking this:
I have:
var Playedcardone: Bool = false
var Playedcardtwo: Bool= false
ect ect ect
my IBAction, this is hooked up with 52 cards:
#IBAction func Tappedoncard(card: UIButton) {
if tapped == true{ //nvm this
checkcard(card)
}
}
In a function, I have:
func checkcard(Card: UIButton) {
("Playedcard" + Card.currentTitle!) = true
}
Well as you may guess this function doesn't work. How can I reference to a var I made depending on the card that I called? When the card is ticked, the bool needs to change to true. I can do this by creating 52 vars, and 51 else if statements, but there should be a quicker option right? You help is welcome :).
/offtopic: I know I could used classes, to define my card value, UIIMageview and the bool itself. I just don't understand classes optimal, maybe for my next app I will use. If you want to see my code, and you want to give me a hand, just ask and I will drop the code here.
You cannot access a variable using a string as you are trying to do. You will need to preform some type of conditional checking to update the variables like so.
func checkcard(Card: UIButton) {
if Card.currentTitle! == "one" {
Playedcardone = true
} else if Card.currentTitle! == "two" {
Playedcardtwo = true
}
}
There is a plethora of different solutions you could use - for example why not make two seperate IBActions for each card? Also as a matter of convention I would suggest using lowercase letters to start your variables.

Swift: Creating a function and calling it multiple times?

I am very new to Swift and I can't find an answer to my qustion.
I am working on an app that will do a lot of the same functions but on separate button pushes. I could reduce my code and time updating greatly if I am able to write a function or action and just call it by name on a button push.
Does Swift have a way to do something like this:
Func doMath {
var answer = 1+1
var answer2 = 2+2
}
Func buttonPush {
call doMath
}
What you need is an IBAction. Using the Assistant view hold the control key and drag it into your code. Then change the connection type to Action and give it a useful name.
From inside your IBAction you can do any maths or call any maths function you need. Using functions to minimise code duplication is a good idea.
Here's an example of an Action that starts a timer.
#IBAction func play(sender: AnyObject) {
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("result"), userInfo: nil, repeats: true)
}
I sugguest you do some examples that use IBAction.
I liked the Ray Wenderlich ones myself.
Here is some code for creating a function that takes two integer parameters. It's taken from the Apple developer documentation.
apple docs hopefully that's what you need.
func halfOpenRangeLength(start: Int, end: Int) -> Int {
return end - start
}