How to list LLDB variables in Xcode? - ios

I want to list the lldb variables in Xcode debugger
such as
$0 = ...
$1 = ...
Which command should i enter?
For example

You can use frameVariable to get a list of all variables in the stack frame.
- (void)viewDidLoad {
[super viewDidLoad];
NSHashTable *hashTable = [NSHashTable weakObjectsHashTable];
ABC *object = [[ABC alloc] init];
[hashTable addObject:object];
//NSLog(#"%#", [hashTable anyObject]);
object = nil;
int i = 0;
int j = 1;
}
frame variable
(ViewController *) self = 0x00007fa2275047d0
(SEL) _cmd = "viewDidLoad"
(NSConcreteHashTable *) hashTable = 0x000061000013f5e0
(ABC *) object = nil
(int) i = 0
(int) j = 1

You want to list all the variables you have defined in or are the result of expressions you've evaluated, right?
If so, there isn't a way to do that currently. But it would be straightforward to add. Please file an enhancement request with the lldb bug reporter:
https://bugs.llvm.org
and somebody will get to it.

Related

unsure of (id)init explanation

So this is fairly beginner, but I'm trying to really grasp this concept. So in my sample code I have an Init method with two Constants defined at the beginning of the .m :
#define NUM_TOP_ITEMS 5
#define NUM_SUBITEMS 6
- (id)init {
self = [super init];
if (self) {
topItems = [[NSArray alloc] initWithArray:[self topLevelItems]];
subItems = [NSMutableArray new];
currentExpandedIndex = -1;
for (int i = 0; i < [topItems count]; i++) {
[subItems addObject:[self subItems]];
}
}
return self;
}
What is the init method doing here? Could i initiate the two constants in their separate alloc/init methods? Any clarity here would be great! thanks
OK, line by line...
#define NUM_TOP_ITEMS 5 // defining a macro for the number 5
#define NUM_SUBITEMS 6 // and 6
- (id)init
{
self = [super init]; // here you are initialising the object by calling the super class method
// this is important as you still want the functionality/properties etc... from the super class.
if (self) { //check the object actually exists.
topItems = [[NSArray alloc] initWithArray:[self topLevelItems]]; //This looks like it's running a method called topLevelItems
// that returns an NSArray. You are then saving it in an iVar (I guess)
subItems = [NSMutableArray new]; // this creates a new mutable array in an iVar called subItems
currentExpandedIndex = -1; // this sets an iVar int value
for (int i = 0; i < [topItems count]; i++) { // set up a for loop for the topItems array
[subItems addObject:[self subItems]]; //...wat?
// not quite sure what's going on here.
// I don't think it's doing what you think it's doing
}
}
return self; // return the object whether it has been allocated successfully or not.
}
Constants defined using #define are like a search and replace for tokens which happens at compile time. This is the C pre-processor, it means that code like this,
#define NUM_TOP_ITEMS 5 + 1
int i = NUM_TOP_ITEMS + NUM_TOP_ITEMS;
gets pre-processed to something like this,
int i = 5 + 1 + 5 + 1;
before the next compilation step happens.

Travel through NSArray without using loop but cursors?

I have an NSArray with objects inside (CLLocation). I can have 50, 100, 300 or more objects inside. In fact, this array is used while the user walking and can follow a direction. But the user can start at the middle of my NSArray, you know what I mean ?
Well, I Have to loop all the time my array to know where my user is compare to the locations in my array.
My question is: Is it possible to use a thing like in Java with a "cursor" in a list, and simply call "Next object" to travel in my array instead of loop ?
Because I need that the user walk on all location of my array.
Example:
Count of my array: 100
User start at location at index 34 (the nearest location found)
The user must do 35, 36, 37... 100 AND 0,1,2,3 ... until 33.
Hope it's clear, I really don't know how to do this without using for loop...
Thank you for help and suggestions!
Regards,
Lapinou.
Here's one way:
NSArray * arr = ... yourArray
int index = [arr indexOfObject:currentLocation];
index ++;
if (index == arr.count) index = 0;
id nextLocation = arr[index];
Another might be to create a global counter variable that stores the current position. If these needs to last after the user closes the app, you could write it to user defaults
Is looks like you are want to use NSEnumerator
NSEnumerator Class Reference
NSArray *anArray = // ... ;
NSEnumerator *enumerator = [anArray objectEnumerator];
id object;
while ((object = [enumerator nextObject])) {
// do something with object...
}
try this:
#interface ArrayEnumerator : NSEnumerator
{
NSArray* array;
NSInteger index;
NSInteger startIndex;
BOOL over;
}
- (id)initWithArray:(NSArray*)anArray
atIndex:(NSInteger)anIndex;
#end
#implementation ArrayEnumerator
- (id)initWithArray:(NSArray*)anArray
atIndex:(NSInteger)anIndex
{
if (self=[super init]) {
array = anArray;
index = anIndex;
startIndex = anIndex;
over = NO;
}
return self;
}
- (id)nextObject
{
if (index == [array count]) {
index = 0;
over = YES;
}
if (over && index == startIndex)
return nil;
return array[index++];
}
- (NSArray*)allObjects
{
return array;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
NSArray* array = #[#0,#1,#2,#3,#4,#5,#6,#7,#8,#9];
id element;
ArrayEnumerator* enumerator = [[ArrayEnumerator alloc] initWithArray:array atIndex:4];
while (element = [enumerator nextObject])
NSLog(#"%#", element);
}
#end
What is wrong with a for loop?
An iterator is typically used on lists, because you can't access elements in a list by index. However you are working with an array, so you don't need an iterator, but rather some clever way of accessing the array in the desired order.
Maybe this code can provide you with some ideas. This will run from 34 to 100, then start with 0 and go up to 33.
for (int i = 34; i < 134; i++)
{
int ix = i % 100;
id whatever = arr[ix];
}
You can access array elements by index:
CLLocation * myLocation = myArray[34];
(or)
int i = 34;
CLLocation * myLocation = myArray[i];

My method won't work

I'm a total noob and need help with a method I'm writing.
The method creates a deck of cards (using NSMutableArray). I'm first experimenting with loading the array with numbers 1-13 randomly (each number appearing once).
When I run a simple test program to print the values in the array, I get a "Build Successful" but an error once the program starts. The error says "[__NSArrayM insertObject:atIndex:]: object cannot be nil".
Once I understand what I'm doing wrong, I can then expand on the method properly. Thanks!
NB: This is my first post. Is this type of question ok?
- (void) createDeck {
int r;
BOOL same;
deck = [[NSMutableArray alloc]init];
NSNumber *randNum;// = nil;
randNum = [[NSNumber alloc]init];
[randNum initWithInt: (arc4random()%13)+1];
[deck addObject: randNum]; // First card added to deck
same = FALSE;
while (!same) {
for (int i=1; i<13; i++) {
same = FALSE;
for (r=0; r<=i; r++) {
[randNum initWithInt: (arc4random()%13)+1];
if ([deck objectAtIndex:r] == [deck objectAtIndex:i]) {
same = TRUE;
}
[deck addObject: randNum]; // Next card added to deck
}
}
}
}
you cannot re-init randNum:
NSNumber *randNum;// = nil;
randNum = [[NSNumber alloc]init];
[randNum initWithInt: (arc4random()%13)+1];
and the third line is missing the assignment anyway. just do:
NSNumber *randNum = [[NSNumber alloc] initWithInt:(arc4random()%13)+1];
and put that inside the inner for loop, like this:
BOOL same = FALSE;
NSMutableArray *deck = [[NSMutableArray alloc] initWithCapacity:13];
[deck addObject:[[NSNumber alloc] initWithInt:(arc4random()%13)+1]]; // First card added to deck
while (!same) {
for (int i = 1; i < 13; i++) {
same = FALSE;
for (int r = 0; r <= i; r++) {
NSNumber *randNum = [randNum initWithInt:(arc4random()%13)+1]; // modern ObjC will assign a register for this outside the while loop, but restrict the variable's scope to the inner-most loop
if ([deck objectAtIndex:r] == [deck objectAtIndex:i])
same = TRUE;
[deck addObject: randNum]; // Next card added to deck
}
}
Note that I haven't thought through the logic of what you are trying to do here, I've only attempted to resolve the NULL object reference. The error was referring to the first line [deck addObject: randNum] outside of the loop.
Try to use this line of code where you using NSNumber
NSNumber * randNum = [NSNumber numberWithInt: (arc4random%13)+1];
Instead of
[[NSNumber alloc] initWithInt: ]

Method does not return what it should when called

I have a piece of code that returns an object of type Card like so:
-(Card*) drawRandomCard {
if ([self.cards count]) {
unsigned index = arc4random() % self.cards.count;
Card *randomCard = self.cards[index];
[self.cards removeObjectAtIndex:index];
NSLog(#"%#", randomCard.description); **//returns a description and not null**
return randomCard;
} else {
NSLog(#"nil");
return nil;
}
}
This actually works fine when I use it in other functions, but there is a problem with this one below:
- (IBAction)addCards:(UIButton *)sender {
int numberOfCardsToAdd = EXTRA_CARDS_NUMBER;
if ([[self.collectionView visibleCells] count] == 0) {
numberOfCardsToAdd = self.startingCardCount;
}
for (int i = 0; i < numberOfCardsToAdd; i++) {
if (!self.game.deck.isEmpty){
Card *cardToAdd = [self.game.deck drawRandomCard];
NSLog(#"%#", cardToAdd.description); **// gives (null)**
if (cardToAdd) { **// this does not get called**
// do stuff with cardToAdd
}
}
}
[self.collectionView reloadData];
}
So for some reason it seems my drawRandomCard, when called with the method above, does not work. Does anyone know how to fix this?
Thanks very much!
Edit: my method for initializing the game object that has the deck property:
- (id) initWithNumberOfCards: (int) numberOfCards withDeck: (SetsPlayingDeck *) deck {
self = [self init];
self.score = 0;
_deck = deck;
_cards = [[NSMutableArray alloc] initWithCapacity:numberOfCards];
for (int i = 0; i < numberOfCards; i++) {
[_cards addObject: [_deck drawRandomCard]];
}
return self;
}
This method is called right at the start of the program.
Edit #2:
Here is the code that initializes the game object, along with a deck object that is its property:
- (SetsGame *) game {
if (!_game) {
SetsPlayingDeck *deck = [[SetsPlayingDeck alloc] init];
_game = [[SetsGame alloc] initWithCardCount:self.startingCardCount usingDeck:deck];
}
NSLog(#"%#", _game.deck.description); **// this returns null!!**
return _game;
}
As far as I can see, the issue should lie with the method initWithCardCount:usingDeck:, where you probably forgot to assign the deck argument to the deck property (or for some reason the assignment is not executed):
_game = [[SetsGame alloc] initWithCardCount:self.startingCardCount usingDeck:deck];
So, please review this or post that method definition.
Maybe the problem is that you're running out of cards. Inside your init method you have the following line inside a for-loop:
[_cards addObject: [_deck drawRandomCard]];
And inside your drawRandomCard method you have the following line:
[self.cards removeObjectAtIndex:index];
I'm assuming that _cards(1st line) and self.cards(2nd line) are different objects.
Probably, by the time you call Card *cardToAdd = [self.game.deck drawRandomCard]; inside your addCards: method you don't have any cards left.
Try to set a breakpoint and step in the for-loop and let me know,
Hope this helps!

Check whether an object was created inside a loop or not

is there any way in Objective-C to check whether an Object has been created inside a loop (while, for)?
Thanks in advance.
NSString *obj = nil;
while()
{
//Create object
obj = [[NSString alloc] init];
}
//check obj is nil or not
if(nil == obj)
{
// obj not created
}
Yes but for an accurate answer can you tell us what the object is and when it is declared? Can you post the code you have?
int x=0;
while (x<3) {
NSString *i = #"hello world";
x++;
}
NSLog(#"i is %#", i) // i is only declared inside the while loop so not available here
Alternatively,
int x=0;
NSString *i;
while (x<3) {
i = #"hello world";
x++;
}
NSLog(#"i is %#", i); // i is declared beforehand outside the while loop so is available here
If you then need to act on whether it's been created or not use Anil's answer but it's the scope that's important here
I don't think you can know if it was created in a loop, but because you are writing the code where the object will be created in a loop you could call a special init method...
SpecialClass * obj = [[SpecialClass alloc] init];
while (isTrue)
{
SpecialClass * loopObj = [[SpecialClass alloc] initCreatedByLoop];
// Do whats needed
}
and in your SpecialClass you create a specific initialiser...
#implementation SpecialClass
-(id)initCreatedByLoop {
self = [super init];
if (self) {
// What ever you want to do
}
return self;
}

Resources