I have a UITabBarController that I would like to assign to another object, so that that object can control it:
watchListView.tabBarController = self.stTabBarController;
During this assignment the value of both self.stTabBarController and watchListView.tabBarController are 0x0.
How can I assign the UITabBarController's?
The assignment is (at least syntactically) correct. The problem is that you're doing at a time when the source property has itself not been set.
Without knowing more about when and where this is happening it's difficult to guess what the problem is. At what point are you trying to make this call? Does the controller ever exist? Is there some subsequent time where the property is demonstrably non-nil?
Related
I have a swift UIViewController in which there is an array of data type ( e.g. countries/person/ bank details) fetched from network service asynchronously in viewDidLoad. This array remains constant once fetched. Hence I want to enforce it using let keyword.
I don't have any value when UIViewController is initialized. Hence it gives me compile time error for not initializing it.
If I declare it as optional with '?' , I have to use if-let/ guard let or optional chaining to use it. I don't want to clutter the code with unwrapping.
What are my options to declare a variable as constant but initialized later in execution without making it an optional variable?
"Constant once fetched" is not constant. There is some period of time when it's not set, and some point later when it is. The fact that it's fetched from the network means that it may fail, so your code has to deal with that (i.e. it may never be set). The right tool to use here is an Optional var.
Since there must be some view state that handles "no data yet" and a different view state that handles "data received," you can improve your design by breaking those into two view controllers, and having your container view controller switch between them when the data becomes available. In that case, you can pass the available data to the "data received" view controller in init, and so it can be let.
What are my options to declare a variable as constant but initialized later
There are no such options. If you do not have the real value of a property at instantiation time, it must be declared with var so that you can set it when you do have the real value.
And use of an Optional is a common pattern to help your code distinguish between before you have the real value (nil) and after (not nil).
I don't want to clutter the code with unwrapping.
Then declare the property as an implicitly unwrapped Optional! This use case is exactly what it is good for.
(It would be nice to be able to “lock” the property somehow after assigning its final value, but that is not a Swift language feature. I have often wished it were. lazy has the same issue.)
If I have property like:
var animatedImagesView:JSAnimatedImagesView?
And eventually it gets initialized at the proper time, do I need to just keep using ! to unwrap it ad nauseum when I want to do something to it? For instance:
self.animatedImagesView!.reloadData()
Usually I unwrap optionals like:
if let dailySleepTime:AnyObject = uw_JSON["daily_sleep_time"] {
self.settings.dailySleepTime = dailySleepTime as String
} else {
log.warning("\n Error finding attr in \(request)\n")
}
but I can't just go around casting my properties to constants in the same way right? I'm not complaining, I'm just wondering if I'm using the exclamation point correctly.
One option is to define animatedImageView as an implicitly unwrapped optional to begin with:
var animatedImagesView: JSAnimatedImagesView!
This is common when dealing with Cocoa .nib objects in Interface Builder, because the View can't be initialized until it is unarchived from the .nib, but you know that it will always be initialized before you use it.
I hate using the ! in general, because it is a runtime error just waiting to happen, but IB objects are one of the few places where its use seems both legitimate and necessary. Otherwise, your two other options are the ones that you have already found - unwrapping it every time using if let... (which is safest, but a pain in the a**), or using the ! every time that you use it, which isn't any safer than just declaring it using ! to begin with.
If you initialize it at the correct time (for example in any of the lifecycle methods, or in the constructor for that matter) you could just use ! instead of ? for the property declaration. I myself usually only use ? for stuff which I dont necessarily know will have a value at all times during my lifecycle.
If the latter is the case for you as well, you need to continue using ? since you can't guarantee you have a value stored. And you should also use the if let myVar = myVar { .. } syntax if you do multiple calls to the variable.
Instead, declare it as follows:
var animatedImagesView:JSAnimatedImagesView!
That implicitly unwrapped optional will obviate the need to constantly "bang" dereference it, but be sure it is never nil at any time accessed.
It's a great way to specify IBOutlets you know will always be initialized from the nib or storyboard before you use them.
Say I have an instance variable MyObject that has been allocated and initialized. Then say I do this:
[backgroundThread performBlock:^{
//do something with MyObject that might take some time
}];
[self dismissModalViewController]; //this releases all instance variables, right?
So what happens is I have an NSManagedObjectContext called backgroundThread that does some work on an object in the background. This returns immediately and does the work in the background, and then dismissModalViewController is called, which deallocates all instance variables. So what if the modal view has now been dismissed, but the backgroundThread still needs to use the object? Is this an issue? What is the workaround?
And another thing: This MyObject is inserted into the managed object context backgroundThread. Does this mean that this NSManagedObjectContext will retain the object, even after dismissing the view?
I'm using ARC.
There are several things you need to think about here. First keep in mind that the block will capture whatever it refers to. So you might not need to do anything special and your code will work fine, depending on exactly what you are doing in your block. The rules for block capture are described in Apple's Block Programming Topics documentation and how each variable is treated depends on its type. In particular,
In a manually reference-counted environment, local variables used within the block are retained when the block is copied. Use of instance variables within the block will cause the object itself to be retained. If you wish to override this behavior for a particular object variable, you can mark it with the __block storage type modifier.
If you are using ARC, object variables are retained and released automatically as the block is copied and later released.
Another thing to consider is that access to the instance variables may or may not be thread safe. Accessing the instance variables through properties declared as atomic is a step in the right direction, but you may need to use mutex locks or other techniques to synchronize access depending on the specifics on the situation.
If you want to reference ivars or other properties of your (modal) view controller, you need to insure that the modal view controller still exists.
Here's a potentially useful hint from Apple's documentation on dismissModalViewControllerAnimated::
If you want to retain a reference to the receiver’s presented view
controller, get the value in the modalViewController property before
calling this method.
Another idea that might work would be to create & instantiate a separate object that encapsulates the data / objects you want to access from either the view controller, or any other thread.
OK, I have a custom object (an NSManagedObject subclass, if it matters) and I want to pass a pointer to one of its iVars to a function that I've set up to modify such values. With a normal pointer you'd just prefix it with an ampersand (&) as in the classic NSError &error example, but that can't be done with dot notation. I can't just pass &object.iVar as I'd hoped. Can anyone suggest a simple and elegant way to obtain the pointer of iVar so that I can pass it? I am loath to pass the entire object for reasons of code structure and neatness.
-Ash
Argh, as is almost always the case, I ask a question after an hour of frustrating puzzling then ten minutes later answer it myself. I don't know, maybe asking questions is some kind of therapeutic trigger for answers... shame this isn't a psychology website.
Anyway, my solution was to add a new 'pseudo-getter' method to the object I'm trying to access the pointer from that looks a bit like this:
- (Pointer **)getIVarPointer
{
return &iVar;
}
It's a bit cludgy, but since I only have that one iVar whose pointer I need to obtain it's not too bad. On ther other hand if there is a simpler, more 'official' way of doing this, I'd love to know it!
My code is: dvController.selectedCountry = selectedCountry;
Why do I get the error "request for member 'selectedCountry' in something not a structure or union"?
You are probably trying to access a property "selectedCountry" on an object, and you forgot to include that header file. (At least that's what I usually do wrong when I get this error.)
I suspect that dvController is a pointer (to a structure) and not the structure. You need to use '->' instead of '.', perhaps.
also if the types are NOT the same you can get this message. Casting to the right type usually resolves this.
I believe that I have encountered this problem when I have a member or variable that hasn't properly been initialized. Check to make sure that each of your objects has memory and is initialized properly.
Also, your question isn't as clear as it could be since there is the local variable selectedCountry and the member. Which one is being referred to here? I would assume the member, if the variable is actually a member of whatever is "self" that might be your problem. Whenever I program, I make sure to make distinctions between locals, members of the current class, and members of other classes so that it's easy to see what's going on when bugs come up. Just a thought.
I just got this issue!
What was doing it in my case, was that I was attempting to access a property on an object of a different type!
It hadn't moaned about alloc'ing and init'ing the object with a different type, but it sure as hell moaned about the property!