AVAudioPlayer's property give "Cannot assign result of this property" - ios

I'm trying to set following property of AVAudioPlayer, but it gives an error.
Error:
Cannot assign result of this property
Code:
self.player = AVAudioPlayer(contentsOfURL: url, error: &error)
self.player?.numberOfLoops = 0 // Error here
self.player?.delegate = self // Error here
if(!self.player?.prepareToPlay()){... } // This seems to good.
Fully confused? Is there any workaround behind this?

Optional chaining does not support the setting of property values. It is only used for querying (see: getting) properties, and calling methods.
Your code should instead read:
if let myPlayer = self.player? {
myPlayer.numberOfLoops = 0
myPlayer.delegate = self
}
This will only set the properties on the object if it has a value. Since your ivar is most likely defined as var player: AVAudioPlayer?, the compiler doesn't actually know whether it will have a value.
As mentioned in the language guide, under the Calling Properties Through Optional Chaining section:
You cannot, however, set a property’s value through optional chaining.

What I do is declare the type of my class's player property as AVAudioPlayer!. I can do this because I happen to know that this class will always have an audio player. This means, in turn, that I don't have to use ? or ! ever again; I can just say self.player and everything just works.
If you use this approach and you are ever in doubt about whether you really have a player, simply say if self.player - it will be false if no player is there, and now you can avoid talking to self.player as if it were an actual AVAudioPlayer (which would crash your app).

Related

GameKit and Swift: instance property is not an optional but can be nil?

GKTurnBasedParticipant has a property: player, which has class GKPlayer. The declaration is written as:
var player: GKPlayer { get }
Yet the API documentation says,
The value of this property may be nil if this slot in the match has
not yet been filled by an actual player.
So if it can be nil, why isn't the declaration:
var player: GKPlayer?
What am I not understanding here? Is it something with the getter? This is actually important because the player should be nil for automatched games where a second player has yet to join.
When I do conditional unwrapping (after migrating to Swift 4.2)
if let onlineGKPlayer = participant.player {
this now is a compiler error:
Initializer for conditional binding must have Optional type, not 'GKPlayer'
https://developer.apple.com/documentation/gamekit/gkturnbasedparticipant/1521037-player
Not sure when it was updated, but the API documentation now lists it as an Optional:
var player: GKPlayer? { get }
It seems you had the right idea

IF Statement Incorrectly Evaluating to True when Using Optional Values in Swift

I have set up my view controllers so that they send a notification once their -viewDidLoad method is about to return. For example:
class MyViewController: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
//Do Stuff
var notificationCenter = NSNotificationCenter.defaultCenter();
notificationCenter.postNotificationName("AViewControllerDidLoadNotification", object: self);
}
}
My AppDelegate class is listening for this notification and implementing the method shown in this picture.
In case the picture isn't loading, the method takes the notification sent by the view controllers as it's only argument and then tests whether the UIViewController's title property has a non-nil value. If the title property is non-nil it logs the title.
However, as you can see in the debugger panel, the title property of the view controller is nil and the if statement is still evaluating to true.
I am admittedly new to optional values. But I have recreated this situation in a swift playground and the if statement evaluates to false. Any ideas?
You've gotten yourself into rather an odd situation with your very peculiar use of the expression notification.object?.title, because notification.object is not, of itself, a UIViewController. It is an AnyObject.
Now, an AnyObject has no known properties, so it has no title and your expression, it would seem, should not even compile. But, by a special dispensation coming from certain oddities of Objective-C, you are in fact allowed to ask about an AnyObject's properties anyway. But when you do, the result is itself an Optional, because no such property might exist.
Thus, you are actually testing, not the value of a view controller's title property, but whether this unknown object has a title property in the first place; and if in fact it does have a title property at all, the value of that title property is double-wrapped inside that Optional.
To see this clearly, just test this (silly) code:
let n = NSNotification(name: "Howdy", object: "Hi")
let t = n.object?.title
Look at what type t is. It is not a String?; it is a String??. That's your double-wrapped Optional. This means that it would be an Optional-wrapping-a-String in case this object turns out to have a title property, but just in case, that value has itself been wrapped in an Optional.
Thus, your test doesn't do what you want it to do. To do what you want to do, just speak much more plainly and simply. You need to cast the object to a UIViewController first, and then examine its title. Like this:
func aViewControllerDidLoad(notification:NSNotification) {
if let vc = notification.object as? UIViewController {
if vc.title != nil {
// ...
}
}
}

Access Optional property in multiple function for calculations - Swift

I have a NSObject Subclass. Say CityWalks
class CityWalks{
var totalCount:Int?
}
How do I use this property further? Should I check the nil coalescing every time this value is accessed.
example:
let aObject =
say in one fucntion (function1()) , I need to access this value, then it would like (aObject!.totalCount ?? 0)
func function1(){
...Some Access code for the object....
(aObject!.totalCount ?? 0)
}
Similarly in every other function(function2()) , I will have to write the same code.
func function2(){
...Some Access code for the object....
(aObject!.totalCount ?? 0)
}
So, what could be a better approach for such field, considering this property might receive a value from server or might not.
If you have a default value for this property just assign this value as default value.
class YourClass {
var totalCount = 0
}
I'd recommend you avoid using an optional value if it's possible. Because optional values its a first place when you can get an error.
As stated in the comments and the other answer using an optional is not really optimal in your case. It seems like you might as well use a default value of 0.
However, to clarify, you have to check the value when unwrapping the optional.
Sometimes it's possible to pass an optional to UIElement etc and then you don't really need to do anything with them
There are pretty ways of checking for nil in optional values built into swift so you can build pretty neat code even though you work with optional.
Look in to guard let and if let if you want to know more about unwrapping values safely.
if let
if let totalWalks = aObject?.totalCount {
//operate on totalWalks
}
guard
guard let totalWalks = aObject?.totalCount else { return }
//operate on totalWalks
There are also cases where you will want to call a function on an optional value and in this case you can do so with ?
aObject?.doSomething()
Any return values this function might have will now be wrapped in an optional and you might have to unwrap them as well with an if let or guard
When working with optionals you should try to avoid forcing the unwrap with ! as even though you at the moment know that the value is not null that might after a change in the code not be true anymore.

Could not find an overload for '=='

I have the following code:
var settingButton:UIButton
settingButton = appDelegate.myFunctionReturningButton()
if (settingButton == nil) {println("WE ARE IN BAD SHAPE!!!!")}
It partly works, but not always. To see what happens in case I do not get what I expect from myFunctionReturningButton(), I added the last line.
But here is the problem and my question:
I get this error message from the Swift compiler:
Could not find an overload for '==' that accepts the supplied arguments
Browsing the net, I kind of understand what that means, but what can I do about it?
How should I write the last line?
For precision:
I have the two following function in AppDelegate.swift and appSettingButton is declared with this line at the top of the AppDelegate class.
var appSettingButton: UIButton = UIButton.alloc()
func registerSettingButton (button:UIButton) {
appSettingButton = button
}
func myFunctionReturningButton() -> UIButton {
return appSettingButton
}
You can't compare a non-optional value to nil because it will never be nil. And you shouldn't use UIButton.alloc() to initialize a button, just use UIButton(). If your logic depends on waiting for this button to be re-defined after initialization of your app delegate subclass, you should make an optional, i.e. UIButton?. Then you can compare it to nil.

Access to AVAudioRecorder's meterEnabled give error

I'm trying to ON meter with AVAudioRecorder, but it give error as
Cann't assign to the result of expression
Declaration:
var recorder : AVAudioRecorder?
..
Definition
self.recorder?.meteringEnabled = true // Error here
You need to unwrap the self.recorder variable like so:
self.recorder!.meteringEnabled = true
Optional chaining does not support the setting of property values. It is only used for querying (see: getting) properties, and calling methods.
So code should be
if let recorder = self.recorder?{
recorder.meteringEnabled = true
}
This will only set the properties on the object if it has a value. Since your ivar is most likely defined as var player: AVAudioPlayer?, the compiler doesn't actually know whether it will have a value.
As mentioned in the language guide, under the Calling Properties Through Optional Chaining section:
You cannot, however, set a property’s value through optional chaining.

Resources