Зачем разделять файлы .h и .m?
Исторически в C, когда вы включали файл .h, это было почти буквально эквивалентно вставке файла в файл, который его включал. По сути, все ваши объявления повторялись в каждом файле, который их использовал. Это нормально, в C вы можете повторять объявления сколько хотите, если они не меняются. Однако повторяющиеся определения приведут к множественным копиям функции и общей поломке. Поэтому вы не можете включить весь код модуля, только его объявления.
Я думаю, что Objective-C на самом деле умнее, и вы можете, если хотите, вообще не иметь файлов .m и поместить весь код в файлы .h. Вы также можете определить класс только в .m-файле и не иметь .h-файла, но вы не можете создать такой проект целиком, поскольку ничто не сможет получить доступ к чему-либо еще.
Тем не менее, по-прежнему рекомендуется отделять объявления от определений. Это похоже на меню в ресторане вместо того, чтобы вернуться на кухню и посмотреть, что готовится. Файл .h представляет собой краткое описание того, как другие модули могут использовать содержимое модуля.
Почему некоторые переменные экземпляра имеют свойства, а некоторые нет?
Правильно, отчасти это то, что переменные экземпляра не доступны автоматически другим классам. Свойства по умолчанию есть. Однако не обязательно. Вы можете сделать собственность частной.
Еще одна вещь, которую вы получаете со свойствами - это автоматическое управление памятью. Если вы используете атрибут сохранения, то при назначении значения свойству количество сохраняемых значений увеличивается, а количество сохраняемых значений предыдущего значения (если оно есть) уменьшается. Это очень удобно и позволяет избежать глупостей. Даже если другие классы не обращаются к переменной экземпляра, это полезно. Если вы не используете свойства, вы должны убедиться, что вы выполняете соответствующие инструкции сохранения и выпуска в своих методах экземпляра, чтобы избежать утечки памяти. Есть и другие автоматические варианты поведения, которые вы можете использовать для свойств, например блокировка или копирование.
Наконец, вы можете получить встроенное поведение с атрибутами свойств и ключевым словом @synthesize, но вы также можете отказаться от использования ключевого слова @synthesize и писать собственные методы получения и установки для своих свойств. Они могут делать причудливые вещи, например, обновлять связанные переменные экземпляра всякий раз, когда изменяется свойство.