Fjalapeno has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/211716

Change subject: Update model class memory semantics, use properties for access.
......................................................................

Update model class memory semantics, use properties for access.

Change-Id: I4938141e8cdfc76241bafd220d7362c32b55be6c
---
M MediaWikiKit/MediaWikiKit/MWKArticle.h
M MediaWikiKit/MediaWikiKit/MWKArticle.m
M MediaWikiKit/MediaWikiKit/MWKDataStore.h
M MediaWikiKit/MediaWikiKit/MWKDataStore.m
M MediaWikiKit/MediaWikiKit/MWKHistoryEntry.h
M MediaWikiKit/MediaWikiKit/MWKHistoryEntry.m
M MediaWikiKit/MediaWikiKit/MWKHistoryList.h
M MediaWikiKit/MediaWikiKit/MWKHistoryList.m
M MediaWikiKit/MediaWikiKit/MWKImage.h
M MediaWikiKit/MediaWikiKit/MWKImage.m
M MediaWikiKit/MediaWikiKit/MWKImageInfo.h
M MediaWikiKit/MediaWikiKit/MWKImageInfo.m
M MediaWikiKit/MediaWikiKit/MWKImageList.h
M MediaWikiKit/MediaWikiKit/MWKImageList.m
M MediaWikiKit/MediaWikiKit/MWKLicense.h
M MediaWikiKit/MediaWikiKit/MWKLicense.m
M MediaWikiKit/MediaWikiKit/MWKProtectionStatus.m
M MediaWikiKit/MediaWikiKit/MWKRecentSearchEntry.h
M MediaWikiKit/MediaWikiKit/MWKRecentSearchEntry.m
M MediaWikiKit/MediaWikiKit/MWKRecentSearchList.h
M MediaWikiKit/MediaWikiKit/MWKRecentSearchList.m
M MediaWikiKit/MediaWikiKit/MWKSavedPageEntry.h
M MediaWikiKit/MediaWikiKit/MWKSavedPageEntry.m
M MediaWikiKit/MediaWikiKit/MWKSavedPageList.h
M MediaWikiKit/MediaWikiKit/MWKSavedPageList.m
M MediaWikiKit/MediaWikiKit/MWKSection.h
M MediaWikiKit/MediaWikiKit/MWKSection.m
M MediaWikiKit/MediaWikiKit/MWKSectionList.h
M MediaWikiKit/MediaWikiKit/MWKSectionList.m
M MediaWikiKit/MediaWikiKit/MWKSite.h
M MediaWikiKit/MediaWikiKit/MWKSite.m
M MediaWikiKit/MediaWikiKit/MWKSiteDataObject.h
M MediaWikiKit/MediaWikiKit/MWKSiteDataObject.m
M MediaWikiKit/MediaWikiKit/MWKTitle.h
M MediaWikiKit/MediaWikiKit/MWKTitle.m
M MediaWikiKit/MediaWikiKit/MWKUser.h
M MediaWikiKit/MediaWikiKit/MWKUser.m
M MediaWikiKit/MediaWikiKit/MWKUserDataStore.h
M MediaWikiKit/MediaWikiKit/MWKUserDataStore.m
M Wikipedia/Data/SchemaConverter.h
M Wikipedia/Session/SessionSingleton.m
41 files changed, 593 insertions(+), 409 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/apps/ios/wikipedia 
refs/changes/16/211716/1

diff --git a/MediaWikiKit/MediaWikiKit/MWKArticle.h 
b/MediaWikiKit/MediaWikiKit/MWKArticle.h
index 93f55de..975dc07 100644
--- a/MediaWikiKit/MediaWikiKit/MWKArticle.h
+++ b/MediaWikiKit/MediaWikiKit/MWKArticle.h
@@ -26,30 +26,29 @@
 }
 
 // Identifiers
-@property (readonly) MWKSite* site;
-@property (readonly) MWKTitle* title;
-@property (readonly) MWKDataStore* dataStore;
+@property (readonly, strong, nonatomic) MWKTitle* title;
+@property (readonly, weak, nonatomic) MWKDataStore* dataStore;
 
 // Metadata
-@property (readonly) MWKTitle* redirected;                // optional
-@property (readonly) NSDate* lastmodified;                // required
-@property (readonly) MWKUser* lastmodifiedby;             // required
-@property (readonly) int articleId;                       // required; -> 'id'
-@property (readonly) int languagecount;                   // required; int
-@property (readonly) NSString* displaytitle;              // optional
-@property (readonly) MWKProtectionStatus* protection;     // required
-@property (readonly) BOOL editable;                       // required
+@property (readonly, strong, nonatomic) MWKTitle* redirected;                
// optional
+@property (readonly, strong, nonatomic) NSDate* lastmodified;                
// required
+@property (readonly, strong, nonatomic) MWKUser* lastmodifiedby;             
// required
+@property (readonly, assign, nonatomic) int articleId;                       
// required; -> 'id'
+@property (readonly, assign, nonatomic) int languagecount;                   
// required; int
+@property (readonly, copy, nonatomic) NSString* displaytitle;              // 
optional
+@property (readonly, strong, nonatomic) MWKProtectionStatus* protection;     
// required
+@property (readonly, assign, nonatomic) BOOL editable;                       
// required
 
-@property (readwrite, nonatomic) NSString* thumbnailURL;   // optional; pulled 
separately via search
-@property (readwrite, nonatomic) NSString* imageURL;       // optional; pulled 
in article request
+@property (readwrite, copy, nonatomic) NSString* thumbnailURL;   // optional; 
pulled separately via search
+@property (readwrite, copy, nonatomic) NSString* imageURL;       // optional; 
pulled in article request
 
-@property (readonly) NSString* entityDescription;            // optional; 
currently pulled separately via wikidata
+@property (readonly, copy, nonatomic) NSString* entityDescription;            
// optional; currently pulled separately via wikidata
 
-@property (readonly) MWKSectionList* sections;
+@property (readonly, strong, nonatomic) MWKSectionList* sections;
 
-@property (readonly) MWKImageList* images;
-@property (readonly) MWKImage* thumbnail;
-@property (readonly) MWKImage* image;
+@property (readonly, strong, nonatomic) MWKImageList* images;
+@property (readonly, strong, nonatomic) MWKImage* thumbnail;
+@property (readonly, strong, nonatomic) MWKImage* image;
 
 - (instancetype)initWithTitle:(MWKTitle*)title 
dataStore:(MWKDataStore*)dataStore;
 - (instancetype)initWithTitle:(MWKTitle*)title 
dataStore:(MWKDataStore*)dataStore dict:(NSDictionary*)dict;
diff --git a/MediaWikiKit/MediaWikiKit/MWKArticle.m 
b/MediaWikiKit/MediaWikiKit/MWKArticle.m
index c6cf2ab..424da87 100644
--- a/MediaWikiKit/MediaWikiKit/MWKArticle.m
+++ b/MediaWikiKit/MediaWikiKit/MWKArticle.m
@@ -9,15 +9,41 @@
 #import "MediaWikiKit.h"
 #import <BlocksKit/BlocksKit.h>
 
-@implementation MWKArticle {
-    MWKSectionList* _sections;
-}
+@interface MWKArticle ()
+
+// Identifiers
+@property (readwrite, strong, nonatomic) MWKTitle* title;
+@property (readwrite, weak, nonatomic) MWKDataStore* dataStore;
+
+// Metadata
+@property (readwrite, strong, nonatomic) MWKTitle* redirected;                
// optional
+@property (readwrite, strong, nonatomic) NSDate* lastmodified;                
// required
+@property (readwrite, strong, nonatomic) MWKUser* lastmodifiedby;             
// required
+@property (readwrite, assign, nonatomic) int articleId;                       
// required; -> 'id'
+@property (readwrite, assign, nonatomic) int languagecount;                   
// required; int
+@property (readwrite, copy, nonatomic) NSString* displaytitle;              // 
optional
+@property (readwrite, strong, nonatomic) MWKProtectionStatus* protection;     
// required
+@property (readwrite, assign, nonatomic) BOOL editable;                       
// required
+
+@property (readwrite, copy, nonatomic) NSString* entityDescription;            
// optional; currently pulled separately via wikidata
+
+@property (readwrite, strong, nonatomic) MWKSectionList* sections;
+
+@property (readwrite, strong, nonatomic) MWKImageList* images;
+@property (readwrite, strong, nonatomic) MWKImage* thumbnail;
+@property (readwrite, strong, nonatomic) MWKImage* image;
+
+@end
+
+@implementation MWKArticle
+
+#pragma mark - Setup / Tear Down
 
 - (instancetype)initWithTitle:(MWKTitle*)title 
dataStore:(MWKDataStore*)dataStore {
     self = [self initWithSite:title.site];
     if (self) {
-        _dataStore = dataStore;
-        _title     = title;
+        self.dataStore = dataStore;
+        self.title     = title;
     }
     return self;
 }
@@ -29,6 +55,35 @@
     }
     return self;
 }
+
+#pragma mark - NSObject
+
+- (BOOL)isEqual:(id)object {
+    if (object == nil) {
+        return NO;
+    } else if (![object isKindOfClass:[MWKArticle class]]) {
+        return NO;
+    } else {
+        MWKArticle* other = object;
+        return [self.site isEqual:other.site] &&
+               (self.redirected == other.redirected || [self.redirected 
isEqual:other.redirected]) &&
+               [self.lastmodified isEqual:other.lastmodified] &&
+               [self.lastmodifiedby isEqual:other.lastmodifiedby] &&
+               self.articleId == other.articleId &&
+               self.languagecount == other.languagecount &&
+               [self.displaytitle isEqualToString:other.displaytitle] &&
+               [self.protection isEqual:other.protection] &&
+               self.editable == other.editable &&
+               (self.thumbnailURL == other.thumbnailURL || [self.thumbnailURL 
isEqualToString:other.thumbnailURL]) &&
+               (self.imageURL == other.imageURL || [self.imageURL 
isEqualToString:other.imageURL]);
+    }
+}
+
+- (NSString*)description {
+    return [NSString stringWithFormat:@"%@ %@", [super description], 
self.title.description];
+}
+
+#pragma mark - Import / Export
 
 - (id)dataExport {
     NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
@@ -63,42 +118,17 @@
     return [NSDictionary dictionaryWithDictionary:dict];
 }
 
-- (BOOL)isEqual:(id)object {
-    if (object == nil) {
-        return NO;
-    } else if (![object isKindOfClass:[MWKArticle class]]) {
-        return NO;
-    } else {
-        MWKArticle* other = object;
-        return [self.site isEqual:other.site] &&
-               (self.redirected == other.redirected || [self.redirected 
isEqual:other.redirected]) &&
-               [self.lastmodified isEqual:other.lastmodified] &&
-               [self.lastmodifiedby isEqual:other.lastmodifiedby] &&
-               self.articleId == other.articleId &&
-               self.languagecount == other.languagecount &&
-               [self.displaytitle isEqualToString:other.displaytitle] &&
-               [self.protection isEqual:other.protection] &&
-               self.editable == other.editable &&
-               (self.thumbnailURL == other.thumbnailURL || [self.thumbnailURL 
isEqualToString:other.thumbnailURL]) &&
-               (self.imageURL == other.imageURL || [self.imageURL 
isEqualToString:other.imageURL]);
-    }
-}
-
-- (NSString*)description {
-    return [NSString stringWithFormat:@"%@ %@", [super description], 
self.title.description];
-}
-
 - (void)importMobileViewJSON:(NSDictionary*)dict {
-    _lastmodified   = [self requiredDate:@"lastmodified" dict:dict];
-    _lastmodifiedby = [self requiredUser:@"lastmodifiedby" dict:dict];
-    _articleId      = [[self requiredNumber:@"id" dict:dict] intValue];
-    _languagecount  = [[self requiredNumber:@"languagecount" dict:dict] 
intValue];
-    _protection     = [self requiredProtectionStatus:@"protection" dict:dict];
-    _editable       = [[self requiredNumber:@"editable" dict:dict] boolValue];
+    self.lastmodified   = [self requiredDate:@"lastmodified" dict:dict];
+    self.lastmodifiedby = [self requiredUser:@"lastmodifiedby" dict:dict];
+    self.articleId      = [[self requiredNumber:@"id" dict:dict] intValue];
+    self.languagecount  = [[self requiredNumber:@"languagecount" dict:dict] 
intValue];
+    self.protection     = [self requiredProtectionStatus:@"protection" 
dict:dict];
+    self.editable       = [[self requiredNumber:@"editable" dict:dict] 
boolValue];
 
-    _redirected        = [self optionalTitle:@"redirected" dict:dict];
-    _displaytitle      = [self optionalString:@"displaytitle" dict:dict];
-    _entityDescription = [self optionalString:@"description" dict:dict];
+    self.redirected        = [self optionalTitle:@"redirected" dict:dict];
+    self.displaytitle      = [self optionalString:@"displaytitle" dict:dict];
+    self.entityDescription = [self optionalString:@"description" dict:dict];
 
     // From mobileview API...
     if (dict[@"thumb"]) {
@@ -117,9 +147,11 @@
     }];
 
     if ([sectionsData count] > 0) {
-        [self.sections setSections:sectionsData];
+        self.sections = [[MWKSectionList alloc] initWithArticle:self 
sections:sectionsData];
     }
 }
+
+#pragma mark - Image Helpers
 
 - (void)updateImageListsWithSourceURL:(NSString*)sourceURL 
inSection:(int)sectionId {
     if (sourceURL && sourceURL.length > 0) {
@@ -166,6 +198,8 @@
     }
 }
 
+#pragma mark - Save
+
 - (void)save {
     [self.dataStore saveArticle:self];
     [self.images save];
@@ -182,13 +216,16 @@
     }
 }
 
+#pragma mark - Remove
+
 - (void)remove {
     NSString* path = [self.dataStore pathForArticle:self];
     [[NSFileManager defaultManager] removeItemAtPath:path error:nil];
-
-    _sections = nil;
-    _images   = nil;
+    self.sections = nil;
+    self.images   = nil;
 }
+
+#pragma mark - Accessors
 
 - (MWKSectionList*)sections {
     if (_sections == nil) {
@@ -201,25 +238,11 @@
     return [self.sections count] > 0 ? YES : NO;
 }
 
-#pragma mark - protection status methods
-
-- (MWKProtectionStatus*)requiredProtectionStatus:(NSString*)key 
dict:(NSDictionary*)dict {
-    NSDictionary* obj = [self requiredDictionary:key dict:dict];
-    if (obj == nil) {
-        @throw [NSException exceptionWithName:@"MWKDataObjectException"
-                                       reason:@"missing required protection 
status field"
-                                     userInfo:@{@"key": key}];
-    } else {
-        return [[MWKProtectionStatus alloc] initWithData:obj];
-    }
-}
-
 - (MWKImage*)thumbnail {
-    if (self.thumbnailURL) {
-        return [self imageWithURL:self.thumbnailURL];
-    } else {
-        return nil;
+    if (self.thumbnailURL && !_thumbnail) {
+        _thumbnail = [self imageWithURL:self.thumbnailURL];
     }
+    return _thumbnail;
 }
 
 - (void)setThumbnailURL:(NSString*)thumbnailURL {
@@ -233,11 +256,10 @@
 }
 
 - (MWKImage*)image {
-    if (self.imageURL) {
-        return [self imageWithURL:self.imageURL];
-    } else {
-        return nil;
+    if (self.imageURL && !_image) {
+        _image = [self imageWithURL:self.imageURL];
     }
+    return _image;
 }
 
 - (MWKImageList*)images {
@@ -247,4 +269,17 @@
     return _images;
 }
 
+#pragma mark - protection status methods
+
+- (MWKProtectionStatus*)requiredProtectionStatus:(NSString*)key 
dict:(NSDictionary*)dict {
+    NSDictionary* obj = [self requiredDictionary:key dict:dict];
+    if (obj == nil) {
+        @throw [NSException exceptionWithName:@"MWKDataObjectException"
+                                       reason:@"missing required protection 
status field"
+                                     userInfo:@{@"key": key}];
+    } else {
+        return [[MWKProtectionStatus alloc] initWithData:obj];
+    }
+}
+
 @end
diff --git a/MediaWikiKit/MediaWikiKit/MWKDataStore.h 
b/MediaWikiKit/MediaWikiKit/MWKDataStore.h
index d9a277b..9a8af74 100644
--- a/MediaWikiKit/MediaWikiKit/MWKDataStore.h
+++ b/MediaWikiKit/MediaWikiKit/MWKDataStore.h
@@ -24,7 +24,7 @@
 
 @interface MWKDataStore : NSObject
 
-@property (readonly) NSString* basePath;
+@property (readonly, copy, nonatomic) NSString* basePath;
 
 - (instancetype)initWithBasePath:(NSString*)basePath;
 
diff --git a/MediaWikiKit/MediaWikiKit/MWKDataStore.m 
b/MediaWikiKit/MediaWikiKit/MWKDataStore.m
index 49a0841..cc7b972 100644
--- a/MediaWikiKit/MediaWikiKit/MWKDataStore.m
+++ b/MediaWikiKit/MediaWikiKit/MWKDataStore.m
@@ -11,12 +11,18 @@
 
 static NSString* const MWKImageInfoFilename = @"ImageInfo.plist";
 
+@interface MWKDataStore ()
+
+@property (readwrite, copy, nonatomic) NSString* basePath;
+
+@end
+
 @implementation MWKDataStore
 
 - (instancetype)initWithBasePath:(NSString*)basePath {
     self = [self init];
     if (self) {
-        _basePath = [basePath copy];
+        self.basePath = basePath;
     }
     return self;
 }
diff --git a/MediaWikiKit/MediaWikiKit/MWKHistoryEntry.h 
b/MediaWikiKit/MediaWikiKit/MWKHistoryEntry.h
index 34cd119..2993426 100644
--- a/MediaWikiKit/MediaWikiKit/MWKHistoryEntry.h
+++ b/MediaWikiKit/MediaWikiKit/MWKHistoryEntry.h
@@ -22,10 +22,10 @@
 
 @interface MWKHistoryEntry : MWKSiteDataObject
 
-@property (readonly) MWKTitle* title;
-@property (readwrite) NSDate* date;
-@property (readwrite) MWKHistoryDiscoveryMethod discoveryMethod;
-@property (readwrite) int scrollPosition;
+@property (readonly, strong, nonatomic) MWKTitle* title;
+@property (readwrite, strong, nonatomic) NSDate* date;
+@property (readwrite, assign, nonatomic) MWKHistoryDiscoveryMethod 
discoveryMethod;
+@property (readwrite, assign, nonatomic) int scrollPosition;
 
 - (instancetype)initWithTitle:(MWKTitle*)title 
discoveryMethod:(MWKHistoryDiscoveryMethod)discoveryMethod;
 - (instancetype)initWithDict:(NSDictionary*)dict;
diff --git a/MediaWikiKit/MediaWikiKit/MWKHistoryEntry.m 
b/MediaWikiKit/MediaWikiKit/MWKHistoryEntry.m
index d8afc72..fa3e30a 100644
--- a/MediaWikiKit/MediaWikiKit/MWKHistoryEntry.m
+++ b/MediaWikiKit/MediaWikiKit/MWKHistoryEntry.m
@@ -9,15 +9,21 @@
 #import "MediaWikiKit.h"
 #import "WikipediaAppUtils.h"
 
+@interface MWKHistoryEntry ()
+
+@property (readwrite, strong, nonatomic) MWKTitle* title;
+
+@end
+
 @implementation MWKHistoryEntry
 
 - (instancetype)initWithTitle:(MWKTitle*)title 
discoveryMethod:(MWKHistoryDiscoveryMethod)discoveryMethod {
     self = [self initWithSite:title.site];
     if (self) {
-        _title           = title;
-        _date            = [[NSDate alloc] init];
-        _discoveryMethod = discoveryMethod;
-        _scrollPosition  = 0;
+        self.title           = title;
+        self.date            = [[NSDate alloc] init];
+        self.discoveryMethod = discoveryMethod;
+        self.scrollPosition  = 0;
     }
     return self;
 }
@@ -29,7 +35,7 @@
 
     self = [self initWithSite:[MWKSite siteWithDomain:domain 
language:language]];
     if (self) {
-        _title               = [self requiredTitle:@"title" dict:dict];
+        self.title           = [self requiredTitle:@"title" dict:dict];
         self.date            = [self requiredDate:@"date" dict:dict];
         self.discoveryMethod = [MWKHistoryEntry discoveryMethodForString:[self 
requiredString:@"discoveryMethod" dict:dict]];
         self.scrollPosition  = [[self requiredNumber:@"scrollPosition" 
dict:dict] intValue];
diff --git a/MediaWikiKit/MediaWikiKit/MWKHistoryList.h 
b/MediaWikiKit/MediaWikiKit/MWKHistoryList.h
index 52b7da1..4d3dc97 100644
--- a/MediaWikiKit/MediaWikiKit/MWKHistoryList.h
+++ b/MediaWikiKit/MediaWikiKit/MWKHistoryList.h
@@ -13,9 +13,9 @@
 
 @interface MWKHistoryList : MWKDataObject <NSFastEnumeration>
 
-@property (nonatomic, readonly) NSUInteger length;
-@property (nonatomic, readwrite) BOOL dirty;
-@property (nonatomic, readonly) MWKHistoryEntry* mostRecentEntry;
+@property (nonatomic, readonly, assign) NSUInteger length;
+@property (nonatomic, readwrite, assign) BOOL dirty;
+@property (nonatomic, readonly, strong) MWKHistoryEntry* mostRecentEntry;
 
 - (MWKHistoryEntry*)entryAtIndex:(NSUInteger)index;
 - (MWKHistoryEntry*)entryForTitle:(MWKTitle*)title;
diff --git a/MediaWikiKit/MediaWikiKit/MWKHistoryList.m 
b/MediaWikiKit/MediaWikiKit/MWKHistoryList.m
index c2d1952..13b5d24 100644
--- a/MediaWikiKit/MediaWikiKit/MWKHistoryList.m
+++ b/MediaWikiKit/MediaWikiKit/MWKHistoryList.m
@@ -8,29 +8,35 @@
 
 #import "MediaWikiKit.h"
 
-@implementation MWKHistoryList {
-    NSMutableArray* entries;
-    NSMutableDictionary* entriesByTitle;
-}
+@interface MWKHistoryList ()
+
+@property (nonatomic, readwrite, assign) NSUInteger length;
+@property (nonatomic, readwrite, strong) MWKHistoryEntry* mostRecentEntry;
+@property (nonatomic, strong)  NSMutableArray* entries;
+@property (nonatomic, strong) NSMutableDictionary* entriesByTitle;
+
+@end
+
+@implementation MWKHistoryList
 
 - (NSUInteger)length {
-    return [entries count];
+    return [self.entries count];
 }
 
 - (MWKHistoryEntry*)mostRecentEntry {
-    return [entries firstObject];
+    return [self.entries firstObject];
 }
 
 - (MWKHistoryEntry*)entryAtIndex:(NSUInteger)index {
-    return entries[index];
+    return self.entries[index];
 }
 
 - (MWKHistoryEntry*)entryForTitle:(MWKTitle*)title {
-    return entriesByTitle[title];
+    return self.entriesByTitle[title];
 }
 
 - (NSUInteger)indexForEntry:(MWKHistoryEntry*)entry {
-    return [entries indexOfObject:entry];
+    return [self.entries indexOfObject:entry];
 }
 
 - (MWKHistoryEntry*)entryAfterEntry:(MWKHistoryEntry*)entry {
@@ -64,27 +70,27 @@
     MWKHistoryEntry* oldEntry = [self entryForTitle:entry.title];
     if (oldEntry) {
         // Replace the old entry and move to top
-        [entries removeObject:oldEntry];
+        [self.entries removeObject:oldEntry];
     }
-    [entries insertObject:entry atIndex:0];
-    entriesByTitle[entry.title] = entry;
-    _dirty                      = YES;
+    [self.entries insertObject:entry atIndex:0];
+    self.entriesByTitle[entry.title] = entry;
+    self.dirty                       = YES;
 }
 
 - (void)removeEntry:(MWKHistoryEntry*)entry {
     if (entry.title == nil) {
         return;
     }
-    [entries removeObject:entry];
-    [entriesByTitle removeObjectForKey:entry.title];
-    _dirty = YES;
+    [self.entries removeObject:entry];
+    [self.entriesByTitle removeObjectForKey:entry.title];
+    self.dirty = YES;
 }
 
 - (void)removeAllEntries;
 {
-    [entries removeAllObjects];
-    [entriesByTitle removeAllObjects];
-    _dirty = YES;
+    [self.entries removeAllObjects];
+    [self.entriesByTitle removeAllObjects];
+    self.dirty = YES;
 }
 
 #pragma mark - data i/o methods
@@ -92,8 +98,8 @@
 - (instancetype)init {
     self = [super init];
     if (self) {
-        entries        = [[NSMutableArray alloc] init];
-        entriesByTitle = [[NSMutableDictionary alloc] init];
+        self.entries        = [[NSMutableArray alloc] init];
+        self.entriesByTitle = [[NSMutableDictionary alloc] init];
     }
     return self;
 }
@@ -103,14 +109,14 @@
     if (self) {
         NSArray* arr = dict[@"entries"];
         if (arr) {
-            entries = [[NSMutableArray alloc] init];
+            self.entries = [[NSMutableArray alloc] init];
             for (NSDictionary* entryDict in arr) {
                 MWKHistoryEntry* entry = [[MWKHistoryEntry alloc] 
initWithDict:entryDict];
-                [entries addObject:entry];
-                entriesByTitle[entry.title] = entry;
+                [self.entries addObject:entry];
+                self.entriesByTitle[entry.title] = entry;
             }
         }
-        _dirty = NO;
+        self.dirty = NO;
     }
     return self;
 }
@@ -118,18 +124,18 @@
 - (id)dataExport {
     NSMutableArray* array = [[NSMutableArray alloc] init];
 
-    for (MWKHistoryEntry* entry in entries) {
+    for (MWKHistoryEntry* entry in self.entries) {
         [array addObject:[entry dataExport]];
     }
 
-    _dirty = NO;
+    self.dirty = NO;
     return @{@"entries": [NSArray arrayWithArray:array]};
 }
 
 - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state
                                   objects:(__unsafe_unretained id [])stackbuf
                                     count:(NSUInteger)len {
-    return [entries countByEnumeratingWithState:state objects:stackbuf 
count:len];
+    return [self.entries countByEnumeratingWithState:state objects:stackbuf 
count:len];
 }
 
 @end
diff --git a/MediaWikiKit/MediaWikiKit/MWKImage.h 
b/MediaWikiKit/MediaWikiKit/MWKImage.h
index 3040a63..e6a9895 100644
--- a/MediaWikiKit/MediaWikiKit/MWKImage.h
+++ b/MediaWikiKit/MediaWikiKit/MWKImage.h
@@ -9,27 +9,26 @@
 @interface MWKImage : MWKSiteDataObject
 
 // Identifiers
-@property (readonly) MWKSite* site;
-@property (readonly) MWKArticle* article;
+@property (readonly, weak, nonatomic) MWKArticle* article;
 
 // Metadata, static
-@property (readonly) NSString* sourceURL;
-@property (readonly) NSString* extension;
-@property (readonly) NSString* fileName;
-@property (readonly) NSString* fileNameNoSizePrefix;
+@property (readonly, copy, nonatomic) NSString* sourceURL;
+@property (readonly, copy, nonatomic) NSString* extension;
+@property (readonly, copy, nonatomic) NSString* fileName;
+@property (readonly, copy, nonatomic) NSString* fileNameNoSizePrefix;
 
 // Metadata, variable
-@property (copy) NSDate* dateLastAccessed;
-@property (copy) NSDate* dateRetrieved;
-@property (copy) NSString* mimeType;
+@property (copy, nonatomic) NSDate* dateLastAccessed;
+@property (copy, nonatomic) NSDate* dateRetrieved;
+@property (copy, nonatomic) NSString* mimeType;
 
-@property (copy) NSNumber* width;
-@property (copy) NSNumber* height;
+@property (copy, nonatomic) NSNumber* width;
+@property (copy, nonatomic) NSNumber* height;
 - (CGSize)size;
 
 
 // Local storage status
-@property (readonly) BOOL isCached;
+@property (readonly, assign, nonatomic) BOOL isCached;
 
 - (instancetype)initWithArticle:(MWKArticle*)article sourceURL:(NSString*)url;
 - (instancetype)initWithArticle:(MWKArticle*)article dict:(NSDictionary*)dict;
@@ -45,7 +44,7 @@
  *  All focal rects as strings. Calculated via 
"calculateFocalRectsBasedOnFaceDetectionWithImageData"
  * Normally you do not need to access this directly, instead use the methods
  */
-@property (copy, readonly) NSArray* focalRectsInUnitCoordinatesAsStrings;
+@property (readonly, copy, nonatomic) NSArray* 
focalRectsInUnitCoordinatesAsStrings;
 
 /**
  *  Returns the primary focal rect
diff --git a/MediaWikiKit/MediaWikiKit/MWKImage.m 
b/MediaWikiKit/MediaWikiKit/MWKImage.m
index af31202..80c044b 100644
--- a/MediaWikiKit/MediaWikiKit/MWKImage.m
+++ b/MediaWikiKit/MediaWikiKit/MWKImage.m
@@ -9,27 +9,34 @@
 
 @interface MWKImage ()
 
-@property (copy, readwrite) NSArray* focalRectsInUnitCoordinatesAsStrings;
+// Identifiers
+@property (readwrite, weak, nonatomic) MWKArticle* article;
+
+// Metadata, static
+@property (readwrite, copy, nonatomic) NSString* sourceURL;
+@property (readwrite, copy, nonatomic) NSString* extension;
+@property (readwrite, copy, nonatomic) NSString* fileName;
+@property (readwrite, copy, nonatomic) NSString* fileNameNoSizePrefix;
+
+@property (readwrite, assign, nonatomic) BOOL isCached;
+
+@property (readwrite, copy, nonatomic) NSArray* 
focalRectsInUnitCoordinatesAsStrings;
 
 @end
 
 @implementation MWKImage
-@synthesize fileNameNoSizePrefix = _fileNameNoSizePrefix;
+
+#pragma mark - Setup
 
 - (instancetype)initWithArticle:(MWKArticle*)article sourceURL:(NSString*)url {
     self = [super initWithSite:article.site];
     if (self) {
-        _article = article;
+        self.article = article;
 
         // fileNameNoSizePrefix is lazily derived from this property, so be 
careful if _sourceURL needs to be re-set
-        _sourceURL = [url copy];
+        self.sourceURL = url;
 
-        _dateLastAccessed                     = nil;
-        _dateRetrieved                        = nil;
-        _mimeType                             = nil;
-        _width                                = nil;
-        _height                               = nil;
-        _focalRectsInUnitCoordinatesAsStrings = @[];
+        self.focalRectsInUnitCoordinatesAsStrings = @[];
     }
     return self;
 }
@@ -38,12 +45,12 @@
     NSString* sourceURL = [self requiredString:@"sourceURL" dict:dict];
     self = [self initWithArticle:article sourceURL:sourceURL];
     if (self) {
-        _dateLastAccessed                     = [self 
optionalDate:@"dateLastAccessed" dict:dict];
-        _dateRetrieved                        = [self 
optionalDate:@"dateRetrieved" dict:dict];
-        _mimeType                             = [self 
optionalString:@"mimeType" dict:dict];
-        _width                                = [self optionalNumber:@"width" 
dict:dict];
-        _height                               = [self optionalNumber:@"height" 
dict:dict];
-        _focalRectsInUnitCoordinatesAsStrings = dict[@"focalRects"];
+        self.dateLastAccessed                     = [self 
optionalDate:@"dateLastAccessed" dict:dict];
+        self.dateRetrieved                        = [self 
optionalDate:@"dateRetrieved" dict:dict];
+        self.mimeType                             = [self 
optionalString:@"mimeType" dict:dict];
+        self.width                                = [self 
optionalNumber:@"width" dict:dict];
+        self.height                               = [self 
optionalNumber:@"height" dict:dict];
+        self.focalRectsInUnitCoordinatesAsStrings = dict[@"focalRects"];
     }
     return self;
 }
@@ -156,6 +163,8 @@
     return _fileNameNoSizePrefix;
 }
 
+#pragma mark - Import / Export
+
 - (id)dataExport {
     NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
     dict[@"sourceURL"] = self.sourceURL;
@@ -186,14 +195,14 @@
 }
 
 - (void)updateWithData:(NSData*)data {
-    _dateRetrieved    = [[NSDate alloc] init];
-    _dateLastAccessed = [[NSDate alloc] init];
-    _mimeType         = [self getImageMimeTypeForExtension:self.extension];
+    self.dateRetrieved    = [[NSDate alloc] init];
+    self.dateLastAccessed = [[NSDate alloc] init];
+    self.mimeType         = [self getImageMimeTypeForExtension:self.extension];
 
-    if (!_width || !_height) {
+    if (!self.width || !self.height) {
         UIImage* img = [UIImage imageWithData:data];
-        _width  = [NSNumber numberWithInt:img.size.width];
-        _height = [NSNumber numberWithInt:img.size.height];
+        self.width  = [NSNumber numberWithInt:img.size.width];
+        self.height = [NSNumber numberWithInt:img.size.height];
     }
 }
 
@@ -215,7 +224,7 @@
 }
 
 - (void)updateLastAccessed {
-    _dateLastAccessed = [[NSDate alloc] init];
+    self.dateLastAccessed = [[NSDate alloc] init];
 }
 
 - (void)save {
diff --git a/MediaWikiKit/MediaWikiKit/MWKImageInfo.h 
b/MediaWikiKit/MediaWikiKit/MWKImageInfo.h
index e7bd91c..3327ecb 100644
--- a/MediaWikiKit/MediaWikiKit/MWKImageInfo.h
+++ b/MediaWikiKit/MediaWikiKit/MWKImageInfo.h
@@ -17,33 +17,33 @@
 @property (nonatomic, readonly, copy) NSString* canonicalPageTitle;
 
 /// URL pointing at the canonical file associated with this gallery item, e.g. 
@c "//site/.../Some_file_name.extension".
-@property (nonatomic, readonly) NSURL* canonicalFileURL;
+@property (nonatomic, readonly, copy) NSURL* canonicalFileURL;
 
 /// Short description of the image contents (e.g. "John Smith posing for a 
picture").
 @property (nonatomic, readonly, copy) NSString* imageDescription;
 
-@property (nonatomic, readonly) MWKLicense* license;
+@property (nonatomic, readonly, strong) MWKLicense* license;
 
 /// URL pointing to the corresponding file page for the receiver.
-@property (nonatomic, readonly) NSURL* filePageURL;
+@property (nonatomic, readonly, copy) NSURL* filePageURL;
 
 /// URL pointing at the original image (at the uploaded resolution).
-@property (nonatomic, readonly) NSURL* imageURL;
+@property (nonatomic, readonly, copy) NSURL* imageURL;
 
 /// URL pointing at a thumbnail version of the image at @c imageURL.
-@property (nonatomic, readonly) NSURL* imageThumbURL;
+@property (nonatomic, readonly, copy) NSURL* imageThumbURL;
 
 /// Size of the original image.
-@property (nonatomic, readonly) CGSize imageSize;
+@property (nonatomic, readonly, assign) CGSize imageSize;
 
 /// Size of the thumbnail at @c imageThumbURL.
-@property (nonatomic, readonly) CGSize thumbSize;
+@property (nonatomic, readonly, assign) CGSize thumbSize;
 
 /// Name of the entity owning this image.
 @property (nonatomic, readonly, copy) NSString* owner;
 
 /// Value which can be used to associate the receiver with a @c MWKImage.
-@property (nonatomic, readonly) id imageAssociationValue;
+@property (nonatomic, readonly, strong) id imageAssociationValue;
 
 /// Factory method for creating an instance from the output of @c exportData.
 + (instancetype)imageInfoWithExportedData:(NSDictionary*)exportedData;
diff --git a/MediaWikiKit/MediaWikiKit/MWKImageInfo.m 
b/MediaWikiKit/MediaWikiKit/MWKImageInfo.m
index b37c82c..023ebb3 100644
--- a/MediaWikiKit/MediaWikiKit/MWKImageInfo.m
+++ b/MediaWikiKit/MediaWikiKit/MWKImageInfo.m
@@ -19,8 +19,25 @@
 NSString* const MWKImageInfoImageSize             = @"imageSize";
 NSString* const MWKImageInfoThumbSize             = @"thumbSize";
 
+
+@interface MWKImageInfo ()
+
+@property (nonatomic, readwrite, copy) NSString* canonicalPageTitle;
+@property (nonatomic, readwrite, copy) NSURL* canonicalFileURL;
+@property (nonatomic, readwrite, copy) NSString* imageDescription;
+@property (nonatomic, readwrite, strong) MWKLicense* license;
+@property (nonatomic, readwrite, copy) NSURL* filePageURL;
+@property (nonatomic, readwrite, copy) NSURL* imageURL;
+@property (nonatomic, readwrite, copy) NSURL* imageThumbURL;
+@property (nonatomic, readwrite, assign) CGSize imageSize;
+@property (nonatomic, readwrite, assign) CGSize thumbSize;
+@property (nonatomic, readwrite, copy) NSString* owner;
+@property (nonatomic, readwrite, strong) id imageAssociationValue;
+
+@end
+
+
 @implementation MWKImageInfo
-@synthesize imageAssociationValue = _imageAssociationValue;
 
 - (instancetype)initWithCanonicalPageTitle:(NSString*)canonicalPageTitle
                           canonicalFileURL:(NSURL*)canonicalFileURL
@@ -38,16 +55,16 @@
     //NSParameterAssert([imageURL.absoluteString length]);
     self = [super init];
     if (self) {
-        _canonicalPageTitle = [canonicalPageTitle copy];
-        _imageDescription   = [imageDescription copy];
-        _owner              = [owner copy];
-        _license            = license;
-        _canonicalFileURL   = canonicalFileURL;
-        _filePageURL        = filePageURL;
-        _imageURL           = imageURL;
-        _imageThumbURL      = imageThumbURL;
-        _imageSize          = imageSize;
-        _thumbSize          = thumbSize;
+        self.canonicalPageTitle = canonicalPageTitle;
+        self.imageDescription   = imageDescription;
+        self.owner              = owner;
+        self.license            = license;
+        self.canonicalFileURL   = canonicalFileURL;
+        self.filePageURL        = filePageURL;
+        self.imageURL           = imageURL;
+        self.imageThumbURL      = imageThumbURL;
+        self.imageSize          = imageSize;
+        self.thumbSize          = thumbSize;
     }
     return self;
 }
diff --git a/MediaWikiKit/MediaWikiKit/MWKImageList.h 
b/MediaWikiKit/MediaWikiKit/MWKImageList.h
index 9cd780a..9620ded 100644
--- a/MediaWikiKit/MediaWikiKit/MWKImageList.h
+++ b/MediaWikiKit/MediaWikiKit/MWKImageList.h
@@ -13,8 +13,9 @@
 @class MWKImage;
 
 @interface MWKImageList : MWKSiteDataObject <NSFastEnumeration>
-@property (weak, readonly) MWKArticle* article;
-@property (weak, readonly) MWKSection* section;
+
+@property (weak, readonly, nonatomic) MWKArticle* article;
+@property (weak, readonly, nonatomic) MWKSection* section;
 
 - (instancetype)initWithArticle:(MWKArticle*)article 
section:(MWKSection*)section;
 - (instancetype)initWithArticle:(MWKArticle*)article 
section:(MWKSection*)section dict:(NSDictionary*)dict;
diff --git a/MediaWikiKit/MediaWikiKit/MWKImageList.m 
b/MediaWikiKit/MediaWikiKit/MWKImageList.m
index 9e90a51..63d5208 100644
--- a/MediaWikiKit/MediaWikiKit/MWKImageList.m
+++ b/MediaWikiKit/MediaWikiKit/MWKImageList.m
@@ -9,20 +9,28 @@
 #import "MediaWikiKit.h"
 #import "NSString+Extras.h"
 
-@implementation MWKImageList {
-    NSMutableArray* entries;
-    NSMutableDictionary* entriesByURL;
-    NSMutableDictionary* entriesByNameWithoutSize;
-    unsigned long mutationState;
-}
+@interface MWKImageList ()
+
+@property (weak, readwrite, nonatomic) MWKArticle* article;
+@property (weak, readwrite, nonatomic) MWKSection* section;
+
+@property (strong, nonatomic) NSMutableArray* entries;
+@property (strong, nonatomic) NSMutableDictionary* entriesByURL;
+@property (strong, nonatomic) NSMutableDictionary* entriesByNameWithoutSize;
+
+@property (assign, nonatomic) unsigned long mutationState;
+
+@end
+
+@implementation MWKImageList
 
 - (instancetype)initWithSite:(MWKSite*)site {
     self = [super initWithSite:site];
     if (self) {
-        entries                  = [[NSMutableArray alloc] init];
-        mutationState            = 0;
-        entriesByURL             = [[NSMutableDictionary alloc] init];
-        entriesByNameWithoutSize = [[NSMutableDictionary alloc] init];
+        self.entries                  = [[NSMutableArray alloc] init];
+        self.mutationState            = 0;
+        self.entriesByURL             = [[NSMutableDictionary alloc] init];
+        self.entriesByNameWithoutSize = [[NSMutableDictionary alloc] init];
     }
     return self;
 }
@@ -30,8 +38,8 @@
 - (instancetype)initWithArticle:(MWKArticle*)article 
section:(MWKSection*)section {
     self = [self initWithSite:section.site];
     if (self) {
-        _article = article;
-        _section = section;
+        self.article = article;
+        self.section = section;
     }
     return self;
 }
@@ -49,26 +57,26 @@
 - (void)addImageURL:(NSString*)imageURL {
     imageURL = [imageURL wmf_schemelessURL];
 
-    [entries addObject:imageURL];
-    entriesByURL[imageURL] = imageURL;
+    [self.entries addObject:imageURL];
+    self.entriesByURL[imageURL] = imageURL;
 
     NSString* key          = [MWKImage fileNameNoSizePrefix:imageURL];
-    NSMutableArray* byname = entriesByNameWithoutSize[key];
+    NSMutableArray* byname = self.entriesByNameWithoutSize[key];
     if (byname == nil) {
-        byname                        = [[NSMutableArray alloc] init];
-        entriesByNameWithoutSize[key] = byname;
+        byname                             = [[NSMutableArray alloc] init];
+        self.entriesByNameWithoutSize[key] = byname;
     }
     [byname addObject:imageURL];
-    mutationState++;
+    self.mutationState++;
 }
 
 - (NSUInteger)count {
-    return [entries count];
+    return [self.entries count];
 }
 
 - (NSString*)imageURLAtIndex:(NSUInteger)index {
-    if (index < [entries count]) {
-        return entries[index];
+    if (index < [self.entries count]) {
+        return self.entries[index];
     } else {
         return nil;
     }
@@ -92,7 +100,7 @@
         return nil;
     }
     NSString* baseName  = [MWKImage fileNameNoSizePrefix:imageURL];
-    NSMutableArray* arr = entriesByNameWithoutSize[baseName];
+    NSMutableArray* arr = self.entriesByNameWithoutSize[baseName];
 
     if (arr) {
         NSMutableArray* arr2 = [NSMutableArray arrayWithArray:arr];
@@ -156,19 +164,19 @@
 }
 
 - (NSUInteger)indexOfImage:(MWKImage*)image {
-    return [entries indexOfObject:image.sourceURL];
+    return [self.entries indexOfObject:image.sourceURL];
 }
 
 - (BOOL)containsImage:(MWKImage*)image {
-    return [entries containsObject:image.sourceURL];
+    return [self.entries containsObject:image.sourceURL];
 }
 
 - (NSArray*)uniqueLargestVariants {
-    if (!entries || entries.count == 0) {
+    if (!self.entries || self.entries.count == 0) {
         return nil;
     }
-    NSMutableOrderedSet* resultBuilder = [[NSMutableOrderedSet alloc] 
initWithCapacity:entries.count];
-    for (NSString* sourceURL in entries) {
+    NSMutableOrderedSet* resultBuilder = [[NSMutableOrderedSet alloc] 
initWithCapacity:self.entries.count];
+    for (NSString* sourceURL in self.entries) {
         MWKImage* image = [self largestImageVariantForURL:sourceURL 
cachedOnly:NO];
         NSAssert(image, @"Couldn't retrieve image record for image list entry: 
%@", sourceURL);
         [resultBuilder addObject:image];
@@ -177,7 +185,7 @@
 }
 
 - (BOOL)addImageURLIfAbsent:(NSString*)imageURL {
-    if (imageURL && imageURL.length > 0 && ![entries containsObject:imageURL]) 
{
+    if (imageURL && imageURL.length > 0 && ![self.entries 
containsObject:imageURL]) {
         [self addImageURL:imageURL];
         return YES;
     } else {
@@ -188,7 +196,7 @@
 #pragma mark - data i/o
 
 - (id)dataExport {
-    return @{@"entries": entries};
+    return @{@"entries": self.entries};
 }
 
 - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state
@@ -204,7 +212,7 @@
     state->state += count;
 
     state->itemsPtr     = stackbuf;
-    state->mutationsPtr = &mutationState;
+    state->mutationsPtr = &_mutationState;
 
     return count;
 }
diff --git a/MediaWikiKit/MediaWikiKit/MWKLicense.h 
b/MediaWikiKit/MediaWikiKit/MWKLicense.h
index d288b50..75ead01 100644
--- a/MediaWikiKit/MediaWikiKit/MWKLicense.h
+++ b/MediaWikiKit/MediaWikiKit/MWKLicense.h
@@ -11,10 +11,8 @@
 @interface MWKLicense : MWKDataObject
 
 @property (nonatomic, readonly, copy) NSString* code;
-
 @property (nonatomic, readonly, copy) NSString* shortDescription;
-
-@property (nonatomic, readonly) NSURL* URL;
+@property (nonatomic, readonly, copy) NSURL* URL;
 
 + (instancetype)licenseWithExportedData:(NSDictionary*)exportedData;
 
diff --git a/MediaWikiKit/MediaWikiKit/MWKLicense.m 
b/MediaWikiKit/MediaWikiKit/MWKLicense.m
index e6f631d..499c03d 100644
--- a/MediaWikiKit/MediaWikiKit/MWKLicense.m
+++ b/MediaWikiKit/MediaWikiKit/MWKLicense.m
@@ -13,6 +13,14 @@
 static NSString* const MWKLicenseShortDescKey = @"shortDescription";
 static NSString* const MWKLicenseURLKey       = @"URL";
 
+@interface MWKLicense ()
+
+@property (nonatomic, readwrite, copy) NSString* code;
+@property (nonatomic, readwrite, copy) NSString* shortDescription;
+@property (nonatomic, readwrite, copy) NSURL* URL;
+
+@end
+
 @implementation MWKLicense
 
 - (instancetype)initWithCode:(NSString*)code
@@ -20,9 +28,9 @@
                          URL:(NSURL*)URL {
     self = [super init];
     if (self) {
-        _code             = [code copy];
-        _shortDescription = [shortDescription copy];
-        _URL              = URL;
+        self.code             = code;
+        self.shortDescription = shortDescription;
+        self.URL              = URL;
     }
     return self;
 }
diff --git a/MediaWikiKit/MediaWikiKit/MWKProtectionStatus.m 
b/MediaWikiKit/MediaWikiKit/MWKProtectionStatus.m
index f586026..7ef0f2c 100644
--- a/MediaWikiKit/MediaWikiKit/MWKProtectionStatus.m
+++ b/MediaWikiKit/MediaWikiKit/MWKProtectionStatus.m
@@ -8,25 +8,29 @@
 
 #import "MediaWikiKit.h"
 
-@implementation MWKProtectionStatus {
-    NSDictionary* _protection;
-}
+@interface MWKProtectionStatus ()
+
+@property (nonatomic, strong) NSDictionary* protection;
+
+@end
+
+@implementation MWKProtectionStatus
 
 - (instancetype)initWithData:(id)data {
     self = [self init];
     if (self) {
         NSDictionary* wrapper = @{@"protection": data};
-        _protection = [self requiredDictionary:@"protection" dict:wrapper];
+        self.protection = [self requiredDictionary:@"protection" dict:wrapper];
     }
     return self;
 }
 
 - (NSArray*)protectedActions {
-    return [_protection allKeys];
+    return [self.protection allKeys];
 }
 
 - (NSArray*)allowedGroupsForAction:(NSString*)action {
-    return _protection[action];
+    return self.protection[action];
 }
 
 - (BOOL)isEqual:(id)object {
@@ -52,7 +56,7 @@
 }
 
 - (id)dataExport {
-    return _protection;
+    return self.protection;
 }
 
 - (id)copyWithZone:(NSZone*)zone {
diff --git a/MediaWikiKit/MediaWikiKit/MWKRecentSearchEntry.h 
b/MediaWikiKit/MediaWikiKit/MWKRecentSearchEntry.h
index 377c1f0..b6bba67 100644
--- a/MediaWikiKit/MediaWikiKit/MWKRecentSearchEntry.h
+++ b/MediaWikiKit/MediaWikiKit/MWKRecentSearchEntry.h
@@ -10,7 +10,7 @@
 
 @interface MWKRecentSearchEntry : MWKSiteDataObject
 
-@property (readonly) NSString* searchTerm;
+@property (readonly, copy, nonatomic) NSString* searchTerm;
 
 - (instancetype)initWithSite:(MWKSite*)site searchTerm:(NSString*)searchTerm;
 - (instancetype)initWithDict:(NSDictionary*)dict;
diff --git a/MediaWikiKit/MediaWikiKit/MWKRecentSearchEntry.m 
b/MediaWikiKit/MediaWikiKit/MWKRecentSearchEntry.m
index ea962cc..a648355 100644
--- a/MediaWikiKit/MediaWikiKit/MWKRecentSearchEntry.m
+++ b/MediaWikiKit/MediaWikiKit/MWKRecentSearchEntry.m
@@ -8,12 +8,18 @@
 
 #import "MediaWikiKit.h"
 
+@interface MWKRecentSearchEntry ()
+
+@property (readwrite, copy, nonatomic) NSString* searchTerm;
+
+@end
+
 @implementation MWKRecentSearchEntry
 
 - (instancetype)initWithSite:(MWKSite*)site searchTerm:(NSString*)searchTerm {
     self = [self initWithSite:site];
     if (self) {
-        _searchTerm = searchTerm;
+        self.searchTerm = searchTerm;
     }
     return self;
 }
diff --git a/MediaWikiKit/MediaWikiKit/MWKRecentSearchList.h 
b/MediaWikiKit/MediaWikiKit/MWKRecentSearchList.h
index bb46af0..22d5463 100644
--- a/MediaWikiKit/MediaWikiKit/MWKRecentSearchList.h
+++ b/MediaWikiKit/MediaWikiKit/MWKRecentSearchList.h
@@ -12,8 +12,8 @@
 
 @interface MWKRecentSearchList : MWKDataObject
 
-@property (readonly) NSUInteger length;
-@property (readonly) BOOL dirty;
+@property (readonly, nonatomic, assign) NSUInteger length;
+@property (readonly, nonatomic, assign) BOOL dirty;
 
 - (MWKRecentSearchEntry*)entryAtIndex:(NSUInteger)index;
 - (void)addEntry:(MWKRecentSearchEntry*)entry;
diff --git a/MediaWikiKit/MediaWikiKit/MWKRecentSearchList.m 
b/MediaWikiKit/MediaWikiKit/MWKRecentSearchList.m
index 404aa85..9152e34 100644
--- a/MediaWikiKit/MediaWikiKit/MWKRecentSearchList.m
+++ b/MediaWikiKit/MediaWikiKit/MWKRecentSearchList.m
@@ -8,16 +8,22 @@
 
 #import "MediaWikiKit.h"
 
-@implementation MWKRecentSearchList {
-    NSMutableArray* entries;
-}
+@interface MWKRecentSearchList ()
+
+@property (readwrite, nonatomic, assign) NSUInteger length;
+@property (readwrite, nonatomic, assign) BOOL dirty;
+@property (nonatomic, strong) NSMutableArray* entries;
+
+@end
+
+@implementation MWKRecentSearchList
 
 - (instancetype)init {
     self = [super init];
     if (self) {
-        entries = [[NSMutableArray alloc] init];
+        self.entries = [[NSMutableArray alloc] init];
     }
-    _dirty = NO;
+    self.dirty = NO;
     return self;
 }
 
@@ -26,35 +32,35 @@
     if (self) {
         for (NSDictionary* entryDict in dict[@"entries"]) {
             MWKRecentSearchEntry* entry = [[MWKRecentSearchEntry alloc] 
initWithDict:entryDict];
-            [entries addObject:entry];
+            [self.entries addObject:entry];
         }
     }
-    _dirty = NO;
+    self.dirty = NO;
     return self;
 }
 
 - (id)dataExport {
     NSMutableArray* dicts = [[NSMutableArray alloc] init];
-    for (MWKRecentSearchEntry* entry in entries) {
+    for (MWKRecentSearchEntry* entry in self.entries) {
         [dicts addObject:[entry dataExport]];
     }
-    _dirty = NO;
+    self.dirty = NO;
     return @{@"entries": dicts};
 }
 
 - (void)addEntry:(MWKRecentSearchEntry*)entry {
-    NSUInteger oldIndex = [entries indexOfObject:entry];
+    NSUInteger oldIndex = [self.entries indexOfObject:entry];
     if (oldIndex != NSNotFound) {
         // Move to top!
-        [entries removeObjectAtIndex:oldIndex];
+        [self.entries removeObjectAtIndex:oldIndex];
     }
-    [entries insertObject:entry atIndex:0];
-    _dirty = YES;
+    [self.entries insertObject:entry atIndex:0];
+    self.dirty = YES;
     // @todo trim to max?
 }
 
 - (MWKRecentSearchEntry*)entryAtIndex:(NSUInteger)index {
-    return entries[index];
+    return self.entries[index];
 }
 
 @end
diff --git a/MediaWikiKit/MediaWikiKit/MWKSavedPageEntry.h 
b/MediaWikiKit/MediaWikiKit/MWKSavedPageEntry.h
index 0a83564..ab888f4 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSavedPageEntry.h
+++ b/MediaWikiKit/MediaWikiKit/MWKSavedPageEntry.h
@@ -10,8 +10,8 @@
 
 @interface MWKSavedPageEntry : MWKSiteDataObject
 
-@property (readonly) MWKTitle* title;
-@property (readwrite) NSDate* date;
+@property (readonly, strong, nonatomic) MWKTitle* title;
+@property (readwrite, strong, nonatomic) NSDate* date;
 
 - (instancetype)initWithTitle:(MWKTitle*)title;
 - (instancetype)initWithDict:(NSDictionary*)dict;
diff --git a/MediaWikiKit/MediaWikiKit/MWKSavedPageEntry.m 
b/MediaWikiKit/MediaWikiKit/MWKSavedPageEntry.m
index c8b1129..0f424c0 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSavedPageEntry.m
+++ b/MediaWikiKit/MediaWikiKit/MWKSavedPageEntry.m
@@ -8,13 +8,18 @@
 
 #import "MediaWikiKit.h"
 
+@interface MWKSavedPageEntry ()
+
+@property (readwrite, strong, nonatomic) MWKTitle* title;
+
+@end
 @implementation MWKSavedPageEntry
 
 - (instancetype)initWithTitle:(MWKTitle*)title {
     self = [self initWithSite:title.site];
     if (self) {
-        _title = title;
-        _date  = [[NSDate alloc] init];
+        self.title = title;
+        self.date  = [[NSDate alloc] init];
     }
     return self;
 }
@@ -26,7 +31,7 @@
 
     self = [self initWithSite:[MWKSite siteWithDomain:domain 
language:language]];
     if (self) {
-        _title = [self requiredTitle:@"title" dict:dict];
+        self.title = [self requiredTitle:@"title" dict:dict];
     }
     return self;
 }
diff --git a/MediaWikiKit/MediaWikiKit/MWKSavedPageList.h 
b/MediaWikiKit/MediaWikiKit/MWKSavedPageList.h
index 5d3993e..fda336a 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSavedPageList.h
+++ b/MediaWikiKit/MediaWikiKit/MWKSavedPageList.h
@@ -13,8 +13,8 @@
 
 @interface MWKSavedPageList : MWKDataObject <NSFastEnumeration>
 
-@property (readonly) NSUInteger length;
-@property (readonly) BOOL dirty;
+@property (readonly, nonatomic, assign) NSUInteger length;
+@property (readonly, nonatomic, assign) BOOL dirty;
 
 - (MWKSavedPageEntry*)entryAtIndex:(NSUInteger)index;
 - (NSUInteger)indexForEntry:(MWKSavedPageEntry*)entry;
diff --git a/MediaWikiKit/MediaWikiKit/MWKSavedPageList.m 
b/MediaWikiKit/MediaWikiKit/MWKSavedPageList.m
index 5c9b3c0..711b142 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSavedPageList.m
+++ b/MediaWikiKit/MediaWikiKit/MWKSavedPageList.m
@@ -8,21 +8,26 @@
 
 #import "MediaWikiKit.h"
 
-@implementation MWKSavedPageList {
-    NSMutableArray* entries;
-    NSMutableDictionary* entriesByTitle;
-}
+@interface MWKSavedPageList ()
+
+@property (nonatomic, strong) NSMutableArray* entries;
+@property (nonatomic, strong) NSMutableDictionary* entriesByTitle;
+@property (readwrite, nonatomic, assign) BOOL dirty;
+
+@end
+
+@implementation MWKSavedPageList
 
 - (NSUInteger)length {
-    return [entries count];
+    return [self.entries count];
 }
 
 - (MWKSavedPageEntry*)entryAtIndex:(NSUInteger)index {
-    return entries[index];
+    return self.entries[index];
 }
 
 - (MWKSavedPageEntry*)entryForTitle:(MWKTitle*)title {
-    MWKSavedPageEntry* entry = entriesByTitle[title];
+    MWKSavedPageEntry* entry = self.entriesByTitle[title];
     return entry;
 }
 
@@ -32,7 +37,7 @@
 }
 
 - (NSUInteger)indexForEntry:(MWKHistoryEntry*)entry {
-    return [entries indexOfObject:entry];
+    return [self.entries indexOfObject:entry];
 }
 
 #pragma mark - update methods
@@ -40,22 +45,22 @@
 - (void)addEntry:(MWKSavedPageEntry*)entry {
     if ([self entryForTitle:entry.title] == nil) {
         // there can be only one
-        [entries insertObject:entry atIndex:0];
-        entriesByTitle[entry.title] = entry;
-        _dirty                      = YES;
+        [self.entries insertObject:entry atIndex:0];
+        self.entriesByTitle[entry.title] = entry;
+        self.dirty                       = YES;
     }
 }
 
 - (void)removeEntry:(MWKSavedPageEntry*)entry {
-    [entries removeObject:entry];
-    [entriesByTitle removeObjectForKey:entry.title];
-    _dirty = YES;
+    [self.entries removeObject:entry];
+    [self.entriesByTitle removeObjectForKey:entry.title];
+    self.dirty = YES;
 }
 
 - (void)removeAllEntries {
-    [entries removeAllObjects];
-    [entriesByTitle removeAllObjects];
-    _dirty = YES;
+    [self.entries removeAllObjects];
+    [self.entriesByTitle removeAllObjects];
+    self.dirty = YES;
 }
 
 #pragma mark - data i/o methods
@@ -63,8 +68,8 @@
 - (instancetype)init {
     self = [super init];
     if (self) {
-        entries        = [[NSMutableArray alloc] init];
-        entriesByTitle = [[NSMutableDictionary alloc] init];
+        self.entries        = [[NSMutableArray alloc] init];
+        self.entriesByTitle = [[NSMutableDictionary alloc] init];
     }
     return self;
 }
@@ -75,10 +80,10 @@
         NSArray* array = dict[@"entries"];
         for (NSDictionary* entryDict in array) {
             MWKSavedPageEntry* entry = [[MWKSavedPageEntry alloc] 
initWithDict:entryDict];
-            [entries addObject:entry];
-            entriesByTitle[entry.title] = entry;
+            [self.entries addObject:entry];
+            self.entriesByTitle[entry.title] = entry;
         }
-        _dirty = NO;
+        self.dirty = NO;
     }
     return self;
 }
@@ -86,18 +91,18 @@
 - (id)dataExport {
     NSMutableArray* array = [[NSMutableArray alloc] init];
 
-    for (MWKSavedPageEntry* entry in entries) {
+    for (MWKSavedPageEntry* entry in self.entries) {
         [array addObject:[entry dataExport]];
     }
 
-    _dirty = NO;
+    self.dirty = NO;
     return @{@"entries": [NSArray arrayWithArray:array]};
 }
 
 - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state
                                   objects:(__unsafe_unretained id [])stackbuf
                                     count:(NSUInteger)len {
-    return [entries countByEnumeratingWithState:state objects:stackbuf 
count:len];
+    return [self.entries countByEnumeratingWithState:state objects:stackbuf 
count:len];
 }
 
 @end
diff --git a/MediaWikiKit/MediaWikiKit/MWKSection.h 
b/MediaWikiKit/MediaWikiKit/MWKSection.h
index 46484a9..e1bcdb9 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSection.h
+++ b/MediaWikiKit/MediaWikiKit/MWKSection.h
@@ -17,21 +17,21 @@
 
 @interface MWKSection : MWKSiteDataObject
 
-@property (readonly) MWKTitle* title;
-@property (readonly) MWKArticle* article;
+@property (readonly, strong, nonatomic) MWKTitle* title;
+@property (readonly, weak, nonatomic) MWKArticle* article;
 
-@property (readonly) NSNumber* toclevel;      // optional
-@property (readonly) NSNumber* level;         // optional; string in JSON, but 
seems to be number-safe?
-@property (readonly) NSString* line;          // optional; HTML
-@property (readonly) NSString* number;        // optional; can be "1.2.3"
-@property (readonly) NSString* index;         // optional; can be "T-3" for 
transcluded sections
-@property (readonly) MWKTitle* fromtitle; // optional
-@property (readonly) NSString* anchor;        // optional
-@property (readonly) int sectionId;           // required; -> id
-@property (readonly) BOOL references;         // optional; marked by presence 
of key with empty string in JSON
+@property (readonly, copy, nonatomic) NSNumber* toclevel;      // optional
+@property (readonly, copy, nonatomic) NSNumber* level;         // optional; 
string in JSON, but seems to be number-safe?
+@property (readonly, copy, nonatomic) NSString* line;          // optional; 
HTML
+@property (readonly, copy, nonatomic) NSString* number;        // optional; 
can be "1.2.3"
+@property (readonly, copy, nonatomic) NSString* index;         // optional; 
can be "T-3" for transcluded sections
+@property (readonly, strong, nonatomic) MWKTitle* fromtitle; // optional
+@property (readonly, copy, nonatomic) NSString* anchor;        // optional
+@property (readonly, assign, nonatomic) int sectionId;           // required; 
-> id
+@property (readonly, assign, nonatomic) BOOL references;         // optional; 
marked by presence of key with empty string in JSON
 
-@property (readonly) NSString* text;          // may be nil
-@property (readonly) MWKImageList* images;    // ?????
+@property (readonly, copy, nonatomic) NSString* text;          // may be nil
+@property (readonly, strong, nonatomic) MWKImageList* images;    // ?????
 
 - (instancetype)initWithArticle:(MWKArticle*)article dict:(NSDictionary*)dict;
 
diff --git a/MediaWikiKit/MediaWikiKit/MWKSection.m 
b/MediaWikiKit/MediaWikiKit/MWKSection.m
index 30b3e47..6c7fef3 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSection.m
+++ b/MediaWikiKit/MediaWikiKit/MWKSection.m
@@ -8,29 +8,45 @@
 
 #import "MediaWikiKit.h"
 
-@implementation MWKSection {
-    NSString* _text;
-    MWKImageList* _images;
-}
+@interface MWKSection ()
+
+@property (readwrite, strong, nonatomic) MWKTitle* title;
+@property (readwrite, weak, nonatomic) MWKArticle* article;
+
+@property (readwrite, copy, nonatomic) NSNumber* toclevel;      // optional
+@property (readwrite, copy, nonatomic) NSNumber* level;         // optional; 
string in JSON, but seems to be number-safe?
+@property (readwrite, copy, nonatomic) NSString* line;          // optional; 
HTML
+@property (readwrite, copy, nonatomic) NSString* number;        // optional; 
can be "1.2.3"
+@property (readwrite, copy, nonatomic) NSString* index;         // optional; 
can be "T-3" for transcluded sections
+@property (readwrite, strong, nonatomic) MWKTitle* fromtitle; // optional
+@property (readwrite, copy, nonatomic) NSString* anchor;        // optional
+@property (readwrite, assign, nonatomic) int sectionId;           // required; 
-> id
+@property (readwrite, assign, nonatomic) BOOL references;         // optional; 
marked by presence of key with empty string in JSON
+
+@property (readwrite, copy, nonatomic) NSString* text;          // may be nil
+@property (readwrite, strong, nonatomic) MWKImageList* images;    // ?????
+@end
+
+@implementation MWKSection
 
 - (instancetype)initWithArticle:(MWKArticle*)article dict:(NSDictionary*)dict {
     self = [self initWithSite:article.site];
     if (self) {
-        _article = article;
-        _title   = article.title;
+        self.article = article;
+        self.title   = article.title;
 
-        _toclevel   = [self optionalNumber:@"toclevel"   dict:dict];
-        _level      = [self optionalNumber:@"level"      dict:dict];  // may 
be a numeric string
-        _line       = [self optionalString:@"line"       dict:dict];
-        _number     = [self optionalString:@"number"     dict:dict];  // 
deceptively named, this must be a string
-        _index      = [self optionalString:@"index"      dict:dict];  // 
deceptively named, this must be a string
-        _fromtitle  = [self optionalTitle:@"fromtitle"  dict:dict];
-        _anchor     = [self optionalString:@"anchor"     dict:dict];
-        _sectionId  = [[self requiredNumber:@"id"         dict:dict] intValue];
-        _references = ([self optionalString:@"references" dict:dict] != nil);
+        self.toclevel   = [self optionalNumber:@"toclevel"   dict:dict];
+        self.level      = [self optionalNumber:@"level"      dict:dict];  // 
may be a numeric string
+        self.line       = [self optionalString:@"line"       dict:dict];
+        self.number     = [self optionalString:@"number"     dict:dict];  // 
deceptively named, this must be a string
+        self.index      = [self optionalString:@"index"      dict:dict];  // 
deceptively named, this must be a string
+        self.fromtitle  = [self optionalTitle:@"fromtitle"  dict:dict];
+        self.anchor     = [self optionalString:@"anchor"     dict:dict];
+        self.sectionId  = [[self requiredNumber:@"id"         dict:dict] 
intValue];
+        self.references = ([self optionalString:@"references" dict:dict] != 
nil);
 
         // Not present in .plist, loaded separately there
-        _text = [self optionalString:@"text"       dict:dict];
+        self.text = [self optionalString:@"text"       dict:dict];
     }
     return self;
 }
diff --git a/MediaWikiKit/MediaWikiKit/MWKSectionList.h 
b/MediaWikiKit/MediaWikiKit/MWKSectionList.h
index 10fccbc..fc8e276 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSectionList.h
+++ b/MediaWikiKit/MediaWikiKit/MWKSectionList.h
@@ -10,15 +10,30 @@
 
 @interface MWKSectionList : MWKDataObject <NSFastEnumeration>
 
-@property (readonly) MWKArticle* article;
+/**
+ *  Creates a section list and sets the sections to the provided array.
+ *
+ *  @param article  The article to load sections for
+ *  @param sections The sections to load
+ *
+ *  @return The Section List
+ */
+- (instancetype)initWithArticle:(MWKArticle*)article 
sections:(NSArray*)sections;
 
-- (NSUInteger)count;
-
-- (MWKSection*)objectAtIndexedSubscript:(NSUInteger)idx;
-- (void)setSections:(NSArray*)sections;
-
+/**
+ *  Creates a section list and loads sections from disks
+ *
+ *  @param article The article to load sections for
+ *
+ *  @return The Section List
+ */
 - (instancetype)initWithArticle:(MWKArticle*)article;
 
+@property (readonly, weak, nonatomic) MWKArticle* article;
+
+- (NSUInteger) count;
+- (MWKSection*)objectAtIndexedSubscript:(NSUInteger)idx;
+
 - (void)save;
 
 @end
diff --git a/MediaWikiKit/MediaWikiKit/MWKSectionList.m 
b/MediaWikiKit/MediaWikiKit/MWKSectionList.m
index 57a184b..ebca4c0 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSectionList.m
+++ b/MediaWikiKit/MediaWikiKit/MWKSectionList.m
@@ -9,28 +9,39 @@
 #import "MWKSectionList_Private.h"
 #import "MediaWikiKit.h"
 
-@implementation MWKSectionList {
-    NSMutableArray* _sections;
-    unsigned long mutationState;
-}
+@interface MWKSectionList ()
+
+@property (readwrite, weak, nonatomic) MWKArticle* article;
+@property (strong, nonatomic) NSMutableArray* sections;
+@property (assign, nonatomic) unsigned long mutationState;
+
+@end
+
+@implementation MWKSectionList
 
 - (NSUInteger)count {
-    return [_sections count];
+    return [self.sections count];
 }
 
 - (MWKSection*)objectAtIndexedSubscript:(NSUInteger)idx {
-    return _sections[idx];
+    return self.sections[idx];
+}
+
+- (instancetype)initWithArticle:(MWKArticle*)article 
sections:(NSArray*)sections {
+    self = [self initWithArticle:article];
+    if (self) {
+        self.sections = [sections mutableCopy];
+    }
+    return self;
 }
 
 - (instancetype)initWithArticle:(MWKArticle*)article {
     self = [self init];
     if (self) {
-        _article      = article;
-        mutationState = 0;
-        if (_sections == nil) {
-            _sections = [NSMutableArray array];
-            [self importSectionsFromDisk];
-        }
+        self.article       = article;
+        self.mutationState = 0;
+        self.sections      = [NSMutableArray array];
+        [self importSectionsFromDisk];
     }
     return self;
 }
@@ -63,12 +74,12 @@
         }
     }@catch (NSException* e) {
         NSLog(@"Failed to import sections at path %@, leaving list empty.", 
path);
-        [_sections removeAllObjects];
+        [self.sections removeAllObjects];
     }
 }
 
 - (void)readAndInsertSection:(int)sectionId {
-    _sections[sectionId] = [self.article.dataStore sectionWithId:sectionId 
article:self.article];
+    self.sections[sectionId] = [self.article.dataStore sectionWithId:sectionId 
article:self.article];
 }
 
 - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state
@@ -84,14 +95,9 @@
     state->state += count;
 
     state->itemsPtr     = stackbuf;
-    state->mutationsPtr = &mutationState;
+    state->mutationsPtr = &_mutationState;
 
     return count;
-}
-
-- (void)setSections:(NSArray*)sections;
-{
-    _sections = [sections mutableCopy];
 }
 
 - (void)save {
diff --git a/MediaWikiKit/MediaWikiKit/MWKSite.h 
b/MediaWikiKit/MediaWikiKit/MWKSite.h
index 647dfc3..f57e3b3 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSite.h
+++ b/MediaWikiKit/MediaWikiKit/MWKSite.h
@@ -11,8 +11,8 @@
 
 @interface MWKSite : NSObject
 
-@property (readonly) NSString* domain;
-@property (readonly) NSString* language;
+@property (readonly, copy, nonatomic) NSString* domain;
+@property (readonly, copy, nonatomic) NSString* language;
 
 - (instancetype)initWithDomain:(NSString*)domain language:(NSString*)language;
 
diff --git a/MediaWikiKit/MediaWikiKit/MWKSite.m 
b/MediaWikiKit/MediaWikiKit/MWKSite.m
index ce2dfdc..aa33a74 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSite.m
+++ b/MediaWikiKit/MediaWikiKit/MWKSite.m
@@ -4,18 +4,41 @@
 #import "MediaWikiKit.h"
 #import "WikipediaAppUtils.h"
 
+@interface MWKSite ()
+
+@property (readwrite, copy, nonatomic) NSString* domain;
+@property (readwrite, copy, nonatomic) NSString* language;
+
+@end
+
 @implementation MWKSite
+
+#pragma mark - Setup
+
++ (MWKSite*)siteWithDomain:(NSString*)domain language:(NSString*)language {
+    static NSMutableDictionary* cachedSites = nil;
+    if (cachedSites == nil) {
+        cachedSites = [[NSMutableDictionary alloc] init];
+    }
+    NSString* key = [NSString stringWithFormat:@"%@:%@", domain, language];
+    MWKSite* site = cachedSites[key];
+    if (site == nil) {
+        site             = [[MWKSite alloc] initWithDomain:domain 
language:language];
+        cachedSites[key] = site;
+    }
+    return site;
+}
 
 - (instancetype)initWithDomain:(NSString*)domain language:(NSString*)language {
     self = [super init];
     if (self) {
-        _domain   = [domain copy];
-        _language = [language copy];
+        self.domain   = domain;
+        self.language = language;
     }
     return self;
 }
 
-#pragma mark - Title methods
+#pragma mark - Title Helpers
 
 - (MWKTitle*)titleWithString:(NSString*)string {
     return [MWKTitle titleWithString:string site:self];
@@ -33,7 +56,7 @@
     }
 }
 
-#pragma mark - NSObject methods
+#pragma mark - NSObject
 
 - (BOOL)isEqual:(id)object {
     if (object == nil) {
@@ -43,23 +66,6 @@
     } else {
         return NO;
     }
-}
-
-#pragma mark - class methods
-
-/// !!!: make this thread safe and test for deadlocks
-+ (MWKSite*)siteWithDomain:(NSString*)domain language:(NSString*)language {
-    static NSMutableDictionary* cachedSites = nil;
-    if (cachedSites == nil) {
-        cachedSites = [[NSMutableDictionary alloc] init];
-    }
-    NSString* key = [NSString stringWithFormat:@"%@:%@", domain, language];
-    MWKSite* site = cachedSites[key];
-    if (site == nil) {
-        site             = [[MWKSite alloc] initWithDomain:domain 
language:language];
-        cachedSites[key] = site;
-    }
-    return site;
 }
 
 - (BOOL)isEqualToSite:(MWKSite*)other {
diff --git a/MediaWikiKit/MediaWikiKit/MWKSiteDataObject.h 
b/MediaWikiKit/MediaWikiKit/MWKSiteDataObject.h
index c42c063..bd9c367 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSiteDataObject.h
+++ b/MediaWikiKit/MediaWikiKit/MWKSiteDataObject.h
@@ -14,7 +14,7 @@
 
 @interface MWKSiteDataObject : MWKDataObject
 
-@property (readonly) MWKSite* site;
+@property (readonly, strong, nonatomic) MWKSite* site;
 
 - (instancetype)initWithSite:(MWKSite*)site;
 
diff --git a/MediaWikiKit/MediaWikiKit/MWKSiteDataObject.m 
b/MediaWikiKit/MediaWikiKit/MWKSiteDataObject.m
index 3654f0b..659f185 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSiteDataObject.m
+++ b/MediaWikiKit/MediaWikiKit/MWKSiteDataObject.m
@@ -8,12 +8,18 @@
 
 #import "MediaWikiKit.h"
 
+@interface MWKSiteDataObject ()
+
+@property (readwrite, strong, nonatomic) MWKSite* site;
+
+@end
+
 @implementation MWKSiteDataObject
 
 - (instancetype)initWithSite:(MWKSite*)site {
     self = [self init];
     if (self) {
-        _site = site;
+        self.site = site;
     }
     return self;
 }
diff --git a/MediaWikiKit/MediaWikiKit/MWKTitle.h 
b/MediaWikiKit/MediaWikiKit/MWKTitle.h
index 31a3542..05f6a3a 100644
--- a/MediaWikiKit/MediaWikiKit/MWKTitle.h
+++ b/MediaWikiKit/MediaWikiKit/MWKTitle.h
@@ -24,62 +24,55 @@
  */
 + (NSString*)normalize:(NSString*)str;
 
-
 /**
  * The site this title belongs to
  */
-@property (readonly) MWKSite* site;
-
-/**
- * Normalized namespace (decoded, no underscores)
- * Warning: not implemented yet
- */
-@property (readonly) NSString* namespace;
+@property (readonly, strong, nonatomic) MWKSite* site;
 
 /**
  * Normalized title component only (decoded, no underscores)
  */
-@property (readonly) NSString* text;
+@property (readonly, copy, nonatomic) NSString* text;
 
 /**
  * Fragment (component after the '#')
  * Warning: fragment may be nil!
  */
-@property (readonly) NSString* fragment;
+@property (readonly, copy, nonatomic) NSString* fragment;
 
 
 /**
  * Full text-normalized namespace+title
  * Decoded, with spaces
  */
-@property (readonly) NSString* prefixedText;
+@property (readonly, copy, nonatomic) NSString* prefixedText;
 
 /**
  * Full DB-normalized namespace+title
  * Decoded, with underscores
  */
-@property (readonly) NSString* prefixedDBKey;
+@property (readonly, copy, nonatomic) NSString* prefixedDBKey;
 
 /**
  * Full URL-normalized namespace+title
  * Encoded, with underscores
  */
-@property (readonly) NSString* prefixedURL;
+@property (readonly, copy, nonatomic) NSString* prefixedURL;
 
 /**
  * URL-normalized fragment, including the # if applicable
  * Always returns a string, may be empty string.
  */
-@property (readonly) NSString* fragmentForURL;
+@property (readonly, copy, nonatomic) NSString* fragmentForURL;
 
 /**
  * Absolute URL to mobile view of this article
  */
-@property (readonly) NSURL* mobileURL;
+@property (readonly, copy, nonatomic) NSURL* mobileURL;
 
 /**
  * Absolute URL to desktop view of this article
  */
-@property (readonly) NSURL* desktopURL;
+@property (readonly, copy, nonatomic) NSURL* desktopURL;
 
 @end
diff --git a/MediaWikiKit/MediaWikiKit/MWKTitle.m 
b/MediaWikiKit/MediaWikiKit/MWKTitle.m
index a30f647..6e05c71 100644
--- a/MediaWikiKit/MediaWikiKit/MWKTitle.m
+++ b/MediaWikiKit/MediaWikiKit/MWKTitle.m
@@ -3,6 +3,21 @@
 
 #import "MediaWikiKit.h"
 
+@interface MWKTitle ()
+
+@property (readwrite, strong, nonatomic) MWKSite* site;
+@property (readwrite, copy, nonatomic) NSString* text;
+@property (readwrite, copy, nonatomic) NSString* fragment;
+@property (readwrite, copy, nonatomic) NSString* prefixedText;
+@property (readwrite, copy, nonatomic) NSString* prefixedDBKey;
+@property (readwrite, copy, nonatomic) NSString* prefixedURL;
+@property (readwrite, copy, nonatomic) NSString* fragmentForURL;
+@property (readwrite, copy, nonatomic) NSURL* mobileURL;
+@property (readwrite, copy, nonatomic) NSURL* desktopURL;
+
+
+@end
+
 @implementation MWKTitle
 
 #pragma mark - Class methods
@@ -21,13 +36,11 @@
 - (instancetype)initWithString:(NSString*)str site:(MWKSite*)site {
     self = [self init];
     if (self) {
-        _site = site;
+        self.site = site;
         NSArray* bits = [str componentsSeparatedByString:@"#"];
-        _text = [MWKTitle normalize:bits[0]];
+        self.text = [MWKTitle normalize:bits[0]];
         if (bits.count > 1) {
-            _fragment = bits[1];
-        } else {
-            _fragment = nil;
+            self.fragment = bits[1];
         }
     }
     return self;
@@ -37,6 +50,7 @@
 
 - (NSString*)namespace {
     // @todo implement namespace detection and normalization
+    // rename the property from a reserved language name
     // doing this right requires some site info
     return nil;
 }
diff --git a/MediaWikiKit/MediaWikiKit/MWKUser.h 
b/MediaWikiKit/MediaWikiKit/MWKUser.h
index e3ad7da..7e6cc99 100644
--- a/MediaWikiKit/MediaWikiKit/MWKUser.h
+++ b/MediaWikiKit/MediaWikiKit/MWKUser.h
@@ -14,9 +14,9 @@
 
 @interface MWKUser : MWKSiteDataObject
 
-@property (readonly) bool anonymous;
-@property (readonly) NSString* name;
-@property (readonly) NSString* gender; // used to format UI messages on-wiki
+@property (readonly, assign, nonatomic) BOOL anonymous;
+@property (readonly, copy, nonatomic) NSString* name;
+@property (readonly, copy, nonatomic) NSString* gender;
 
 - (instancetype)initWithSite:(MWKSite*)site data:(id)data;
 
diff --git a/MediaWikiKit/MediaWikiKit/MWKUser.m 
b/MediaWikiKit/MediaWikiKit/MWKUser.m
index ecb6981..04e27ab 100644
--- a/MediaWikiKit/MediaWikiKit/MWKUser.m
+++ b/MediaWikiKit/MediaWikiKit/MWKUser.m
@@ -8,19 +8,27 @@
 
 #import "MediaWikiKit.h"
 
+@interface MWKUser ()
+
+@property (readwrite, assign, nonatomic) BOOL anonymous;
+@property (readwrite, copy, nonatomic) NSString* name;
+@property (readwrite, copy, nonatomic) NSString* gender;
+
+@end
+
 @implementation MWKUser
 
 - (instancetype)initWithSite:(MWKSite*)site data:(id)data {
     self = [self initWithSite:site];
     if ([data isKindOfClass:[NSNull class]]) {
-        _anonymous = YES;
-        _name      = nil;
-        _gender    = nil;
+        self.anonymous = YES;
+        self.name      = nil;
+        self.gender    = nil;
     } else if ([data isKindOfClass:[NSDictionary class]]) {
         NSDictionary* dict = (NSDictionary*)data;
-        _anonymous = NO;
-        _name      = [self requiredString:@"name"   dict:dict];
-        _gender    = [self requiredString:@"gender" dict:dict];
+        self.anonymous = NO;
+        self.name      = [self requiredString:@"name"   dict:dict];
+        self.gender    = [self requiredString:@"gender" dict:dict];
     } else {
         @throw [NSException exceptionWithName:@"MWKDataObjectException"
                                        reason:@"expected null or user info 
dict, got something else"
diff --git a/MediaWikiKit/MediaWikiKit/MWKUserDataStore.h 
b/MediaWikiKit/MediaWikiKit/MWKUserDataStore.h
index 1b80a70..190f900 100644
--- a/MediaWikiKit/MediaWikiKit/MWKUserDataStore.h
+++ b/MediaWikiKit/MediaWikiKit/MWKUserDataStore.h
@@ -18,10 +18,10 @@
 
 @interface MWKUserDataStore : NSObject
 
-@property (readonly) MWKDataStore* dataStore;
-@property (readonly) MWKHistoryList* historyList;
-@property (readonly) MWKSavedPageList* savedPageList;
-@property (readonly) MWKRecentSearchList* recentSearchList;
+@property (readonly, weak, nonatomic) MWKDataStore* dataStore;
+@property (readonly, strong, nonatomic) MWKHistoryList* historyList;
+@property (readonly, strong, nonatomic) MWKSavedPageList* savedPageList;
+@property (readonly, strong, nonatomic) MWKRecentSearchList* recentSearchList;
 
 - (instancetype)initWithDataStore:(MWKDataStore*)dataStore;
 
diff --git a/MediaWikiKit/MediaWikiKit/MWKUserDataStore.m 
b/MediaWikiKit/MediaWikiKit/MWKUserDataStore.m
index e4c5c84..6acfe09 100644
--- a/MediaWikiKit/MediaWikiKit/MWKUserDataStore.m
+++ b/MediaWikiKit/MediaWikiKit/MWKUserDataStore.m
@@ -8,18 +8,25 @@
 
 #import "MediaWikiKit.h"
 
-@implementation MWKUserDataStore {
-    MWKHistoryList* _historyList;
-    MWKSavedPageList* _savedPageList;
-    MWKRecentSearchList* _recentSearchList;
-}
+@interface MWKUserDataStore ()
+
+@property (readwrite, weak, nonatomic) MWKDataStore* dataStore;
+@property (readwrite, strong, nonatomic) MWKHistoryList* historyList;
+@property (readwrite, strong, nonatomic) MWKSavedPageList* savedPageList;
+@property (readwrite, strong, nonatomic) MWKRecentSearchList* recentSearchList;
+
+@end
+
+@implementation MWKUserDataStore
 
 - (BOOL)save:(NSError**)error {
     BOOL success = YES;
 
     if (_historyList && _historyList.dirty) {
-        success = [self.dataStore saveHistoryList:_historyList error:error];
-        NSAssert(success, @"Error saving history: %@", [*error 
localizedDescription]);
+        if (![self.dataStore saveHistoryList:_historyList error:error]) {
+            NSAssert(NO, @"Error saving history: %@", [*error 
localizedDescription]);
+        }
+        ;
     }
     if (_savedPageList && _savedPageList.dirty) {
         [self.dataStore saveSavedPageList:_savedPageList];
@@ -37,20 +44,15 @@
 
 /// Clear out any currently loaded data and force it to be reloaded on next use
 - (void)reset {
-    _historyList      = nil;
-    _savedPageList    = nil;
-    _recentSearchList = nil;
+    self.historyList      = nil;
+    self.savedPageList    = nil;
+    self.recentSearchList = nil;
 }
 
 - (instancetype)initWithDataStore:(MWKDataStore*)dataStore {
     self = [self init];
     if (self) {
-        _dataStore = dataStore;
-
-        // Load these on demand
-        _historyList      = nil;
-        _savedPageList    = nil;
-        _recentSearchList = nil;
+        self.dataStore = dataStore;
     }
     return self;
 }
diff --git a/Wikipedia/Data/SchemaConverter.h b/Wikipedia/Data/SchemaConverter.h
index dfad96e..c274f30 100644
--- a/Wikipedia/Data/SchemaConverter.h
+++ b/Wikipedia/Data/SchemaConverter.h
@@ -14,9 +14,9 @@
 
 @interface SchemaConverter : NSObject <OldDataSchemaDelegate>
 
-@property OldDataSchemaMigrator* schema;
-@property MWKDataStore* dataStore;
-@property MWKUserDataStore* userDataStore;
+@property (nonatomic, strong) OldDataSchemaMigrator* schema;
+@property (nonatomic, strong) MWKDataStore* dataStore;
+@property (nonatomic, strong) MWKUserDataStore* userDataStore;
 
 - (instancetype)initWithDataStore:(MWKDataStore*)dataStore;
 
diff --git a/Wikipedia/Session/SessionSingleton.m 
b/Wikipedia/Session/SessionSingleton.m
index aaecd3c..84cd049 100644
--- a/Wikipedia/Session/SessionSingleton.m
+++ b/Wikipedia/Session/SessionSingleton.m
@@ -65,8 +65,8 @@
         self.zeroConfigState             = [[ZeroConfigState alloc] init];
         self.zeroConfigState.disposition = false;
 
-        _dataStore     = dataStore;
-        _userDataStore = dataStore.userDataStore;
+        self.dataStore     = dataStore;
+        self.userDataStore = [dataStore userDataStore];
 
         _currentArticleSite = [self lastKnownSite];
 

-- 
To view, visit https://gerrit.wikimedia.org/r/211716
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I4938141e8cdfc76241bafd220d7362c32b55be6c
Gerrit-PatchSet: 1
Gerrit-Project: apps/ios/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Fjalapeno <cfl...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to