ios - 当调用某些函数时变量消失

标签 ios objective-c xcode uitableview uistoryboardsegue

我是个菜鸟,所以希望这不会太复杂。我的代码有一个问题,到目前为止,这个问题一直困扰着我和其他一些用户。我花了一些时间清理代码并遵循一些教程,但我仍然解决了这个问题。我只知道这非常简单,所以这里是:

我正在为我的博客网站制作一个 iOS 应用程序。它访问该站点,提取 XML 文档(包含博客标题、简短描述和完整文章 url),并解析它以在 UITableView 中显示。为了管理这个,有两个自定义对象:“PostList”和“Post”。 Post 只是一个保存单个帖子数据(url、标题、发布日期等)的对象,PostList 有一个保存 Post 对象的数组,以及一些 getter/setter/init 函数。

一切顺利。 View 会加载,XML 会被解析并显示在列表中。当用户点击链接或将某些单元格滚动到屏幕之外时,就会出现问题。据我所知,这些都与同一问题有关。在用户点击单元格的情况下, View Controller 不会将值传递给详细 View Controller (prepareForSegue),并且在滚动的情况下,cellForRowAtIndexPath 不会重新初始化单元格值。

我相信这是由于同样的问题,一旦 View 被初始化,PostList 数组中的现有值就会以某种方式被删除。调试器说数组仍然可以看到其中的对象,但它们都是空白对象。我花了很长时间试图找出原因。

如果您能给我一些关于为什么会发生这种情况的想法,那就太棒了!我的代码如下。我几乎发布了所有内容,因为我以前曾遇到过发布不够多的问题。希望这可以帮助。如果您需要更多请询问!

-提前致谢;)

FirstViewController.h

 #import <UIKit/UIKit.h>
 #import "PostList.h"
 #import "Post.h"

 @interface FirstViewController : UITableViewController     

 @property (nonatomic, strong) PostList *postController;
 @property (nonatomic, strong) IBOutlet UITableView *tableView;
 @property (nonatomic, strong) Post *postToSendToDetailView;
 @property (nonatomic, strong) NSString *type;

 @end

FirstViewController.m

#import "FirstViewController.h"
#import "DetailViewController.h"
#import "Post.h"
#import "PostList.h"

@interface FirstViewController ()
@end

@implementation FirstViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.type = @"blog";
    self.postController = [[PostList alloc] initWithType:self.type];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.postController countOfList];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    Post *postAtSighting = [self.postController objectInListAtIndex:indexPath.row];

    // Configure the cell...
    [[cell textLabel] setText:postAtSighting.name];
    [[cell detailTextLabel] setText:postAtSighting.content];
    NSLog(@"Cell Initalized");
    return cell;
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"pushToDetailView"]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        DetailViewController *destViewController = segue.destinationViewController;
        destViewController.aPost = [self.postController objectInListAtIndex:indexPath.row];
    }
}

@end

PostList.h

#import <Foundation/Foundation.h>
#import "Post.h"

@interface PostList : NSObject

-(NSMutableArray *) getPostsofType:(NSString *)type;
-(NSString *) getName: (Post *)aPost;
-(NSUInteger) countOfList;
-(Post *)objectInListAtIndex:(NSUInteger)theIndex;
-(id)initWithType:(NSString *)type;

@property (nonatomic, strong) NSMutableArray *postsArray;
@property (nonatomic) NSString *urlString;
@property (nonatomic) NSUInteger countingIndex;

@end

PostList.m

#import "PostList.h"
#import "TBXML+HTTP.h"

@implementation PostList

- (id)initWithType:(NSString *)type {
    self = [super init];
    if (self) {    
        //Creates postArray to store Post objects
        self.postsArray = [[NSMutableArray alloc] init];

        //Create other resources
        self.urlString = [[NSString alloc] init];
        self.countingIndex = 0;
        [self getPostsofType:type];
    }
    return self;
}

-(NSString *)getName:(Post *)somePost {
    //Gets the Name of the Post object and returns the value
    NSString *name = somePost.name;
    return name;
}

-(NSMutableArray *)getPostsofType:(NSString *)type {

    //Go to the Server and get the posts that are available for the post type selected.

    //Determing the post type
    if ([type isEqual: @"blog"]) {
        self.urlString = @"http://www.biteofanapple.com/blog/feeds/blogFeed.xml";
    }
    if ([type isEqual: @"bbp"]) {
        self.urlString = @"http://www.biteofanapple.com/blog/feeds/blogFeed.xml";
    }

    //Checks for an existant xmlBlogData.xml
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents directory

    NSString* blogXML = [documentsDirectory stringByAppendingPathComponent:@"xmlBlogData.xml"];
    BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:blogXML];
    NSData *data = [[NSData alloc] init];

    //Determines the best way to handle the xml file
    if (fileExists) {
        data = [NSData dataWithContentsOfFile:blogXML];
    } else {
        NSURL *url = [NSURL URLWithString:self.urlString];

        //Goes to the Server and reads the XML file of the Posts
        data = [NSData dataWithContentsOfURL:url];
        if (data != nil) {
        NSLog(@" NSData value is not nil");
    }

        //Saves the XML data to a .dat file in the document's directory
        NSError *error;
    BOOL succeed = [data writeToFile:[documentsDirectory stringByAppendingPathComponent:@"xmlBlogData.dat"] atomically:YES];
        if (!succeed){
            // Handle error here
            NSLog(@"Error: File was unable to be written to the documents directory.");
            [error setValue:@"-1" forKey: @"File unable to be written"];
        }
    }

    //Parses the XML file
    TBXML *tbxml = [TBXML newTBXMLWithXMLData:data error:nil];

    //Prints the data Variable to NSLog
    NSLog(@"%@", [NSString stringWithUTF8String:[data bytes]]);


    //Make some placeholder variables
    if (tbxml.rootXMLElement == nil) {
        NSLog(@"XML Document does not have rootElement. Error -1");
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Sorry, there was an error" message:@"Could not find root XML element. Please contact support for help with this issue." delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
        [alert show];
    }

    TBXMLElement *element = tbxml.rootXMLElement;
    TBXMLElement *nextElement = element->nextSibling;
    NSLog(@"URLs have been set, preparing for parse/input. [PostList.getPosts]");

    //Extracts the content of the XML file and saves it to values in the Post Class
    do {
        /**********
         * This loop goes through the XML file looking for <item> tags that hold information
         * about the blog posts. It finds <item> tags and scours them for <title>, <description>, 
         * <pubdate>, and <link> tags to put into the class variables for the Post Class (aPost).
         **********/

        NSString *stringElement = [TBXML elementName:element];
        NSLog(@"%@", stringElement);

        //Creates Post variable to put stuff in.
        Post *aPost = [[Post alloc] init];

        //Sorts through the header junk to find the first <item> tag.
        if (![stringElement isEqualToString:@"item"]) {
            if (!(element->firstChild)) {
                if (!(element->nextSibling)) {
                    element = nil;
                }
                element = element->nextSibling;
            }
            element = element->firstChild;
        }
        //Once the first <item> tag is found, this code executes.
        else {
            //Now we move to the first child tag and scour its contents and its siblings
            nextElement = [TBXML nextSiblingNamed:@"item" searchFromElement:element];
            element = element->firstChild;
            do {
                //Here it loops over and over until all the parts have been collected.
                stringElement = [TBXML elementName:element];
                if ([stringElement isEqualToString:@"title"]) {
                    aPost.name = [TBXML textForElement:element];
                }
                if ([stringElement isEqualToString:@"description"]) {
                    aPost.content = [TBXML textForElement:element];
                }
                if ([stringElement isEqualToString:@"link"]) {
                    aPost.postURL = [TBXML textForElement:element];
                }
                if ([stringElement isEqualToString:@"pubdate"]) {
                    aPost.publicationDate = [TBXML textForElement:element];
                }
                element = element->nextSibling;
            } while (element->nextSibling);
            NSLog(@"%@", [self getName:aPost]);
            NSLog(@"name %@ content %@", aPost.name, aPost.content);
            [self.postsArray insertObject:aPost atIndex:self.countingIndex];
            self.countingIndex++;
            element = nextElement;

        }
    } while ((element != nil));
    return self.postsArray;
}

-(Post *)objectInListAtIndex:(NSUInteger)theIndex {
    return [self.postsArray objectAtIndex:theIndex];
}

-(NSUInteger)countOfList {
    return [self.postsArray count];
}

@end

Post.h

#import <Foundation/Foundation.h>

@class Post;

@interface Post : NSObject

@property (nonatomic, weak) NSString *name;
@property (nonatomic, weak) NSString *author;
@property (nonatomic, weak) NSString *publicationDate;
@property (nonatomic, weak) NSString *content;
@property (nonatomic, weak) NSString *postURL;

@end

帖子.m

#import "Post.h"

@implementation Post

- (id)init {
    self = [super init];
    if (self) {
        self.name = @"";
        self.author = @"";
        self.content = @"";
        self.publicationDate = @"";
        self.postURL = @"";
    }
    return self;
}
@end

最佳答案

正如我在上面的评论中发布的,问题是您在 Post 类中使用弱引用。请尝试使用以下代码:

#import <Foundation/Foundation.h>

@class Post;

@interface Post : NSObject

@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *author;
@property (nonatomic, strong) NSString *publicationDate;
@property (nonatomic, strong) NSString *content;
@property (nonatomic, strong) NSString *postURL;

@end

如果你想了解强引用和弱引用之间的区别,请看这个问题: Differences between strong and weak in Objective-C

另请注意,objective-c 属性的默认引用类型是 strong,因此您可以根据需要省略 strong 关键字。

关于ios - 当调用某些函数时变量消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16050629/

相关文章:

ios - 无法读取 objective-c 中json文件的具体值

ios - 回合制配对在 iOS 10 中不起作用

ios - 如何让 UIViewController 暂停直到数据加载

ios - 如何从图像中删除纯背景颜色

ios - 核心数据中的UIImage

iOS >> 如何安排与用户操作无关的基于时间的事件

ios - 无法在 iTunes 连接上提交应用程序 : "New apps and app updates must be built with the public (GM) versions of Xcode"

ios - 如何仅在委托(delegate)(继承)中快速指定可用性?

ios - 自定义 UIView 类约束取决于 ParentView

xcode - 'isConnected' 在 iOS 7 中被弃用